Merge branch 'master' into bigmerge

avinationmerge
Melanie 2011-11-24 01:16:37 +00:00
commit a8270cb48c
27 changed files with 903 additions and 696 deletions

View File

@ -102,12 +102,28 @@ namespace OpenSim.Framework
bool TryGetScenePresence(UUID agentID, out object scenePresence);
T RequestModuleInterface<T>();
T[] RequestModuleInterfaces<T>();
/// <summary>
/// Register an interface to a region module. This allows module methods to be called directly as
/// well as via events. If there is already a module registered for this interface, it is not replaced
/// (is this the best behaviour?)
/// </summary>
/// <param name="mod"></param>
void RegisterModuleInterface<M>(M mod);
void StackModuleInterface<M>(M mod);
/// <summary>
/// For the given interface, retrieve the region module which implements it.
/// </summary>
/// <returns>null if there is no registered module implementing that interface</returns>
T RequestModuleInterface<T>();
/// <summary>
/// For the given interface, retrieve an array of region modules that implement it.
/// </summary>
/// <returns>an empty array if there are no registered modules implementing that interface</returns>
T[] RequestModuleInterfaces<T>();
// void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback);
ISceneObject DeserializeObject(string representation);

View File

@ -70,7 +70,7 @@ namespace OpenSim
/// <param name="networkInfo"></param>
/// <returns>A configuration that gets passed to modules</returns>
public OpenSimConfigSource LoadConfigSettings(
IConfigSource argvSource, out ConfigSettings configSettings,
IConfigSource argvSource, EnvConfigSource envConfigSource, out ConfigSettings configSettings,
out NetworkServersInfo networkInfo)
{
m_configSettings = configSettings = new ConfigSettings();
@ -195,6 +195,24 @@ namespace OpenSim
// Make sure command line options take precedence
m_config.Source.Merge(argvSource);
IConfig enVars = m_config.Source.Configs["Environment"];
if( enVars != null )
{
string[] env_keys = enVars.GetKeys();
foreach ( string key in env_keys )
{
envConfigSource.AddEnv(key, string.Empty);
}
envConfigSource.LoadEnv();
m_config.Source.Merge(envConfigSource);
m_config.Source.ExpandKeyValues();
}
ReadConfigSettings();
return m_config;

View File

@ -112,6 +112,13 @@ namespace OpenSim
get { return m_clientServers; }
}
protected EnvConfigSource m_EnvConfigSource = new EnvConfigSource();
public EnvConfigSource envConfigSource
{
get { return m_EnvConfigSource; }
}
protected List<IClientNetworkServer> m_clientServers = new List<IClientNetworkServer>();
public uint HttpServerPort
@ -146,7 +153,7 @@ namespace OpenSim
protected virtual void LoadConfigSettings(IConfigSource configSource)
{
m_configLoader = new ConfigurationLoader();
m_config = m_configLoader.LoadConfigSettings(configSource, out m_configSettings, out m_networkServersInfo);
m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
ReadExtraConfigSettings();
}

View File

@ -82,16 +82,9 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
if (engines != null)
{
foreach (IScriptModule engine in engines)
{
if (engine != null)
{
engine.StartProcessing();
}
}
}
foreach (IScriptModule engine in engines)
engine.StartProcessing();
}
public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)

View File

@ -451,7 +451,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
return new T[] { default(T) };
return new T[] {};
}
}

View File

@ -252,7 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
private byte[] m_TextureAnimation;
private byte m_clickAction;
private Color m_color = Color.Black;
private string m_description = String.Empty;
private readonly List<uint> m_lastColliders = new List<uint>();
private int m_linkNum;
@ -331,11 +330,14 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public SceneObjectPart()
{
// It's not necessary to persist this
m_TextureAnimation = Utils.EmptyBytes;
m_particleSystem = Utils.EmptyBytes;
Rezzed = DateTime.UtcNow;
Description = String.Empty;
// Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
// this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
// the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
m_inventory = new SceneObjectPartInventory(this);
}
@ -349,11 +351,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="offsetPosition"></param>
public SceneObjectPart(
UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
Quaternion rotationOffset, Vector3 offsetPosition)
Quaternion rotationOffset, Vector3 offsetPosition) : this()
{
m_name = "Object";
Rezzed = DateTime.UtcNow;
CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
LastOwnerID = CreatorID = OwnerID = ownerID;
UUID = UUID.Random();
@ -368,19 +369,10 @@ namespace OpenSim.Region.Framework.Scenes
Velocity = Vector3.Zero;
AngularVelocity = Vector3.Zero;
Acceleration = Vector3.Zero;
m_TextureAnimation = Utils.EmptyBytes;
m_particleSystem = Utils.EmptyBytes;
// Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
// this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
// 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_inventory = new SceneObjectPartInventory(this);
}
#endregion Constructors
@ -938,19 +930,7 @@ namespace OpenSim.Region.Framework.Scenes
set { m_acceleration = value; }
}
public string Description
{
get { return m_description; }
set
{
m_description = value;
PhysicsActor actor = PhysActor;
if (actor != null)
{
actor.SOPDescription = value;
}
}
}
public string Description { get; set; }
/// <value>
/// Text color.
@ -1595,8 +1575,7 @@ namespace OpenSim.Region.Framework.Scenes
// Basic Physics returns null.. joy joy joy.
if (PhysActor != null)
{
PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info
PhysActor.SOPDescription = this.Description;
PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
PhysActor.SetMaterial(Material);
DoPhysicsPropertyUpdate(RigidBody, true);
PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);

View File

@ -282,8 +282,6 @@ namespace OpenSim.Region.Framework.Scenes
ArrayList ret = new ArrayList();
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
return ret;
foreach (IScriptModule e in engines)
{
@ -397,7 +395,7 @@ namespace OpenSim.Region.Framework.Scenes
private void RestoreSavedScriptState(UUID oldID, UUID newID)
{
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
if (engines.Length == 0) // No engine at all
return;
if (m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID))
@ -437,6 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.ParentGroup.m_savedScriptState[oldID] = newDoc.OuterXml;
}
foreach (IScriptModule e in engines)
{
if (e != null)
@ -445,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes
break;
}
}
m_part.ParentGroup.m_savedScriptState.Remove(oldID);
}
}
@ -1327,7 +1327,7 @@ namespace OpenSim.Region.Framework.Scenes
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
if (engines.Length == 0) // No engine at all
return ret;
Items.LockItemsForRead(true);
@ -1365,7 +1365,7 @@ namespace OpenSim.Region.Framework.Scenes
public void ResumeScripts()
{
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null)
if (engines.Length == 0)
return;

View File

@ -3535,23 +3535,23 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="args">The arguments for the event</param>
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;
if (m_scriptEngines.Length == 0)
return;
m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
}
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 });
}
}
}

View File

@ -48,7 +48,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
public class PhysicsParameters : ISharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[PHYSICS PARAMETERS]";
// private static string LogHeader = "[PHYSICS PARAMETERS]";
private List<Scene> m_scenes = new List<Scene>();
private static bool m_commandsLoaded = false;

View File

@ -160,8 +160,19 @@ namespace OpenSim.Region.Physics.Manager
public abstract bool Selected { set; }
/// <summary>
/// Name of this actor.
/// </summary>
/// <remarks>
/// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or
/// water. This is not a problem due to the formatting of names given by prims and avatars.
/// </remarks>
public string Name { get; protected set; }
/// <summary>
/// This is being used by ODE joint code.
/// </summary>
public string SOPName;
public string SOPDescription;
public abstract void CrossingFailure();

View File

@ -224,15 +224,9 @@ namespace OpenSim.Region.Physics.Manager
return false;
}
public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
{
return;
}
public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
public virtual void UnCombine(PhysicsScene pScene)
{
}
public virtual void UnCombine(PhysicsScene pScene) {}
/// <summary>
/// Queue a raycast against the physics scene.

View File

@ -70,7 +70,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private Vector3 _position;
private d.Vector3 _zeroPosition;
// private d.Matrix3 m_StandUpRotation;
private bool _zeroFlag = false;
private bool m_lastUpdateSent = false;
private Vector3 _velocity;
@ -123,9 +122,6 @@ namespace OpenSim.Region.Physics.OdePlugin
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];
@ -181,7 +177,7 @@ namespace OpenSim.Region.Physics.OdePlugin
parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
m_taintPosition = _position;
m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName);
}
_parent_scene = parent_scene;
@ -204,7 +200,7 @@ namespace OpenSim.Region.Physics.OdePlugin
m_colliderarr[i] = false;
}
CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
//m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
//m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH.ToString());
m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
m_isPhysical = false; // current status: no ODE information exists
@ -212,7 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.AddPhysicsActorTaint(this);
m_name = avName;
Name = avName;
}
public override int PhysicsActorType
@ -269,7 +265,7 @@ namespace OpenSim.Region.Physics.OdePlugin
set
{
flying = value;
// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
// m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying);
}
}
@ -440,7 +436,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
{
m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name);
}
}
}
@ -467,7 +463,7 @@ namespace OpenSim.Region.Physics.OdePlugin
Vector3 SetSize = value;
m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
// m_log.Info("[SIZE]: " + CAPSULE_LENGTH);
// m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH);
// If we reset velocity here, then an avatar stalls when it crosses a border for the first time
// (as the height of the new root agent is set).
@ -477,7 +473,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
{
m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size from Scene on {0}", Name);
}
}
}
@ -529,7 +525,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
// movementVector.Z is zero
// calculate tilt components based on desired amount of tilt and current (snapped) heading.
@ -537,7 +532,7 @@ namespace OpenSim.Region.Physics.OdePlugin
float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
//m_log.Debug("[PHYSICS] changing avatar tilt");
//m_log.Debug("[ODE CHARACTER]: 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);
@ -546,124 +541,6 @@ namespace OpenSim.Region.Physics.OdePlugin
d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
}
/// <summary>
/// This creates the Avatar's physical Surrogate at the position supplied
/// </summary>
/// <param name="npositionX"></param>
/// <param name="npositionY"></param>
/// <param name="npositionZ"></param>
// 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 = _position;
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();
}
//
/// <summary>
/// Uses the capped cyllinder volume formula to calculate the avatar's mass.
/// This may be used in calculations in the scene/scenepresence
@ -774,7 +651,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
{
m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name);
}
// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity);
@ -836,7 +713,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_taintForce += force;
_parent_scene.AddPhysicsActorTaint(this);
//doForce(force);
// If uncommented, things get pushed off world
//
// m_log.Debug("Push!");
@ -852,7 +728,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
{
m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name);
}
//m_lastUpdateSent = false;
}
@ -861,15 +737,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{
}
/// <summary>
/// After all of the forces add up with 'add force' we apply them with doForce
/// </summary>
/// <param name="force"></param>
public void doForce(Vector3 force)
{
d.BodyAddForce(Body, force.X, force.Y, force.Z);
}
public override void SetMomentum(Vector3 momentum)
{
}
@ -878,9 +745,8 @@ namespace OpenSim.Region.Physics.OdePlugin
/// Called from Simulate
/// This is the avatar's movement control + PID Controller
/// </summary>
/// <param name="defects">
/// If there is something wrong with the character (e.g. its position is non-finite)
/// then it is added to this list. The ODE structures associated with it are also destroyed.
/// <param name="defects">The character will be added to this list if there is something wrong (non-finite
/// position or velocity).
/// </param>
internal void Move(List<OdeCharacter> defects)
{
@ -903,12 +769,11 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!localPos.IsFinite())
{
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
m_log.WarnFormat(
"[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.",
localPos, Name);
defects.Add(this);
// _parent_scene.RemoveCharacter(this);
DestroyOdeStructures();
return;
}
@ -1035,26 +900,31 @@ namespace OpenSim.Region.Physics.OdePlugin
if (vec.IsFinite())
{
doForce(vec);
// Apply the total force acting on this avatar
d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
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);
m_log.WarnFormat(
"[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.",
vec, Name);
DestroyOdeStructures();
defects.Add(this);
return;
}
}
/// <summary>
/// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
/// </summary>
internal void UpdatePositionAndVelocity()
/// <param name="defects">The character will be added to this list if there is something wrong (non-finite
/// position or velocity).
/// </param>
internal void UpdatePositionAndVelocity(List<OdeCharacter> defects)
{
// no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
d.Vector3 newPos;
@ -1065,10 +935,12 @@ namespace OpenSim.Region.Physics.OdePlugin
catch (NullReferenceException)
{
bad = true;
_parent_scene.BadCharacter(this);
defects.Add(this);
newPos = 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);
m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);
return;
}
// kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
@ -1136,6 +1008,123 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
/// <summary>
/// This creates the Avatar's physical Surrogate in ODE at the position supplied
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="npositionX"></param>
/// <param name="npositionY"></param>
/// <param name="npositionZ"></param>
/// <param name="tensor"></param>
private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor)
{
int dAMotorEuler = 1;
// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
if (CAPSULE_LENGTH <= 0)
{
m_log.Warn("[ODE CHARACTER]: 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("[ODE CHARACTER]: 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 = _position;
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();
_parent_scene.geom_name_map[Shell] = Name;
_parent_scene.actor_name_map[Shell] = this;
}
/// <summary>
/// Cleanup the things we use in the scene.
/// </summary>
@ -1148,7 +1137,7 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <summary>
/// Used internally to destroy the ODE structures associated with this character.
/// </summary>
private void DestroyOdeStructures()
internal void DestroyOdeStructures()
{
// destroy avatar capsule and related ODE data
if (Amotor != IntPtr.Zero)
@ -1159,13 +1148,12 @@ namespace OpenSim.Region.Physics.OdePlugin
}
//kill the Geometry
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
if (Body != IntPtr.Zero)
{
//kill the body
d.BodyDestroy(Body);
Body = IntPtr.Zero;
}
@ -1173,6 +1161,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{
d.GeomDestroy(Shell);
_parent_scene.geom_name_map.Remove(Shell);
_parent_scene.actor_name_map.Remove(Shell);
Shell = IntPtr.Zero;
}
}
@ -1261,7 +1251,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// FIXME: This is not a good solution since it's subject to a race condition if a force is another
// thread sets a new force while we're in this loop (since it could be obliterated by
// m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force.
doForce(m_taintForce);
d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z);
}
m_taintForce = Vector3.Zero;
@ -1277,15 +1267,13 @@ namespace OpenSim.Region.Physics.OdePlugin
// 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 - "
m_log.Warn("[ODE CHARACTER]: re-creating the following avatar ODE data for " + Name + ", 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;
CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor);
_parent_scene.AddCharacter(this);
}
else
@ -1301,17 +1289,19 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
{
// m_log.DebugFormat("[PHYSICS]: Changing capsule size");
// m_log.DebugFormat(
// "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}",
// CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name);
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);
DestroyOdeStructures();
float prevCapsule = CAPSULE_LENGTH;
CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
//m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
d.BodyDestroy(Body);
d.GeomDestroy(Shell);
AvatarGeomAndBodyCreation(
CreateOdeStructures(
_position.X,
_position.Y,
_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
@ -1319,13 +1309,10 @@ namespace OpenSim.Region.Physics.OdePlugin
// As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't
// appear to stall initial region crossings when done here. Being done for consistency.
// 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 - "
m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - "
+ (Shell==IntPtr.Zero ? "Shell ":"")
+ (Body==IntPtr.Zero ? "Body ":"")
+ (Amotor==IntPtr.Zero ? "Amotor ":""));

View File

@ -184,7 +184,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_lastUpdateSent;
public IntPtr Body = IntPtr.Zero;
public String Name { get; private set; }
private Vector3 _target_velocity;
private d.Mass pMass;
@ -273,7 +272,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_taintadd = true;
_parent_scene.AddPhysicsActorTaint(this);
// don't do .add() here; old geoms get recycled with the same hash
}
public override int PhysicsActorType
@ -857,7 +855,7 @@ namespace OpenSim.Region.Physics.OdePlugin
m_MeshToTriMeshMap[mesh] = _triMeshData;
}
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
if (prim_geom == IntPtr.Zero)
@ -1380,7 +1378,7 @@ Console.WriteLine("CreateGeom:");
{
if (((_size.X / 2f) > 0f))
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
//Console.WriteLine(" CreateGeom 1");
@ -1394,7 +1392,7 @@ Console.WriteLine("CreateGeom:");
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
//Console.WriteLine(" CreateGeom 2");
@ -1409,7 +1407,7 @@ Console.WriteLine("CreateGeom:");
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
//Console.WriteLine(" CreateGeom 3");
@ -1424,7 +1422,7 @@ Console.WriteLine("CreateGeom:");
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
//Console.WriteLine(" CreateGeom 4");
@ -1577,17 +1575,17 @@ Console.WriteLine(" JointCreateFixed");
{
// string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
// int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
m_targetSpace = tempspace;
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _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);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
d.SpaceAdd(m_targetSpace, prim_geom);
}
}
@ -1978,7 +1976,7 @@ Console.WriteLine(" JointCreateFixed");
if (d.SpaceQuery(m_targetSpace, prim_geom))
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
// _parent_scene.waitForSpaceUnlock(m_targetSpace);
d.SpaceRemove(m_targetSpace, prim_geom);
}

File diff suppressed because it is too large Load Diff

View File

@ -759,33 +759,33 @@ namespace OpenSim.Region.RegionCombinerModule
{
}
/// <summary>
/// TODO:
/// </summary>
/// <param name="rdata"></param>
public void UnCombineRegion(RegionData rdata)
{
lock (m_regions)
{
if (m_regions.ContainsKey(rdata.RegionId))
{
// uncombine root region and virtual regions
}
else
{
foreach (RegionConnections r in m_regions.Values)
{
foreach (RegionData rd in r.ConnectedRegions)
{
if (rd.RegionId == rdata.RegionId)
{
// uncombine virtual region
}
}
}
}
}
}
// /// <summary>
// /// TODO:
// /// </summary>
// /// <param name="rdata"></param>
// public void UnCombineRegion(RegionData rdata)
// {
// lock (m_regions)
// {
// if (m_regions.ContainsKey(rdata.RegionId))
// {
// // uncombine root region and virtual regions
// }
// else
// {
// foreach (RegionConnections r in m_regions.Values)
// {
// foreach (RegionData rd in r.ConnectedRegions)
// {
// if (rd.RegionId == rdata.RegionId)
// {
// // uncombine virtual region
// }
// }
// }
// }
// }
// }
// Create a set of infinite borders around the whole aabb of the combined island.
private void AdjustLargeRegionBounds()

View File

@ -87,12 +87,26 @@ namespace OpenSim.Services.Connectors
public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion)
{
string uri = region.ServerURI + "region/" + thisRegion.RegionID + "/";
//m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
// m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
WebRequest HelloNeighbourRequest = WebRequest.Create(uri);
HelloNeighbourRequest.Method = "POST";
HelloNeighbourRequest.ContentType = "application/json";
HelloNeighbourRequest.Timeout = 10000;
WebRequest helloNeighbourRequest;
try
{
helloNeighbourRequest = WebRequest.Create(uri);
}
catch (Exception e)
{
m_log.WarnFormat(
"[NEIGHBOUR SERVICE CONNCTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}",
uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
return false;
}
helloNeighbourRequest.Method = "POST";
helloNeighbourRequest.ContentType = "application/json";
helloNeighbourRequest.Timeout = 10000;
// Fill it in
OSDMap args = null;
@ -102,38 +116,48 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message);
m_log.WarnFormat(
"[NEIGHBOUR SERVICE CONNCTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}",
thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
return false;
}
// Add the regionhandle of the destination region
args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString());
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
UTF8Encoding str = new UTF8Encoding();
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message);
m_log.WarnFormat(
"[NEIGHBOUR SERVICE CONNCTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}",
thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
return false;
}
Stream os = null;
try
{ // send the Post
HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
os = HelloNeighbourRequest.GetRequestStream();
helloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
os = helloNeighbourRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
//m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
}
catch (Exception ex)
catch (Exception e)
{
m_log.InfoFormat("[REST COMMS]: Unable to send HelloNeighbour to {0}: {1}", region.RegionName, ex.Message);
m_log.WarnFormat(
"[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}",
thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
return false;
}
finally
@ -148,10 +172,12 @@ namespace OpenSim.Services.Connectors
StreamReader sr = null;
try
{
WebResponse webResponse = HelloNeighbourRequest.GetResponse();
WebResponse webResponse = helloNeighbourRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post");
m_log.DebugFormat(
"[REST COMMS]: Null reply on DoHelloNeighbourCall post from {0} to {1}",
thisRegion.RegionName, region.RegionName);
}
sr = new StreamReader(webResponse.GetResponseStream());
@ -160,9 +186,12 @@ namespace OpenSim.Services.Connectors
//m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
}
catch (Exception ex)
catch (Exception e)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message);
m_log.WarnFormat(
"[NEIGHBOUR SERVICE CONNCTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}",
region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace);
return false;
}
finally
@ -172,8 +201,6 @@ namespace OpenSim.Services.Connectors
}
return true;
}
}
}

View File

@ -334,7 +334,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
// Make the remote storage request
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl);
// Simian does not require the asset ID to be in the URL because it's in the post data.
// By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
HttpWebResponse response = MultipartForm.Post(request, postParameters);
using (Stream responseStream = response.GetResponseStream())

View File

@ -109,11 +109,13 @@ namespace OpenSim.Tests
// Prepare call to ConfigurationLoader.LoadConfigSettings()
ConfigurationLoader cl = new ConfigurationLoader();
IConfigSource argvSource = new IniConfigSource();
EnvConfigSource envConfigSource = new EnvConfigSource();
argvSource.AddConfig("Startup").Set("inifile", mainIniFile);
ConfigSettings configSettings;
NetworkServersInfo networkInfo;
OpenSimConfigSource source = cl.LoadConfigSettings(argvSource, out configSettings, out networkInfo);
OpenSimConfigSource source = cl.LoadConfigSettings(argvSource, envConfigSource,
out configSettings, out networkInfo);
// Remove default config
config = source.Source.Configs["Startup"];

View File

@ -41,6 +41,8 @@ namespace pCampBot
/// </remarks>
public class GrabbingBehaviour : IBehaviour
{
public string Name { get { return "Grabbing"; } }
public void Action(Bot bot)
{
Dictionary<UUID, Primitive> objects = bot.Objects;

View File

@ -42,6 +42,8 @@ namespace pCampBot
/// </remarks>
public class PhysicsBehaviour : IBehaviour
{
public string Name { get { return "Physics"; } }
private string[] talkarray;
public PhysicsBehaviour()

View File

@ -0,0 +1,75 @@
/*
* 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.Linq;
using System.Reflection;
using log4net;
using OpenMetaverse;
using pCampBot.Interfaces;
namespace pCampBot
{
/// <summary>
/// Teleport to a random region on the grid.
/// </summary>
public class TeleportBehaviour : IBehaviour
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Name { get { return "Teleport"; } }
public void Action(Bot bot)
{
Random rng = bot.Manager.Rng;
GridRegion[] knownRegions;
lock (bot.Manager.RegionsKnown)
{
if (bot.Manager.RegionsKnown.Count == 0)
{
m_log.DebugFormat(
"[TELEPORT BEHAVIOUR]: Ignoring teleport action for {0} since no regions are known yet", bot.Name);
return;
}
knownRegions = bot.Manager.RegionsKnown.Values.ToArray();
}
Simulator sourceRegion = bot.Client.Network.CurrentSim;
GridRegion destRegion = knownRegions[rng.Next(knownRegions.Length)];
Vector3 destPosition = new Vector3(rng.Next(255), rng.Next(255), 50);
m_log.DebugFormat(
"[TELEPORT BEHAVIOUR]: Teleporting {0} from {1} {2} to {3} {4}",
bot.Name, sourceRegion.Name, bot.Client.Self.SimPosition, destRegion.Name, destPosition);
bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition);
}
}
}

View File

@ -49,8 +49,15 @@ namespace pCampBot
public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events
public BotManager BotManager { get; private set; }
private IConfig startupConfig; // bot config, passed from BotManager
/// <summary>
/// Bot manager.
/// </summary>
public BotManager Manager { get; private set; }
/// <summary>
/// Bot config, passed from BotManager.
/// </summary>
private IConfig startupConfig;
/// <summary>
/// Behaviours implemented by this bot.
@ -132,7 +139,7 @@ namespace pCampBot
Password = password;
LoginUri = loginUri;
BotManager = bm;
Manager = bm;
startupConfig = bm.Config;
readconfig();
@ -218,7 +225,19 @@ namespace pCampBot
{
MakeDefaultAppearance(wear);
}
Client.Self.Jump(true);
// Extract nearby region information.
Client.Grid.GridRegion += Manager.Grid_GridRegion;
uint xUint, yUint;
Utils.LongToUInts(Client.Network.CurrentSim.Handle, out xUint, out yUint);
ushort minX, minY, maxX, maxY;
minX = (ushort)Math.Min(0, xUint - 5);
minY = (ushort)Math.Min(0, yUint - 5);
maxX = (ushort)(xUint + 5);
maxY = (ushort)(yUint + 5);
Client.Grid.RequestMapBlocks(GridLayerType.Terrain, minX, minY, maxX, maxY, false);
}
else
{
@ -472,13 +491,13 @@ namespace pCampBot
private void GetTexture(UUID textureID)
{
lock (BotManager.AssetsReceived)
lock (Manager.AssetsReceived)
{
// Don't request assets more than once.
if (BotManager.AssetsReceived.ContainsKey(textureID))
if (Manager.AssetsReceived.ContainsKey(textureID))
return;
BotManager.AssetsReceived[textureID] = false;
Manager.AssetsReceived[textureID] = false;
Client.Assets.RequestImage(textureID, ImageType.Normal, Asset_TextureCallback_Texture);
}
}
@ -490,8 +509,8 @@ namespace pCampBot
public void Asset_ReceivedCallback(AssetDownload transfer, Asset asset)
{
lock (BotManager.AssetsReceived)
BotManager.AssetsReceived[asset.AssetID] = true;
lock (Manager.AssetsReceived)
Manager.AssetsReceived[asset.AssetID] = true;
// if (wear == "save")
// {

View File

@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using OpenMetaverse;
@ -48,9 +49,24 @@ namespace pCampBot
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Command console
/// </summary>
protected CommandConsole m_console;
/// <summary>
/// Created bots, whether active or inactive.
/// </summary>
protected List<Bot> m_lBot;
protected Random somthing = new Random(Environment.TickCount);
/// <summary>
/// Random number generator.
/// </summary>
public Random Rng { get; private set; }
/// <summary>
/// Overall configuration.
/// </summary>
public IConfig Config { get; private set; }
/// <summary>
@ -58,12 +74,19 @@ namespace pCampBot
/// </summary>
public Dictionary<UUID, bool> AssetsReceived { get; private set; }
/// <summary>
/// The regions that we know about.
/// </summary>
public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; }
/// <summary>
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
/// </summary>
public BotManager()
{
Rng = new Random(Environment.TickCount);
AssetsReceived = new Dictionary<UUID, bool>();
RegionsKnown = new Dictionary<ulong, GridRegion>();
m_console = CreateConsole();
MainConsole.Instance = m_console;
@ -93,8 +116,13 @@ namespace pCampBot
"Shutdown bots and exit",
HandleShutdown);
m_console.Commands.AddCommand("bot", false, "show status",
"show status",
m_console.Commands.AddCommand("bot", false, "show regions",
"show regions",
"Show regions known to bots",
HandleShowRegions);
m_console.Commands.AddCommand("bot", false, "show bots",
"show bots",
"Shows the status of all bots",
HandleShowStatus);
@ -123,19 +151,26 @@ namespace pCampBot
Array.ForEach<string>(
cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b));
List<IBehaviour> behaviours = new List<IBehaviour>();
// Hard-coded for now
if (behaviourSwitches.Contains("p"))
behaviours.Add(new PhysicsBehaviour());
if (behaviourSwitches.Contains("g"))
behaviours.Add(new GrabbingBehaviour());
if (behaviourSwitches.Contains("t"))
behaviours.Add(new TeleportBehaviour());
MainConsole.Instance.OutputFormat(
"[BOT MANAGER]: Bots configured for behaviours {0}",
string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray()));
for (int i = 0; i < botcount; i++)
{
string lastName = string.Format("{0}_{1}", lastNameStem, i);
List<IBehaviour> behaviours = new List<IBehaviour>();
// Hard-coded for now
if (behaviourSwitches.Contains("p"))
behaviours.Add(new PhysicsBehaviour());
if (behaviourSwitches.Contains("g"))
behaviours.Add(new GrabbingBehaviour());
StartBot(this, behaviours, firstName, lastName, password, loginUri);
}
}
@ -240,17 +275,33 @@ namespace pCampBot
});
}
private void HandleShowRegions(string module, string[] cmd)
{
string outputFormat = "{0,-30} {1, -20} {2, -5} {3, -5}";
MainConsole.Instance.OutputFormat(outputFormat, "Name", "Handle", "X", "Y");
lock (RegionsKnown)
{
foreach (GridRegion region in RegionsKnown.Values)
{
MainConsole.Instance.OutputFormat(
outputFormat, region.Name, region.RegionHandle, region.X, region.Y);
}
}
}
private void HandleShowStatus(string module, string[] cmd)
{
string outputFormat = "{0,-30} {1,-14}";
MainConsole.Instance.OutputFormat(outputFormat, "Name", "Status");
string outputFormat = "{0,-30} {1, -30} {2,-14}";
MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status");
lock (m_lBot)
{
foreach (Bot pb in m_lBot)
{
MainConsole.Instance.OutputFormat(
outputFormat, pb.Name, (pb.IsConnected ? "Connected" : "Disconnected"));
outputFormat,
pb.Name, pb.Client.Network.CurrentSim.Name, pb.IsConnected ? "Connected" : "Disconnected");
}
}
}
@ -274,5 +325,24 @@ namespace pCampBot
// if (newbots > 0)
// addbots(newbots);
// }
internal void Grid_GridRegion(object o, GridRegionEventArgs args)
{
lock (RegionsKnown)
{
GridRegion newRegion = args.Region;
if (RegionsKnown.ContainsKey(newRegion.RegionHandle))
{
return;
}
else
{
m_log.DebugFormat(
"[BOT MANAGER]: Adding {0} {1} to known regions", newRegion.Name, newRegion.RegionHandle);
RegionsKnown[newRegion.RegionHandle] = newRegion;
}
}
}
}
}

View File

@ -31,6 +31,15 @@ namespace pCampBot.Interfaces
{
public interface IBehaviour
{
/// <summary>
/// Name of this behaviour.
/// </summary>
string Name { get; }
/// <summary>
/// Action to take when this behaviour is invoked.
/// </summary>
/// <param name="bot"></param>
void Action(Bot bot);
}
}

View File

@ -111,7 +111,7 @@ namespace pCampBot
" -firstname first name for the bots\n" +
" -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" +
" -password password for the bots\n" +
" -b, behaviours behaviours for bots. Current options p (physics), g (grab). Comma separated, e.g. p,g. Default is p",
" -b, behaviours behaviours for bots. Current options p (physics), g (grab), t (teleport). Comma separated, e.g. p,g. Default is p",
" -wear set appearance folder to load from (default: no)\n" +
" -h, -help show this message"
);

Binary file not shown.

View File

@ -231,13 +231,6 @@
;; server to send mail through.
; emailmodule = DefaultEmailModule
;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true
;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
;; by scripts have changed.
; DeleteScriptsOnStartup = true
[SMTP]
;; The SMTP server enabled the email module to send email to external
;; destinations.
@ -571,6 +564,13 @@
;; Stack size per thread created
; ThreadStackSize = 262144
;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true
;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false
;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the
;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used
;; by scripts have changed.
; DeleteScriptsOnStartup = true
;; 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