diff --git a/LibreMetaverse/AgentManager.cs b/LibreMetaverse/AgentManager.cs
index e50f6b32..66125b98 100644
--- a/LibreMetaverse/AgentManager.cs
+++ b/LibreMetaverse/AgentManager.cs
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
- * Copyright (c) 2019-2024, Sjofn LLC
+ * Copyright (c) 2019-2025, Sjofn LLC
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -1398,8 +1398,7 @@ namespace OpenMetaverse
// go up the hierarchy trying to find the root prim
while (p != null && p.ParentID != 0)
{
- Avatar av;
- if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(p.ParentID, out av))
+ if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(p.ParentID, out var av))
{
p = av;
fullPosition += p.Position;
@@ -1437,8 +1436,8 @@ namespace OpenMetaverse
{
if (sittingOn != 0)
{
- Primitive parent;
- if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
+ if (Client.Network.CurrentSim != null
+ && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out var parent))
{
return relativeRotation * parent.Rotation;
}
diff --git a/LibreMetaverse/AgentManagerMovement.cs b/LibreMetaverse/AgentManagerMovement.cs
index d885952c..fed22d44 100644
--- a/LibreMetaverse/AgentManagerMovement.cs
+++ b/LibreMetaverse/AgentManagerMovement.cs
@@ -532,7 +532,7 @@ namespace OpenMetaverse
{
if (!Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(Client.Self.SittingOn, out var parent))
{
- Logger.Log("Attempted TurnToward but parent prim is not in dictionary", Helpers.LogLevel.Warning, Client);
+ Logger.Log("Attempted TurnToward but parent prim is not found", Helpers.LogLevel.Warning, Client);
return false;
}
diff --git a/LibreMetaverse/AvatarManager.cs b/LibreMetaverse/AvatarManager.cs
index ee68cf6a..7591d7d6 100644
--- a/LibreMetaverse/AvatarManager.cs
+++ b/LibreMetaverse/AvatarManager.cs
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
- * Copyright (c) 2021-2022, Sjofn LLC.
+ * Copyright (c) 2021-2025, Sjofn LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -581,11 +581,11 @@ namespace OpenMetaverse
/// Callback giving results when fetching AgentProfile
///
/// If the request was successful
- /// AgentProfile result
+ /// AgentProfile result
public delegate void AgentProfileCallback(bool success, AgentProfileMessage profile);
#endregion Delegates
- private GridClient Client;
+ private readonly GridClient Client;
///
/// Represents other avatars
@@ -1036,10 +1036,13 @@ namespace OpenMetaverse
signaledAnimations.Add(animation);
}
- Avatar avatar = e.Simulator.ObjectsAvatars.Find(avi => avi.ID == data.Sender.ID);
- if (avatar != null)
+ var kvp = e.Simulator.ObjectsAvatars.SingleOrDefault(
+ avi => avi.Value.ID == data.Sender.ID);
+ if (kvp.Value != null)
{
- avatar.Animations = signaledAnimations;
+ var av = kvp.Value;
+ av.Animations = signaledAnimations;
+ e.Simulator.ObjectsAvatars.TryUpdate(kvp.Key, av, kvp.Value);
}
else
{
@@ -1092,9 +1095,11 @@ namespace OpenMetaverse
{
if (appearance.AttachmentBlock != null && appearance.AttachmentBlock.Length > 0)
{
- Avatar av = simulator.ObjectsAvatars.Find((Avatar a) => a.ID == appearance.Sender.ID);
- if (av != null)
+ var kv = simulator.ObjectsAvatars.SingleOrDefault(
+ a => a.Value.ID == appearance.Sender.ID);
+ if (kv.Value != null)
{
+ var av = kv.Value;
av.Attachments = new List();
foreach (var block in appearance.AttachmentBlock)
{
@@ -1106,37 +1111,42 @@ namespace OpenMetaverse
}
childCount = av.ChildCount = av.Attachments.Count;
+
+ simulator.ObjectsAvatars.TryUpdate(kv.Key, av, kv.Value);
}
}
}
- if (appearance.Sender.ID != Client.Self.AgentID) // We need to ignore this for avatar self-appearance.
- // The data in this packet is incorrect, and only the
- // mesh bake CAP response can be treated as fully reliable.
+ // We need to ignore this for avatar self-appearance.
+ // The data in this packet is incorrect, and only the
+ // mesh bake CAP response can be treated as fully reliable.
+ if (appearance.Sender.ID == Client.Self.AgentID) { return; }
+
+ var kvp = simulator.ObjectsAvatars.SingleOrDefault(
+ a => a.Value.ID == appearance.Sender.ID);
+ if (kvp.Value != null)
{
- Avatar av = simulator.ObjectsAvatars.Find((Avatar a) => a.ID == appearance.Sender.ID);
- if (av != null)
- {
- av.Textures = textureEntry;
- av.VisualParameters = visualParams.ToArray();
- av.AppearanceVersion = appearanceVersion;
- av.COFVersion = COFVersion;
- av.AppearanceFlags = appearanceFlags;
- av.HoverHeight = hoverHeight;
+ var av = kvp.Value;
+ av.Textures = textureEntry;
+ av.VisualParameters = visualParams.ToArray();
+ av.AppearanceVersion = appearanceVersion;
+ av.COFVersion = COFVersion;
+ av.AppearanceFlags = appearanceFlags;
+ av.HoverHeight = hoverHeight;
- }
-
- OnAvatarAppearance(new AvatarAppearanceEventArgs(simulator,
- appearance.Sender.ID,
- appearance.Sender.IsTrial,
- defaultTexture,
- faceTextures,
- visualParams,
- appearanceVersion,
- COFVersion,
- appearanceFlags,
- childCount));
+ simulator.ObjectsAvatars.TryUpdate(kvp.Key, av, kvp.Value);
}
+
+ OnAvatarAppearance(new AvatarAppearanceEventArgs(simulator,
+ appearance.Sender.ID,
+ appearance.Sender.IsTrial,
+ defaultTexture,
+ faceTextures,
+ visualParams,
+ appearanceVersion,
+ COFVersion,
+ appearanceFlags,
+ childCount));
}
}
diff --git a/LibreMetaverse/ObjectManager.cs b/LibreMetaverse/ObjectManager.cs
index 77dd92fa..b206fdfc 100644
--- a/LibreMetaverse/ObjectManager.cs
+++ b/LibreMetaverse/ObjectManager.cs
@@ -2015,11 +2015,18 @@ namespace OpenMetaverse
{
if (Client.Settings.OBJECT_TRACKING)
{
- Primitive prim = sim.ObjectsPrimitives.Find(p => p.ID == primID);
- if (prim != null)
+ var kvp = sim.ObjectsPrimitives.SingleOrDefault(
+ p => p.Value.ID == primID);
+ if (kvp.Value != null)
{
- prim.MediaVersion = response.Version;
- prim.FaceMedia = response.FaceMedia;
+ Primitive prim = kvp.Value;
+ if (prim != null)
+ {
+ prim.MediaVersion = response.Version;
+ prim.FaceMedia = response.FaceMedia;
+ }
+
+ sim.ObjectsPrimitives.TryUpdate(kvp.Key, prim, kvp.Value);
}
}
@@ -2481,9 +2488,7 @@ namespace OpenMetaverse
case PCode.NewTree:
case PCode.Prim:
- bool isNewObject;
- lock (simulator.ObjectsPrimitives.Dictionary)
- isNewObject = !simulator.ObjectsPrimitives.ContainsKey(block.ID);
+ bool isNewObject = !simulator.ObjectsPrimitives.ContainsKey(block.ID);
Primitive prim = GetPrimitive(simulator, block.ID, block.FullID);
@@ -2587,9 +2592,7 @@ namespace OpenMetaverse
#region Avatar
case PCode.Avatar:
- bool isNewAvatar;
- lock (simulator.ObjectsAvatars.Dictionary)
- isNewAvatar = !simulator.ObjectsAvatars.ContainsKey(block.ID);
+ bool isNewAvatar = !simulator.ObjectsAvatars.ContainsKey(block.ID);
// Update some internals if this is our avatar
if (block.FullID == Client.Self.AgentID && simulator == Client.Network.CurrentSim)
@@ -2878,9 +2881,7 @@ namespace OpenMetaverse
#endregion Relevance check
- bool isNew;
- lock (simulator.ObjectsPrimitives.Dictionary)
- isNew = !simulator.ObjectsPrimitives.ContainsKey(LocalID);
+ bool isNew = !simulator.ObjectsPrimitives.ContainsKey(LocalID);
Primitive prim = GetPrimitive(simulator, LocalID, FullID);
@@ -3113,10 +3114,11 @@ namespace OpenMetaverse
foreach (var odb in update.ObjectData)
{
uint localID = odb.ID;
+ uint crc = odb.CRC;
if (cachedPrimitives)
{
- if (!simulator.DataPool.NeedsRequest(localID, odb.CRC))
+ if (!simulator.DataPool.NeedsRequest(localID, crc))
{
continue;
}
@@ -3147,71 +3149,75 @@ namespace OpenMetaverse
}
OnKillObjects(new KillObjectsEventArgs(e.Simulator, killed));
+ List removeAvatars = new List();
+ List removePrims = new List();
- lock (simulator.ObjectsPrimitives.Dictionary)
+ if (Client.Settings.OBJECT_TRACKING)
{
- List removeAvatars = new List();
- List removePrims = new List();
-
- if (Client.Settings.OBJECT_TRACKING)
+ foreach (var odb in kill.ObjectData)
{
- uint localID;
- foreach (var odb in kill.ObjectData)
+ var localID = odb.ID;
+
+ if (simulator.ObjectsPrimitives.ContainsKey(localID))
{
- localID = odb.ID;
+ removePrims.Add(localID);
+ }
- if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(localID))
- removePrims.Add(localID);
-
- foreach (var prim in simulator.ObjectsPrimitives.Dictionary.Where(prim => prim.Value.ParentID == localID))
+ foreach (var prim in simulator.ObjectsPrimitives)
+ {
+ if (prim.Value.ParentID == localID)
{
OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
removePrims.Add(prim.Key);
}
}
}
+ }
- if (Client.Settings.AVATAR_TRACKING)
+ if (Client.Settings.AVATAR_TRACKING)
+ {
+ uint localID;
+ foreach (var odb in kill.ObjectData)
{
- lock (simulator.ObjectsAvatars.Dictionary)
+ localID = odb.ID;
+
+ if (simulator.ObjectsAvatars.ContainsKey(localID))
{
- uint localID;
- foreach (var odb in kill.ObjectData)
- {
- localID = odb.ID;
+ removeAvatars.Add(localID);
+ }
- if (simulator.ObjectsAvatars.Dictionary.ContainsKey(localID))
- removeAvatars.Add(localID);
+ List rootPrims = new List();
- List rootPrims = new List();
+ foreach (var prim in simulator.ObjectsPrimitives
+ .Where(prim => prim.Value.ParentID == localID))
+ {
+ OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
+ removePrims.Add(prim.Key);
+ rootPrims.Add(prim.Key);
+ }
- foreach (var prim in simulator.ObjectsPrimitives.Dictionary.Where(prim => prim.Value.ParentID == localID))
- {
- OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
- removePrims.Add(prim.Key);
- rootPrims.Add(prim.Key);
- }
-
- foreach (var prim in simulator.ObjectsPrimitives.Dictionary.Where(prim => rootPrims.Contains(prim.Value.ParentID)))
- {
- OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
- removePrims.Add(prim.Key);
- }
- }
-
- //Do the actual removing outside the loops but still inside the lock.
- //This safely prevents the collection from being modified during a loop.
- foreach (uint removeID in removeAvatars)
- simulator.ObjectsAvatars.Dictionary.Remove(removeID);
+ foreach (var prim in simulator.ObjectsPrimitives
+ .Where(prim => rootPrims.Contains(prim.Value.ParentID)))
+ {
+ OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
+ removePrims.Add(prim.Key);
}
}
- if (Client.Settings.CACHE_PRIMITIVES)
+ foreach (uint removeID in removeAvatars)
{
- simulator.DataPool.ReleasePrims(removePrims);
+ simulator.ObjectsAvatars.TryRemove(removeID, out _);
}
- foreach (uint removeID in removePrims)
- simulator.ObjectsPrimitives.Dictionary.Remove(removeID);
+ }
+
+ if (Client.Settings.CACHE_PRIMITIVES)
+ {
+ simulator.DataPool.ReleasePrims(removePrims);
+ }
+
+ foreach (uint removeID in removePrims)
+ {
+ simulator.ObjectsPrimitives.TryRemove(removeID, out _);
}
}
@@ -3262,17 +3268,19 @@ namespace OpenMetaverse
if (Client.Settings.OBJECT_TRACKING)
{
- Primitive findPrim = simulator.ObjectsPrimitives.Find(
- prim => prim.ID == props.ObjectID);
-
- if (findPrim != null)
+ if (simulator.UUIDToLocalID.TryGetValue(props.ObjectID, out var localID))
{
- OnObjectPropertiesUpdated(new ObjectPropertiesUpdatedEventArgs(simulator, findPrim, props));
-
- lock (simulator.ObjectsPrimitives.Dictionary)
+ if (simulator.ObjectsPrimitives.TryGetValue(localID, out var findPrim))
{
- if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(findPrim.LocalID))
- simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties = props;
+ if (findPrim != null)
+ {
+ OnObjectPropertiesUpdated(new ObjectPropertiesUpdatedEventArgs(simulator, findPrim, props));
+
+ if (simulator.ObjectsPrimitives.TryGetValue(findPrim.LocalID, out var primitive))
+ {
+ primitive.Properties = props;
+ }
+ }
}
}
}
@@ -3312,18 +3320,21 @@ namespace OpenMetaverse
if (Client.Settings.OBJECT_TRACKING)
{
- Primitive findPrim = simulator.ObjectsPrimitives.Find(
- prim => prim.ID == op.ObjectData.ObjectID);
-
- if (findPrim != null)
+ if (simulator.UUIDToLocalID.TryGetValue(props.ObjectID, out var localID))
{
- lock (simulator.ObjectsPrimitives.Dictionary)
+ if (simulator.ObjectsPrimitives.TryGetValue(localID, out var findPrim))
{
- if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(findPrim.LocalID))
+ if (findPrim != null)
{
- if (simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties == null)
- simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties = new Primitive.ObjectProperties();
- simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties.SetFamilyProperties(props);
+ if (simulator.ObjectsPrimitives.TryGetValue(findPrim.LocalID, out var prim))
+ {
+ if (prim.Properties == null)
+ {
+ prim.Properties = new Primitive.ObjectProperties();
+ }
+
+ prim.Properties.SetFamilyProperties(props);
+ }
}
}
}
@@ -3370,12 +3381,9 @@ namespace OpenMetaverse
{
foreach (var prop in msg.ObjectPhysicsProperties)
{
- lock (simulator.ObjectsPrimitives.Dictionary)
+ if (simulator.ObjectsPrimitives.TryGetValue(prop.LocalID, out var primitive))
{
- if (simulator.ObjectsPrimitives.Dictionary.TryGetValue(prop.LocalID, out var primitive))
- {
- primitive.PhysicsProps = prop;
- }
+ primitive.PhysicsProps = prop;
}
}
}
@@ -3620,40 +3628,37 @@ namespace OpenMetaverse
{
if (Client.Settings.OBJECT_TRACKING)
{
- lock (simulator.ObjectsPrimitives.Dictionary)
+ if (simulator.ObjectsPrimitives.TryGetValue(localID, out var prim))
{
- if (simulator.ObjectsPrimitives.Dictionary.TryGetValue(localID, out var prim))
- {
- return prim;
- }
- else
- {
- if (!createIfMissing) { return null; }
- if (Client.Settings.CACHE_PRIMITIVES)
- {
- prim = simulator.DataPool.MakePrimitive(localID);
- }
- else
- {
- prim = new Primitive
- {
- LocalID = localID,
- RegionHandle = simulator.Handle
- };
- }
- prim.ActiveClients++;
- prim.ID = fullID;
-
- simulator.ObjectsPrimitives.Dictionary[localID] = prim;
-
- return prim;
- }
+ return prim;
}
+
+ if (!createIfMissing) {return null;}
+
+ if (Client.Settings.CACHE_PRIMITIVES)
+ {
+ prim = simulator.DataPool.MakePrimitive(localID);
+ }
+ else
+ {
+ prim = new Primitive
+ {
+ LocalID = localID,
+ RegionHandle = simulator.Handle
+ };
+ }
+
+ prim.ActiveClients++;
+ prim.ID = fullID;
+
+ prim = simulator.ObjectsPrimitives.GetOrAdd(localID, prim);
+
+ simulator.UUIDToLocalID.AddOrUpdate(prim.ID, prim.LocalID, (uuid, u) => prim.LocalID);
+
+ return prim;
}
- else
- {
- return new Primitive();
- }
+
+ return new Primitive();
}
///
@@ -3665,31 +3670,27 @@ namespace OpenMetaverse
///
protected Avatar GetAvatar(Simulator simulator, uint localID, UUID fullID)
{
- if (Client.Settings.AVATAR_TRACKING)
- {
- lock (simulator.ObjectsAvatars.Dictionary)
- {
- if (simulator.ObjectsAvatars.Dictionary.TryGetValue(localID, out var avatar))
- {
- return avatar;
- }
-
- avatar = new Avatar
- {
- LocalID = localID,
- ID = fullID,
- RegionHandle = simulator.Handle
- };
-
- simulator.ObjectsAvatars.Dictionary[localID] = avatar;
-
- return avatar;
- }
- }
- else
+ if (!Client.Settings.AVATAR_TRACKING)
{
return new Avatar();
}
+
+ if (simulator.ObjectsAvatars.TryGetValue(localID, out var avatar))
+ {
+ return avatar;
+ }
+
+ avatar = new Avatar
+ {
+ LocalID = localID,
+ ID = fullID,
+ RegionHandle = simulator.Handle
+ };
+
+ simulator.ObjectsAvatars[localID] = avatar;
+
+ return avatar;
+
}
#endregion Object Tracking Link
@@ -3712,68 +3713,62 @@ namespace OpenMetaverse
float adjSeconds = seconds * sim.Stats.Dilation;
// Iterate through all of this region's avatars
- sim.ObjectsAvatars.ForEach(
- delegate(Avatar avatar)
+ foreach (var avatar in sim.ObjectsAvatars)
+ {
+ #region Linear Motion
+ if (avatar.Value.Acceleration != Vector3.Zero)
{
- #region Linear Motion
+ avatar.Value.Velocity += avatar.Value.Acceleration * adjSeconds;
+ }
+
+ if (avatar.Value.Velocity != Vector3.Zero)
+ {
+ avatar.Value.Position += (avatar.Value.Velocity) * adjSeconds;
+ }
+ #endregion Linear Motion
+ }
+
+ // Iterate through all the simulator's primitives
+
+ foreach (var prim in sim.ObjectsPrimitives)
+ {
+ if (prim.Value.Joint == JointType.Invalid)
+ {
+ Vector3 angVel = prim.Value.AngularVelocity;
+ float omega = angVel.LengthSquared();
+
+ if (omega > 0.00001f)
+ {
+ omega = (float)Math.Sqrt(omega);
+ float angle = omega * adjSeconds;
+ angVel *= 1.0f / omega;
+ Quaternion dQ = Quaternion.CreateFromAxisAngle(angVel, angle);
+
+ prim.Value.Rotation *= dQ;
+ }
+
// Only do movement interpolation (extrapolation) when there is a non-zero velocity but
// no acceleration
- if (avatar.Acceleration != Vector3.Zero && avatar.Velocity == Vector3.Zero)
+ if (prim.Value.Acceleration != Vector3.Zero && prim.Value.Velocity == Vector3.Zero)
{
- avatar.Position += (avatar.Velocity + avatar.Acceleration *
- (0.5f * (adjSeconds - HAVOK_TIMESTEP))) * adjSeconds;
- avatar.Velocity += avatar.Acceleration * adjSeconds;
+ prim.Value.Position += (prim.Value.Velocity + prim.Value.Acceleration *
+ (0.5f * (adjSeconds - HAVOK_TIMESTEP))) * adjSeconds;
+ prim.Value.Velocity += prim.Value.Acceleration * adjSeconds;
}
- #endregion Linear Motion
}
- );
-
- // Iterate through all of this region's primitives
- sim.ObjectsPrimitives.ForEach(
- delegate(Primitive prim)
+ else if (prim.Value.Joint == JointType.Hinge)
{
- if (prim.Joint == JointType.Invalid)
- {
- #region Angular Velocity
- Vector3 angVel = prim.AngularVelocity;
- float omega = angVel.LengthSquared();
-
- if (omega > 0.00001f)
- {
- omega = (float)Math.Sqrt(omega);
- float angle = omega * adjSeconds;
- angVel *= 1.0f / omega;
- Quaternion dQ = Quaternion.CreateFromAxisAngle(angVel, angle);
-
- prim.Rotation *= dQ;
- }
- #endregion Angular Velocity
-
- #region Linear Motion
- // Only do movement interpolation (extrapolation) when there is a non-zero velocity but
- // no acceleration
- if (prim.Acceleration != Vector3.Zero && prim.Velocity == Vector3.Zero)
- {
- prim.Position += (prim.Velocity + prim.Acceleration *
- (0.5f * (adjSeconds - HAVOK_TIMESTEP))) * adjSeconds;
- prim.Velocity += prim.Acceleration * adjSeconds;
- }
- #endregion Linear Motion
- }
- else if (prim.Joint == JointType.Hinge)
- {
- //FIXME: Hinge movement extrapolation
- }
- else if (prim.Joint == JointType.Point)
- {
- //FIXME: Point movement extrapolation
- }
- else
- {
- Logger.Log("Unhandled joint type " + prim.Joint, Helpers.LogLevel.Warning, Client);
- }
+ //FIXME: Hinge movement extrapolation
}
- );
+ else if (prim.Value.Joint == JointType.Point)
+ {
+ //FIXME: Point movement extrapolation
+ }
+ else
+ {
+ Logger.Log($"Unhandled joint type {prim.Value.Joint}", Helpers.LogLevel.Warning, Client);
+ }
+ }
}
// Make sure the last interpolated time is always updated
@@ -4026,7 +4021,7 @@ namespace OpenMetaverse
public Primitive Prim { get; }
///
- /// Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class
+ /// Construct a new instance of the ObjectPropertiesUpdatedEventArgs class
///
/// The simulator the object is located
/// The Primitive
@@ -4063,7 +4058,8 @@ namespace OpenMetaverse
}
}
- /// Provides primitive data containing updated location, velocity, rotation, textures for the event
+ /// Provides primitive data containing updated location, velocity, rotation, textures for the
+ /// event
/// The event occurs when the simulator sends updated location, velocity, rotation, etc
///
public class TerseObjectUpdateEventArgs : EventArgs
diff --git a/LibreMetaverse/Simulator.cs b/LibreMetaverse/Simulator.cs
index 5514dfad..09603d9a 100644
--- a/LibreMetaverse/Simulator.cs
+++ b/LibreMetaverse/Simulator.cs
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
- * Copyright (c) 2022, Sjofn LLC.
+ * Copyright (c) 2022-2025, Sjofn LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -186,7 +186,7 @@ namespace OpenMetaverse
///
/// Outgoing bytes per second
///
- /// It would be nice to have this claculated on the fly, but
+ /// It would be nice to have this calculated on the fly, but
/// this is far, far easier
public int OutgoingBPS;
/// Time last ping was sent
@@ -271,7 +271,7 @@ namespace OpenMetaverse
public uint SizeY;
/// The current version of software this simulator is running
public string SimVersion = string.Empty;
- /// Human readable name given to the simulator
+ /// Human-readable name given to the simulator
public string Name = string.Empty;
/// A 64x64 grid of parcel coloring values. The values stored
/// in this array are of the type
@@ -383,18 +383,19 @@ namespace OpenMetaverse
///
/// A thread-safe dictionary containing avatars in a simulator
///
- public LockingDictionary ObjectsAvatars = new LockingDictionary();
+ public ConcurrentDictionary ObjectsAvatars = new ConcurrentDictionary();
///
/// A thread-safe dictionary containing primitives in a simulator
///
- public LockingDictionary ObjectsPrimitives = new LockingDictionary();
+ public ConcurrentDictionary ObjectsPrimitives = new ConcurrentDictionary();
///
/// A thread-safe dictionary which can be used to find the local ID of a specified UUID.
///
public ConcurrentDictionary UUIDToLocalID = new ConcurrentDictionary();
+
public readonly TerrainPatch[] Terrain;
public readonly Vector2[] WindSpeeds;
@@ -463,16 +464,20 @@ namespace OpenMetaverse
#region Properties
/// The IP address and port of the server
- public IPEndPoint IPEndPoint { get { return remoteEndPoint; } }
+ public IPEndPoint IPEndPoint => remoteEndPoint;
+
/// Whether there is a working connection to the simulator or
/// not
- public bool Connected { get { return connected; } }
+ public bool Connected => connected;
+
/// Coarse locations of avatars in this simulator
- public LockingDictionary AvatarPositions { get { return avatarPositions; } }
+ public LockingDictionary AvatarPositions => avatarPositions;
+
/// AvatarPositions key representing TrackAgent target
- public UUID PreyID { get { return preyID; } }
+ public UUID PreyID => preyID;
+
/// Indicates if UDP connection to the sim is fully established
- public bool HandshakeComplete { get { return handshakeComplete; } }
+ public bool HandshakeComplete => handshakeComplete;
#endregion Properties
@@ -499,10 +504,12 @@ namespace OpenMetaverse
/// Indicates if UDP connection to the sim is fully established
internal bool handshakeComplete;
- private NetworkManager Network;
- private Queue InBytes, OutBytes;
+ private readonly NetworkManager Network;
+ private readonly Queue InBytes;
+ private readonly Queue OutBytes;
+
// ACKs that are queued up to be sent to the simulator
- private ConcurrentQueue PendingAcks = new ConcurrentQueue();
+ private readonly ConcurrentQueue PendingAcks = new ConcurrentQueue();
private Timer AckTimer;
private Timer PingTimer;
private Timer StatsTimer;
@@ -552,7 +559,7 @@ namespace OpenMetaverse
internal bool _DownloadingParcelMap = false;
- private ManualResetEvent GotUseCircuitCodeAck = new ManualResetEvent(false);
+ private readonly ManualResetEvent GotUseCircuitCodeAck = new ManualResetEvent(false);
#endregion Internal/Private Members
///
@@ -1384,11 +1391,11 @@ namespace OpenMetaverse
public sealed class IncomingPacketIDCollection
{
- readonly uint[] _items;
- HashSet hashSet;
- int first;
- int next;
- int capacity;
+ private readonly uint[] _items;
+ private readonly HashSet hashSet;
+ private int first;
+ private int next;
+ private readonly int capacity;
public IncomingPacketIDCollection(int capacity)
{
@@ -1519,8 +1526,7 @@ namespace OpenMetaverse
var dict = PrimCache;
lock (dict)
{
- Primitive prim;
- if (!dict.TryGetValue(localID, out prim) || prim.IsAttachment)
+ if (!dict.TryGetValue(localID, out var prim) || prim.IsAttachment)
{
dict[localID] = prim = new Primitive { RegionHandle = Handle, LocalID = localID };
}
@@ -1544,8 +1550,7 @@ namespace OpenMetaverse
{
foreach (var u in removePrims)
{
- Primitive prim;
- if (PrimCache.TryGetValue(u, out prim)) prim.ActiveClients--;
+ if (PrimCache.TryGetValue(u, out var prim)) prim.ActiveClients--;
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Agent/BotsCommand.cs b/Programs/examples/TestClient/Commands/Agent/BotsCommand.cs
index e61f8f9b..4390593f 100644
--- a/Programs/examples/TestClient/Commands/Agent/BotsCommand.cs
+++ b/Programs/examples/TestClient/Commands/Agent/BotsCommand.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
namespace OpenMetaverse.TestClient
@@ -48,22 +49,14 @@ namespace OpenMetaverse.TestClient
lock (Client.Network.Simulators)
{
- foreach (var sim in Client.Network.Simulators)
+ foreach (var av in from sim in Client.Network.Simulators
+ from kvp in sim.ObjectsAvatars
+ where kvp.Value != null select kvp.Value into av
+ where !m_AgentList.ContainsKey(av.ID) select av)
{
- sim.ObjectsAvatars.ForEach(
- delegate(Avatar av)
- {
- lock (m_AgentList)
- {
- if (!m_AgentList.ContainsKey(av.ID))
- {
- result.AppendLine();
- result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3} LocalID: {4}) Is Probably a bot",
- av.Name, av.GroupName, av.Position, av.ID, av.LocalID);
- }
- }
- }
- );
+ result.AppendLine();
+ result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3} LocalID: {4}) Is Probably a bot",
+ av.Name, av.GroupName, av.Position, av.ID, av.LocalID);
}
}
diff --git a/Programs/examples/TestClient/Commands/Agent/TouchCommand.cs b/Programs/examples/TestClient/Commands/Agent/TouchCommand.cs
index 3497d18c..70edcffa 100644
--- a/Programs/examples/TestClient/Commands/Agent/TouchCommand.cs
+++ b/Programs/examples/TestClient/Commands/Agent/TouchCommand.cs
@@ -1,3 +1,5 @@
+using System.Linq;
+
namespace OpenMetaverse.TestClient
{
public class TouchCommand: Command
@@ -11,25 +13,25 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
- UUID target;
-
if (args.Length != 1)
- return "Usage: touch UUID";
-
- if (UUID.TryParse(args[0], out target))
{
- Primitive targetPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find(
- prim => prim.ID == target
- );
-
- if (targetPrim != null)
- {
- Client.Self.Touch(targetPrim.LocalID);
- return "Touched prim " + targetPrim.LocalID;
- }
+ return "Usage: touch UUID";
}
- return "Couldn't find a prim to touch with UUID " + args[0];
- }
+ if (!UUID.TryParse(args[0], out var target))
+ {
+ return $"{args[0]} is not a valid UUID";
+ }
+ var targetPrim = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(prim => prim.Value.ID == target);
+
+ if (targetPrim.Value == null)
+ {
+ return $"Couldn't find an object to touch with UUID {args[0]}";
+ }
+
+ Client.Self.Touch(targetPrim.Value.LocalID);
+ return $"Touched object {targetPrim.Value.LocalID}";
+
+ }
}
}
diff --git a/Programs/examples/TestClient/Commands/Agent/WhoCommand.cs b/Programs/examples/TestClient/Commands/Agent/WhoCommand.cs
index 2be3e1e1..736892b9 100644
--- a/Programs/examples/TestClient/Commands/Agent/WhoCommand.cs
+++ b/Programs/examples/TestClient/Commands/Agent/WhoCommand.cs
@@ -1,3 +1,4 @@
+using System.Linq;
using System.Text;
namespace OpenMetaverse.TestClient
@@ -17,18 +18,12 @@ namespace OpenMetaverse.TestClient
lock (Client.Network.Simulators)
{
- foreach (var sim
- in Client.Network.Simulators)
+ foreach (var av in from sim in Client.Network.Simulators
+ from kvp in sim.ObjectsAvatars where kvp.Value != null select kvp.Value)
{
- sim
-.ObjectsAvatars.ForEach(
- delegate(Avatar av)
- {
- result.AppendLine();
- result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3} LocalID: {4})",
- av.Name, av.GroupName, av.Position, av.ID, av.LocalID);
- }
- );
+ result.AppendLine();
+ result.AppendFormat("{0} (Group: {1}, Location: {2}, UUID: {3} LocalID: {4})",
+ av.Name, av.GroupName, av.Position, av.ID, av.LocalID);
}
}
diff --git a/Programs/examples/TestClient/Commands/Appearance/AttachmentsCommand.cs b/Programs/examples/TestClient/Commands/Appearance/AttachmentsCommand.cs
index b87a4a70..5cacde39 100644
--- a/Programs/examples/TestClient/Commands/Appearance/AttachmentsCommand.cs
+++ b/Programs/examples/TestClient/Commands/Appearance/AttachmentsCommand.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Linq;
namespace OpenMetaverse.TestClient
{
@@ -15,20 +14,19 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
- List attachments = Client.Network.CurrentSim.ObjectsPrimitives.FindAll(
- prim => prim.ParentID == Client.Self.LocalID
- );
+ var attachments = (from kvp in Client.Network.CurrentSim.ObjectsPrimitives
+ where kvp.Value != null where kvp.Value.ParentID == Client.Self.LocalID select kvp.Value).ToList();
foreach (var prim in attachments)
{
- AttachmentPoint point = StateToAttachmentPoint(prim.PrimData.State);
+ var point = StateToAttachmentPoint(prim.PrimData.State);
- // TODO: Fetch properties for the objects with missing property sets so we can show names
+ // TODO: Fetch properties for the objects with missing property sets, so we can show names
Logger.Log($"[Attachment @ {point}] LocalID: {prim.LocalID} UUID: {prim.ID} Offset: {prim.Position}",
Helpers.LogLevel.Info, Client);
}
- return "Found " + attachments.Count + " attachments";
+ return $"Found {attachments.Count} attachments";
}
public static AttachmentPoint StateToAttachmentPoint(uint state)
diff --git a/Programs/examples/TestClient/Commands/Appearance/AvatarInfoCommand.cs b/Programs/examples/TestClient/Commands/Appearance/AvatarInfoCommand.cs
index 2dbf1852..85091533 100644
--- a/Programs/examples/TestClient/Commands/Appearance/AvatarInfoCommand.cs
+++ b/Programs/examples/TestClient/Commands/Appearance/AvatarInfoCommand.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Text;
namespace OpenMetaverse.TestClient.Commands.Appearance
@@ -19,12 +20,12 @@ namespace OpenMetaverse.TestClient.Commands.Appearance
string targetName = $"{args[0]} {args[1]}";
- Avatar foundAv = Client.Network.CurrentSim.ObjectsAvatars.Find(
- avatar => (avatar.Name == targetName)
- );
+ var kvp = Client.Network.CurrentSim.ObjectsAvatars.SingleOrDefault(
+ avatar => (avatar.Value.Name == targetName));
- if (foundAv != null)
+ if (kvp.Value != null)
{
+ var foundAv = kvp.Value;
StringBuilder output = new StringBuilder();
output.AppendFormat("{0} ({1})", targetName, foundAv.ID);
@@ -46,7 +47,7 @@ namespace OpenMetaverse.TestClient.Commands.Appearance
}
else
{
- return "No nearby avatar with the name " + targetName;
+ return $"No nearby avatar named {targetName}";
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs b/Programs/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs
index 7da5b64a..ed472f08 100644
--- a/Programs/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs
+++ b/Programs/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs
@@ -29,6 +29,7 @@ using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
+using System.Linq;
using CoreJ2K;
using OpenMetaverse.Assets;
using OpenMetaverse.Imaging;
@@ -64,12 +65,12 @@ namespace OpenMetaverse.TestClient
{
foreach (var sim in Client.Network.Simulators)
{
- Avatar targetAv = sim.ObjectsAvatars.Find(
- avatar => avatar.ID == target
- );
+ var kvp = sim.ObjectsAvatars.FirstOrDefault(
+ avatar => avatar.Value.ID == target);
- if (targetAv != null)
+ if (kvp.Value != null)
{
+ var targetAv = kvp.Value;
StringBuilder output = new StringBuilder("Downloading ");
lock (OutfitAssets) OutfitAssets.Clear();
diff --git a/Programs/examples/TestClient/Commands/Inventory/ObjectInventoryCommand.cs b/Programs/examples/TestClient/Commands/Inventory/ObjectInventoryCommand.cs
index eaad0269..50346b48 100644
--- a/Programs/examples/TestClient/Commands/Inventory/ObjectInventoryCommand.cs
+++ b/Programs/examples/TestClient/Commands/Inventory/ObjectInventoryCommand.cs
@@ -1,5 +1,5 @@
using System;
-using System.Collections.Generic;
+using System.Linq;
namespace OpenMetaverse.TestClient
{
@@ -15,44 +15,47 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
if (args.Length != 1)
- return "Usage: objectinventory [objectID]";
-
- uint objectLocalID;
- UUID objectID;
- if (!UUID.TryParse(args[0], out objectID))
- return "Usage: objectinventory [objectID]";
-
- Primitive found = Client.Network.CurrentSim.ObjectsPrimitives.Find(prim => prim.ID == objectID);
- if (found != null)
- objectLocalID = found.LocalID;
- else
- return "Couldn't find prim " + objectID;
-
- List items = Client.Inventory.GetTaskInventory(objectID, objectLocalID, TimeSpan.FromSeconds(30));
-
- if (items != null)
{
- string result = string.Empty;
+ return "Usage: objectinventory [objectID]";
+ }
- foreach (var i in items)
+ if (!UUID.TryParse(args[0], out var objectID))
+ {
+ return "Usage: objectinventory [objectID]";
+ }
+
+ var found = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(prim => prim.Value.ID == objectID);
+ if (found.Value == null)
+ {
+ return $"Could not find ${objectID} object";
+ }
+
+ var objectLocalID = found.Value.LocalID;
+
+ var items = Client.Inventory.GetTaskInventory(objectID, objectLocalID, TimeSpan.FromSeconds(30));
+
+ if (items == null)
+ {
+ return $"Failed to download task inventory for {objectLocalID}";
+ }
+
+ var result = string.Empty;
+
+ foreach (var i in items)
+ {
+ if (i is InventoryFolder)
{
- if (i is InventoryFolder)
- {
- result += $"[Folder] Name: {i.Name}" + Environment.NewLine;
- }
- else
- {
- InventoryItem item = (InventoryItem)i;
- result += $"[Item] Name: {item.Name} Desc: {item.Description} Type: {item.AssetType}" + Environment.NewLine;
- }
+ result += $"[Folder] Name: {i.Name}" + Environment.NewLine;
}
+ else
+ {
+ InventoryItem item = (InventoryItem)i;
+ result += $"[Item] Name: {item.Name} Desc: {item.Description} Type: {item.AssetType}" + Environment.NewLine;
+ }
+ }
+
+ return result;
- return result;
- }
- else
- {
- return "Failed to download task inventory for " + objectLocalID;
- }
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Inventory/TaskRunningCommand.cs b/Programs/examples/TestClient/Commands/Inventory/TaskRunningCommand.cs
index c2861563..e9725fd8 100644
--- a/Programs/examples/TestClient/Commands/Inventory/TaskRunningCommand.cs
+++ b/Programs/examples/TestClient/Commands/Inventory/TaskRunningCommand.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
namespace OpenMetaverse.TestClient
@@ -16,19 +17,22 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
if (args.Length != 1)
+ {
return "Usage: taskrunning objectID [[scriptName] true|false]";
+ }
- uint objectLocalID;
- UUID objectID;
-
- if (!UUID.TryParse(args[0], out objectID))
+ if (!UUID.TryParse(args[0], out var objectID))
+ {
return "Usage: taskrunning objectID [[scriptName] true|false]";
+ }
- Primitive found = Client.Network.CurrentSim.ObjectsPrimitives.Find(prim => prim.ID == objectID);
- if (found != null)
- objectLocalID = found.LocalID;
- else
- return $"Couldn't find prim {objectID}";
+ var found = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(prim => prim.Value.ID == objectID);
+ if (found.Value == null)
+ {
+ return $"Couldn't find object {objectID}";
+ }
+
+ var objectLocalID = found.Value.LocalID;
List items = Client.Inventory.GetTaskInventory(objectID, objectLocalID, TimeSpan.FromSeconds(30));
diff --git a/Programs/examples/TestClient/Commands/Movement/FollowCommand.cs b/Programs/examples/TestClient/Commands/Movement/FollowCommand.cs
index 730a0ba3..a46f8a22 100644
--- a/Programs/examples/TestClient/Commands/Movement/FollowCommand.cs
+++ b/Programs/examples/TestClient/Commands/Movement/FollowCommand.cs
@@ -43,18 +43,14 @@ namespace OpenMetaverse.TestClient
{
lock (Client.Network.Simulators)
{
- foreach (var sim in Client.Network.Simulators)
+ foreach (var target in Client.Network.Simulators
+ .Select(sim => sim.ObjectsAvatars
+ .FirstOrDefault(avatar => avatar.Value.Name == name))
+ .Where(target => target.Value != null))
{
- Avatar target = sim.ObjectsAvatars.Find(
- avatar => avatar.Name == name
- );
-
- if (target != null)
- {
- targetLocalID = target.LocalID;
- Active = true;
- return true;
- }
+ targetLocalID = target.Value.LocalID;
+ Active = true;
+ return true;
}
}
diff --git a/Programs/examples/TestClient/Commands/Movement/SitCommand.cs b/Programs/examples/TestClient/Commands/Movement/SitCommand.cs
index 41c35eec..06d969ed 100644
--- a/Programs/examples/TestClient/Commands/Movement/SitCommand.cs
+++ b/Programs/examples/TestClient/Commands/Movement/SitCommand.cs
@@ -16,30 +16,28 @@ namespace OpenMetaverse.TestClient
Primitive closest = null;
double closestDistance = double.MaxValue;
- Client.Network.CurrentSim.ObjectsPrimitives.ForEach(
- delegate(Primitive prim)
- {
- float distance = Vector3.Distance(Client.Self.SimPosition, prim.Position);
-
- if (closest == null || distance < closestDistance)
- {
- closest = prim;
- closestDistance = distance;
- }
- }
- );
-
- if (closest != null)
+ foreach (var kvp in Client.Network.CurrentSim.ObjectsPrimitives)
{
- Client.Self.RequestSit(closest.ID, Vector3.Zero);
- Client.Self.Sit();
+ if (kvp.Value == null) { continue; }
- return "Sat on " + closest.ID + " (" + closest.LocalID + "). Distance: " + closestDistance;
+ var prim = kvp.Value;
+ var distance = Vector3.Distance(Client.Self.SimPosition, prim.Position);
+ if (closest == null || distance < closestDistance)
+ {
+ closest = prim;
+ closestDistance = distance;
+ }
}
- else
+
+ if (closest == null)
{
return "Couldn't find a nearby prim to sit on";
}
- }
+ Client.Self.RequestSit(closest.ID, Vector3.Zero);
+ Client.Self.Sit();
+
+ return $"Sat on {closest.ID} ({closest.LocalID}). Distance: {closestDistance}";
+
+ }
}
}
diff --git a/Programs/examples/TestClient/Commands/Movement/SitOnCommand.cs b/Programs/examples/TestClient/Commands/Movement/SitOnCommand.cs
index e1c16735..8ccb3bb0 100644
--- a/Programs/examples/TestClient/Commands/Movement/SitOnCommand.cs
+++ b/Programs/examples/TestClient/Commands/Movement/SitOnCommand.cs
@@ -1,3 +1,5 @@
+using System.Linq;
+
namespace OpenMetaverse.TestClient
{
public class SitOnCommand : Command
@@ -14,16 +16,13 @@ namespace OpenMetaverse.TestClient
if (args.Length != 1)
return "Usage: siton UUID";
- UUID target;
-
- if (UUID.TryParse(args[0], out target))
+ if (UUID.TryParse(args[0], out var target))
{
- Primitive targetPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find(
- prim => prim.ID == target
- );
+ var kvp = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(prim => prim.Value.ID == target);
- if (targetPrim != null)
+ if (kvp.Value != null)
{
+ var targetPrim = kvp.Value;
Client.Self.RequestSit(targetPrim.ID, Vector3.Zero);
Client.Self.Sit();
return "Requested to sit on prim " + targetPrim.ID +
diff --git a/Programs/examples/TestClient/Commands/Prims/ChangePermsCommand.cs b/Programs/examples/TestClient/Commands/Prims/ChangePermsCommand.cs
index 0f22e0d9..398c567a 100644
--- a/Programs/examples/TestClient/Commands/Prims/ChangePermsCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/ChangePermsCommand.cs
@@ -7,9 +7,9 @@ namespace OpenMetaverse.TestClient
{
public class ChangePermsCommand : Command
{
- AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
- Dictionary Objects = new Dictionary();
- PermissionMask Perms = PermissionMask.None;
+ private readonly AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
+ private readonly Dictionary Objects = new Dictionary();
+ private PermissionMask Perms = PermissionMask.None;
private bool PermsSent;
private int PermCount;
@@ -24,7 +24,6 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
- UUID rootID;
var localIDs = new List();
// Reset class-wide variables
@@ -36,7 +35,7 @@ namespace OpenMetaverse.TestClient
if (args.Length < 1 || args.Length > 4)
return "Usage prim-uuid [copy] [mod] [xfer]";
- if (!UUID.TryParse(args[0], out rootID))
+ if (!UUID.TryParse(args[0], out var rootID))
return "Usage prim-uuid [copy] [mod] [xfer]";
for (int i = 1; i < args.Length; i++)
@@ -60,13 +59,15 @@ namespace OpenMetaverse.TestClient
Logger.DebugLog($"Using PermissionMask: {Perms}", Client);
// Find the requested prim
- var rootPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find(prim => prim.ID == rootID);
- if (rootPrim == null)
+ var reqkvp = Client.Network.CurrentSim.ObjectsPrimitives
+ .FirstOrDefault(prim => prim.Value.ID == rootID);
+ if (reqkvp.Value == null)
{
- return $"Cannot find requested prim {rootID}";
+ return $"Cannot find requested object {rootID}";
}
- Logger.DebugLog($"Found requested prim {rootPrim.ID}", Client);
+ var rootPrim = reqkvp.Value;
+ Logger.DebugLog($"Found requested object {rootPrim.ID}", Client);
if (rootPrim.ParentID != 0)
{
@@ -79,8 +80,10 @@ namespace OpenMetaverse.TestClient
Logger.DebugLog($"Set root prim to {rootPrim.ID}", Client);
}
- // Find, find all the child objects linked to this root
- var childPrims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll(prim => prim.ParentID == rootPrim.LocalID);
+ // Find all the child primitives linked to the root
+ var childPrims = (from kvp
+ in Client.Network.CurrentSim.ObjectsPrimitives where kvp.Value != null
+ select kvp.Value into child where child.ParentID == rootPrim.LocalID select child).ToList();
// Build a dictionary of primitives for referencing later
Objects[rootPrim.ID] = rootPrim;
@@ -140,7 +143,7 @@ namespace OpenMetaverse.TestClient
return $"Set permissions to {Perms} on {localIDs.Count} objects and {taskItems} inventory items";
}
- void Objects_OnObjectProperties(object sender, ObjectPropertiesEventArgs e)
+ private void Objects_OnObjectProperties(object sender, ObjectPropertiesEventArgs e)
{
if (!PermsSent) { return; }
diff --git a/Programs/examples/TestClient/Commands/Prims/DeRezObjectCommand.cs b/Programs/examples/TestClient/Commands/Prims/DeRezObjectCommand.cs
index c1ca8af5..1336cbdf 100644
--- a/Programs/examples/TestClient/Commands/Prims/DeRezObjectCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/DeRezObjectCommand.cs
@@ -1,4 +1,6 @@
-namespace OpenMetaverse.TestClient
+using System.Linq;
+
+namespace OpenMetaverse.TestClient
{
public class DeRezCommand : Command
{
@@ -11,34 +13,28 @@
public override string Execute(string[] args, UUID fromAgentID)
{
- UUID primID;
-
if (args.Length != 1)
- return "Usage: derez [prim-uuid]";
-
- if (UUID.TryParse(args[0], out primID))
- {
- Primitive target = Client.Network.CurrentSim.ObjectsPrimitives.Find(
- prim => prim.ID == primID
- );
-
- if (target != null)
- {
- uint objectLocalID = target.LocalID;
- Client.Inventory.RequestDeRezToInventory(objectLocalID, DeRezDestination.AgentInventoryTake,
- Client.Inventory.FindFolderForType(FolderType.Trash),
- UUID.Random());
- return "removing " + target;
- }
- else
- {
- return "Could not find prim " + primID;
- }
- }
- else
{
return "Usage: derez [prim-uuid]";
}
+
+ if (!UUID.TryParse(args[0], out var primID))
+ {
+ return $"{args[0]} is not a valid UUID";
+ }
+
+ var kvp = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(prim => prim.Value.ID == primID);
+ if (kvp.Value == null)
+ {
+ return $"Could not find object {primID}";
+ }
+ var target = kvp.Value;
+ var objectLocalID = target.LocalID;
+ Client.Inventory.RequestDeRezToInventory(objectLocalID, DeRezDestination.AgentInventoryTake,
+ Client.Inventory.FindFolderForType(FolderType.Trash),
+ UUID.Random());
+ return $"Removing {target}";
+
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Prims/ExportCommand.cs b/Programs/examples/TestClient/Commands/Prims/ExportCommand.cs
index ab693f95..80eba860 100644
--- a/Programs/examples/TestClient/Commands/Prims/ExportCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/ExportCommand.cs
@@ -10,14 +10,14 @@ namespace OpenMetaverse.TestClient
{
public class ExportCommand : Command
{
- List Textures = new List();
- AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
- Primitive.ObjectProperties Properties;
- bool GotPermissions = false;
- UUID SelectedObject = UUID.Zero;
+ private readonly List Textures = new List();
+ private readonly AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
+ private Primitive.ObjectProperties Properties;
+ private bool GotPermissions = false;
+ private UUID SelectedObject = UUID.Zero;
- Dictionary PrimsWaiting = new Dictionary();
- AutoResetEvent AllPropertiesReceived = new AutoResetEvent(false);
+ private readonly Dictionary PrimsWaiting = new Dictionary();
+ private readonly AutoResetEvent AllPropertiesReceived = new AutoResetEvent(false);
public ExportCommand(TestClient testClient)
{
@@ -29,9 +29,9 @@ namespace OpenMetaverse.TestClient
Name = "export";
Description = "Exports an object to an xml file. Usage: export uuid outputfile.xml";
Category = CommandCategory.Objects;
- }
+ }
- void Avatars_ViewerEffectPointAt(object sender, ViewerEffectPointAtEventArgs e)
+ private void Avatars_ViewerEffectPointAt(object sender, ViewerEffectPointAtEventArgs e)
{
if (e.SourceID == Client.MasterKey)
{
@@ -46,7 +46,6 @@ namespace OpenMetaverse.TestClient
return "Usage: export uuid outputfile.xml";
UUID id;
- uint localid;
string file;
if (args.Length == 2)
@@ -61,105 +60,100 @@ namespace OpenMetaverse.TestClient
id = SelectedObject;
}
- var exportPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find(
- prim => prim.ID == id
- );
+ var kvp = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(
+ prim => prim.Value.ID == id);
- if (exportPrim != null)
+ if (kvp.Value == null)
{
- localid = exportPrim.ParentID != 0 ? exportPrim.ParentID : exportPrim.LocalID;
+ return $"Couldn't find UUID {id} in the objects currently indexed in the current simulator";
+ }
- // Check for export permission first
- Client.Objects.RequestObjectPropertiesFamily(Client.Network.CurrentSim, id);
- GotPermissionsEvent.WaitOne(TimeSpan.FromSeconds(20), false);
+ var exportPrim = kvp.Value;
+ var localId = exportPrim.ParentID != 0 ? exportPrim.ParentID : exportPrim.LocalID;
- if (!GotPermissions)
+ // Check for export permission first
+ Client.Objects.RequestObjectPropertiesFamily(Client.Network.CurrentSim, id);
+ GotPermissionsEvent.WaitOne(TimeSpan.FromSeconds(20), false);
+
+ if (!GotPermissions)
+ {
+ return "Couldn't fetch permissions for the requested object, try again";
+ }
+
+ GotPermissions = false;
+
+ if (Properties.OwnerID != Client.Self.AgentID &&
+ Properties.OwnerID != Client.MasterKey)
+ {
+ return "That object is owned by " + Properties.OwnerID + ", we don't have permission " +
+ "to export it";
+ }
+
+ var prims = (from kvprim in Client.Network.CurrentSim.ObjectsPrimitives
+ where kvprim.Value != null select kvprim.Value into prim
+ where prim.LocalID == localId || prim.ParentID == localId select prim).ToList();
+
+ bool complete = RequestObjectProperties(prims, 250);
+
+ if (!complete)
+ {
+ Logger.Log("Warning: Unable to retrieve full properties for:", Helpers.LogLevel.Warning, Client);
+ foreach (UUID uuid in PrimsWaiting.Keys)
+ Logger.Log(uuid.ToString(), Helpers.LogLevel.Warning, Client);
+ }
+
+ string output = OSDParser.SerializeLLSDXmlString(Helpers.PrimListToOSD(prims));
+ try { File.WriteAllText(file, output); }
+ catch (Exception e) { return e.Message; }
+
+ Logger.Log("Exported " + prims.Count + " prims to " + file, Helpers.LogLevel.Info, Client);
+
+ // Create a list of all the textures to download
+ List textureRequests = new List();
+
+ lock (Textures)
+ {
+ foreach (var prim in prims)
{
- return "Couldn't fetch permissions for the requested object, try again";
- }
- else
- {
- GotPermissions = false;
- if (Properties.OwnerID != Client.Self.AgentID &&
- Properties.OwnerID != Client.MasterKey)
+ if (prim.Textures.DefaultTexture.TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
+ !Textures.Contains(prim.Textures.DefaultTexture.TextureID))
{
- return "That object is owned by " + Properties.OwnerID + ", we don't have permission " +
- "to export it";
+ Textures.Add(prim.Textures.DefaultTexture.TextureID);
}
- }
- List prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll(
- prim => (prim.LocalID == localid || prim.ParentID == localid)
- );
-
- bool complete = RequestObjectProperties(prims, 250);
-
- if (!complete)
- {
- Logger.Log("Warning: Unable to retrieve full properties for:", Helpers.LogLevel.Warning, Client);
- foreach (UUID uuid in PrimsWaiting.Keys)
- Logger.Log(uuid.ToString(), Helpers.LogLevel.Warning, Client);
- }
-
- string output = OSDParser.SerializeLLSDXmlString(Helpers.PrimListToOSD(prims));
- try { File.WriteAllText(file, output); }
- catch (Exception e) { return e.Message; }
-
- Logger.Log("Exported " + prims.Count + " prims to " + file, Helpers.LogLevel.Info, Client);
-
- // Create a list of all of the textures to download
- List textureRequests = new List();
-
- lock (Textures)
- {
- foreach (var prim in prims)
+ foreach (var face in prim.Textures.FaceTextures)
{
- if (prim.Textures.DefaultTexture.TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
- !Textures.Contains(prim.Textures.DefaultTexture.TextureID))
+ if (face != null &&
+ face.TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
+ !Textures.Contains(face.TextureID))
{
- Textures.Add(prim.Textures.DefaultTexture.TextureID);
- }
-
- foreach (var face in prim.Textures.FaceTextures)
- {
- if (face != null &&
- face.TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
- !Textures.Contains(face.TextureID))
- {
- Textures.Add(face.TextureID);
- }
- }
-
- if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero && !Textures.Contains(prim.Sculpt.SculptTexture))
- {
- Textures.Add(prim.Sculpt.SculptTexture);
+ Textures.Add(face.TextureID);
}
}
- // Create a request list from all of the images
- textureRequests.AddRange(Textures.Select(t => new ImageRequest(t, ImageType.Normal, 1013000.0f, 0)));
+ if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero && !Textures.Contains(prim.Sculpt.SculptTexture))
+ {
+ Textures.Add(prim.Sculpt.SculptTexture);
+ }
}
- // Download all of the textures in the export list
- foreach (ImageRequest request in textureRequests)
- {
- Client.Assets.RequestImage(request.ImageID, request.Type, Assets_OnImageReceived);
- }
-
- return "XML exported, began downloading " + Textures.Count + " textures";
+ // Create a request list from all the images
+ textureRequests.AddRange(Textures.Select(t => new ImageRequest(t, ImageType.Normal, 1013000.0f, 0)));
}
- else
+
+ // Download all the textures in the export list
+ foreach (var request in textureRequests)
{
- return "Couldn't find UUID " + id + " in the " +
- Client.Network.CurrentSim.ObjectsPrimitives.Count +
- "objects currently indexed in the current simulator";
+ Client.Assets.RequestImage(request.ImageID, request.Type, Assets_OnImageReceived);
}
+
+ return $"XML exported, downloading {Textures.Count} textures";
}
private bool RequestObjectProperties(List objects, int msPerRequest)
{
// Create an array of the local IDs of all the prims we are requesting properties for
- uint[] localids = new uint[objects.Count];
+ uint[] localIds = new uint[objects.Count];
lock (PrimsWaiting)
{
@@ -167,12 +161,12 @@ namespace OpenMetaverse.TestClient
for (int i = 0; i < objects.Count; ++i)
{
- localids[i] = objects[i].LocalID;
+ localIds[i] = objects[i].LocalID;
PrimsWaiting.Add(objects[i].ID, objects[i]);
}
}
- Client.Objects.SelectObjects(Client.Network.CurrentSim, localids);
+ Client.Objects.SelectObjects(Client.Network.CurrentSim, localIds);
return AllPropertiesReceived.WaitOne(2000 + msPerRequest * objects.Count, false);
}
@@ -202,7 +196,7 @@ namespace OpenMetaverse.TestClient
}
}
- void Objects_OnObjectPropertiesFamily(object sender, ObjectPropertiesFamilyEventArgs e)
+ private void Objects_OnObjectPropertiesFamily(object sender, ObjectPropertiesFamilyEventArgs e)
{
Properties = new Primitive.ObjectProperties();
Properties.SetFamilyProperties(e.Properties);
@@ -210,7 +204,7 @@ namespace OpenMetaverse.TestClient
GotPermissionsEvent.Set();
}
- void Objects_OnObjectProperties(object sender, ObjectPropertiesEventArgs e)
+ private void Objects_OnObjectProperties(object sender, ObjectPropertiesEventArgs e)
{
lock (PrimsWaiting)
{
diff --git a/Programs/examples/TestClient/Commands/Prims/ExportParticlesCommand.cs b/Programs/examples/TestClient/Commands/Prims/ExportParticlesCommand.cs
index a339eb25..c48f3d34 100644
--- a/Programs/examples/TestClient/Commands/Prims/ExportParticlesCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/ExportParticlesCommand.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Text;
namespace OpenMetaverse.TestClient
@@ -15,121 +16,119 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
if (args.Length != 1)
+ {
return "Usage: exportparticles [prim-uuid]";
+ }
- UUID id;
- if (!UUID.TryParse(args[0], out id))
+ if (!UUID.TryParse(args[0], out var id))
+ {
return "Usage: exportparticles [prim-uuid]";
+ }
lock (Client.Network.Simulators)
{
- foreach (var sim in Client.Network.Simulators)
+ foreach (var exportPrim in from sim in Client.Network.Simulators
+ select sim.ObjectsPrimitives.FirstOrDefault(
+ prim => prim.Value.ID == id)
+ into kvp where kvp.Value != null select kvp.Value)
{
- Primitive exportPrim = sim.ObjectsPrimitives.Find(
- prim => prim.ID == id
- );
-
- if (exportPrim != null)
+ if (exportPrim.ParticleSys.CRC == 0)
{
- if (exportPrim.ParticleSys.CRC != 0)
- {
- StringBuilder lsl = new StringBuilder();
-
- #region Particle System to LSL
-
- lsl.Append("default" + Environment.NewLine);
- lsl.Append("{" + Environment.NewLine);
- lsl.Append(" state_entry()" + Environment.NewLine);
- lsl.Append(" {" + Environment.NewLine);
- lsl.Append(" llParticleSystem([" + Environment.NewLine);
-
- lsl.Append(" PSYS_PART_FLAGS, 0");
-
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpColor) != 0)
- lsl.Append(" | PSYS_PART_INTERP_COLOR_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpScale) != 0)
- lsl.Append(" | PSYS_PART_INTERP_SCALE_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Bounce) != 0)
- lsl.Append(" | PSYS_PART_BOUNCE_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Wind) != 0)
- lsl.Append(" | PSYS_PART_WIND_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowSrc) != 0)
- lsl.Append(" | PSYS_PART_FOLLOW_SRC_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowVelocity) != 0)
- lsl.Append(" | PSYS_PART_FOLLOW_VELOCITY_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetPos) != 0)
- lsl.Append(" | PSYS_PART_TARGET_POS_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetLinear) != 0)
- lsl.Append(" | PSYS_PART_TARGET_LINEAR_MASK");
- if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Emissive) != 0)
- lsl.Append(" | PSYS_PART_EMISSIVE_MASK");
-
- lsl.Append(","); lsl.Append(Environment.NewLine);
- lsl.Append(" PSYS_SRC_PATTERN, 0");
-
- if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Drop) != 0)
- lsl.Append(" | PSYS_SRC_PATTERN_DROP");
- if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Explode) != 0)
- lsl.Append(" | PSYS_SRC_PATTERN_EXPLODE");
- if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Angle) != 0)
- lsl.Append(" | PSYS_SRC_PATTERN_ANGLE");
- if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleCone) != 0)
- lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE");
- if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleConeEmpty) != 0)
- lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY");
-
- lsl.Append("," + Environment.NewLine);
-
- lsl.Append(" PSYS_PART_START_ALPHA, " +
- $"{exportPrim.ParticleSys.PartStartColor.A:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_PART_END_ALPHA, " +
- $"{exportPrim.ParticleSys.PartEndColor.A:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_PART_START_COLOR, " + exportPrim.ParticleSys.PartStartColor.ToRGBString() + "," + Environment.NewLine);
- lsl.Append(" PSYS_PART_END_COLOR, " + exportPrim.ParticleSys.PartEndColor.ToRGBString() + "," + Environment.NewLine);
- lsl.Append(" PSYS_PART_START_SCALE, <" +
- $"{exportPrim.ParticleSys.PartStartScaleX:0.00000}" + ", " +
- $"{exportPrim.ParticleSys.PartStartScaleY:0.00000}" + ", 0>, " + Environment.NewLine);
- lsl.Append(" PSYS_PART_END_SCALE, <" +
- $"{exportPrim.ParticleSys.PartEndScaleX:0.00000}" + ", " +
- $"{exportPrim.ParticleSys.PartEndScaleY:0.00000}" + ", 0>, " + Environment.NewLine);
- lsl.Append(" PSYS_PART_MAX_AGE, " + $"{exportPrim.ParticleSys.PartMaxAge:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_MAX_AGE, " + $"{exportPrim.ParticleSys.MaxAge:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_ACCEL, " + exportPrim.ParticleSys.PartAcceleration + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_BURST_PART_COUNT, " +
- $"{exportPrim.ParticleSys.BurstPartCount:0}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_BURST_RADIUS, " +
- $"{exportPrim.ParticleSys.BurstRadius:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_BURST_RATE, " +
- $"{exportPrim.ParticleSys.BurstRate:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_BURST_SPEED_MIN, " +
- $"{exportPrim.ParticleSys.BurstSpeedMin:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_BURST_SPEED_MAX, " +
- $"{exportPrim.ParticleSys.BurstSpeedMax:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_INNERANGLE, " +
- $"{exportPrim.ParticleSys.InnerAngle:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_OUTERANGLE, " +
- $"{exportPrim.ParticleSys.OuterAngle:0.00000}" + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_OMEGA, " + exportPrim.ParticleSys.AngularVelocity + "," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_TEXTURE, (key)\"" + exportPrim.ParticleSys.Texture + "\"," + Environment.NewLine);
- lsl.Append(" PSYS_SRC_TARGET_KEY, (key)\"" + exportPrim.ParticleSys.Target + "\"" + Environment.NewLine);
-
- lsl.Append(" ]);" + Environment.NewLine);
- lsl.Append(" }" + Environment.NewLine);
- lsl.Append("}" + Environment.NewLine);
-
- #endregion Particle System to LSL
-
- return lsl.ToString();
- }
- else
- {
- return "Prim " + exportPrim.LocalID + " does not have a particle system";
- }
+ return $"Prim {exportPrim.LocalID} does not have a particle system";
}
+
+ StringBuilder lsl = new StringBuilder();
+
+ #region Particle System to LSL
+
+ lsl.Append("default" + Environment.NewLine);
+ lsl.Append("{" + Environment.NewLine);
+ lsl.Append(" state_entry()" + Environment.NewLine);
+ lsl.Append(" {" + Environment.NewLine);
+ lsl.Append(" llParticleSystem([" + Environment.NewLine);
+
+ lsl.Append(" PSYS_PART_FLAGS, 0");
+
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpColor) != 0)
+ lsl.Append(" | PSYS_PART_INTERP_COLOR_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpScale) != 0)
+ lsl.Append(" | PSYS_PART_INTERP_SCALE_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Bounce) != 0)
+ lsl.Append(" | PSYS_PART_BOUNCE_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Wind) != 0)
+ lsl.Append(" | PSYS_PART_WIND_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowSrc) != 0)
+ lsl.Append(" | PSYS_PART_FOLLOW_SRC_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowVelocity) != 0)
+ lsl.Append(" | PSYS_PART_FOLLOW_VELOCITY_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetPos) != 0)
+ lsl.Append(" | PSYS_PART_TARGET_POS_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetLinear) != 0)
+ lsl.Append(" | PSYS_PART_TARGET_LINEAR_MASK");
+ if ((exportPrim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Emissive) != 0)
+ lsl.Append(" | PSYS_PART_EMISSIVE_MASK");
+
+ lsl.Append(","); lsl.Append(Environment.NewLine);
+ lsl.Append(" PSYS_SRC_PATTERN, 0");
+
+ if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Drop) != 0)
+ lsl.Append(" | PSYS_SRC_PATTERN_DROP");
+ if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Explode) != 0)
+ lsl.Append(" | PSYS_SRC_PATTERN_EXPLODE");
+ if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Angle) != 0)
+ lsl.Append(" | PSYS_SRC_PATTERN_ANGLE");
+ if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleCone) != 0)
+ lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE");
+ if ((exportPrim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleConeEmpty) != 0)
+ lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY");
+
+ lsl.Append("," + Environment.NewLine);
+
+ lsl.Append(" PSYS_PART_START_ALPHA, " +
+ $"{exportPrim.ParticleSys.PartStartColor.A:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_PART_END_ALPHA, " +
+ $"{exportPrim.ParticleSys.PartEndColor.A:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_PART_START_COLOR, " + exportPrim.ParticleSys.PartStartColor.ToRGBString() + "," + Environment.NewLine);
+ lsl.Append(" PSYS_PART_END_COLOR, " + exportPrim.ParticleSys.PartEndColor.ToRGBString() + "," + Environment.NewLine);
+ lsl.Append(" PSYS_PART_START_SCALE, <" +
+ $"{exportPrim.ParticleSys.PartStartScaleX:0.00000}" + ", " +
+ $"{exportPrim.ParticleSys.PartStartScaleY:0.00000}" + ", 0>, " + Environment.NewLine);
+ lsl.Append(" PSYS_PART_END_SCALE, <" +
+ $"{exportPrim.ParticleSys.PartEndScaleX:0.00000}" + ", " +
+ $"{exportPrim.ParticleSys.PartEndScaleY:0.00000}" + ", 0>, " + Environment.NewLine);
+ lsl.Append(" PSYS_PART_MAX_AGE, " + $"{exportPrim.ParticleSys.PartMaxAge:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_MAX_AGE, " + $"{exportPrim.ParticleSys.MaxAge:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_ACCEL, " + exportPrim.ParticleSys.PartAcceleration + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_BURST_PART_COUNT, " +
+ $"{exportPrim.ParticleSys.BurstPartCount:0}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_BURST_RADIUS, " +
+ $"{exportPrim.ParticleSys.BurstRadius:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_BURST_RATE, " +
+ $"{exportPrim.ParticleSys.BurstRate:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_BURST_SPEED_MIN, " +
+ $"{exportPrim.ParticleSys.BurstSpeedMin:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_BURST_SPEED_MAX, " +
+ $"{exportPrim.ParticleSys.BurstSpeedMax:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_INNERANGLE, " +
+ $"{exportPrim.ParticleSys.InnerAngle:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_OUTERANGLE, " +
+ $"{exportPrim.ParticleSys.OuterAngle:0.00000}" + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_OMEGA, " + exportPrim.ParticleSys.AngularVelocity + "," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_TEXTURE, (key)\"" + exportPrim.ParticleSys.Texture + "\"," + Environment.NewLine);
+ lsl.Append(" PSYS_SRC_TARGET_KEY, (key)\"" + exportPrim.ParticleSys.Target + "\"" + Environment.NewLine);
+
+ lsl.Append(" ]);" + Environment.NewLine);
+ lsl.Append(" }" + Environment.NewLine);
+ lsl.Append("}" + Environment.NewLine);
+
+ #endregion Particle System to LSL
+
+ return lsl.ToString();
+
}
}
- return "Couldn't find prim " + id;
+ return $"Could not find {id} object";
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Prims/FindObjectsCommand.cs b/Programs/examples/TestClient/Commands/Prims/FindObjectsCommand.cs
index 0a65b29f..3be22d9d 100644
--- a/Programs/examples/TestClient/Commands/Prims/FindObjectsCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/FindObjectsCommand.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
using System.Threading;
@@ -23,36 +25,36 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
// *** parse arguments ***
- if ((args.Length < 1) || (args.Length > 2))
+ if (args.Length < 1 || args.Length > 2)
+ {
return "Usage: findobjects [radius] ";
- float radius = float.Parse(args[0]);
- string searchString = (args.Length > 1) ? args[1] : string.Empty;
+ }
+
+ var radius = float.Parse(args[0]);
+ var searchString = (args.Length > 1) ? args[1] : string.Empty;
// *** get current location ***
- Vector3 location = Client.Self.SimPosition;
+ var location = Client.Self.SimPosition;
// *** find all objects in radius ***
- List 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));
- }
- );
+ var prims = (from kvp
+ in Client.Network.CurrentSim.ObjectsPrimitives
+ where kvp.Value != null select kvp.Value into prim let pos = prim.Position
+ where prim.ParentID == 0 && pos != Vector3.Zero && Vector3.Distance(pos, location) < radius select prim).ToList();
// *** request properties of these objects ***
- bool complete = RequestObjectProperties(prims, 250);
+ var complete = RequestObjectProperties(prims, 250);
- foreach (Primitive p in prims)
+ foreach (var p in prims)
{
- string name = p.Properties?.Name;
+ var name = p.Properties?.Name;
if (string.IsNullOrEmpty(searchString) || ((name != null) && (name.Contains(searchString))))
Console.WriteLine("Object '{0}': {1}", name, p.ID.ToString());
}
if (complete) return "Done searching";
Console.WriteLine("Warning: Unable to retrieve full properties for:");
- foreach (UUID uuid in PrimsWaiting.Keys)
+ foreach (var uuid in PrimsWaiting.Keys)
Console.WriteLine(uuid);
return "Done searching";
@@ -83,8 +85,7 @@ namespace OpenMetaverse.TestClient
{
lock (PrimsWaiting)
{
- Primitive prim;
- if (PrimsWaiting.TryGetValue(e.Properties.ObjectID, out prim))
+ if (PrimsWaiting.TryGetValue(e.Properties.ObjectID, out var prim))
{
prim.Properties = e.Properties;
}
diff --git a/Programs/examples/TestClient/Commands/Prims/FindTextureCommand.cs b/Programs/examples/TestClient/Commands/Prims/FindTextureCommand.cs
index 325babce..45ab1a2d 100644
--- a/Programs/examples/TestClient/Commands/Prims/FindTextureCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/FindTextureCommand.cs
@@ -1,4 +1,5 @@
using System;
+using System.Security.Permissions;
namespace OpenMetaverse.TestClient
{
@@ -14,36 +15,32 @@ namespace OpenMetaverse.TestClient
public override string Execute(string[] args, UUID fromAgentID)
{
- int faceIndex;
- UUID textureID;
-
if (args.Length != 2)
- return "Usage: findtexture [face-index] [texture-uuid]";
-
- if (int.TryParse(args[0], out faceIndex) &&
- UUID.TryParse(args[1], out textureID))
{
- Client.Network.CurrentSim.ObjectsPrimitives.ForEach(
- delegate(Primitive prim)
+ return "Usage: findtexture [face-index] [texture-uuid]";
+ }
+
+ if (int.TryParse(args[0], out var faceIndex) &&
+ UUID.TryParse(args[1], out var textureID))
+ {
+ foreach (var kvp in Client.Network.CurrentSim.ObjectsPrimitives)
+ {
+ if (kvp.Value == null) { continue; }
+
+ var prim = kvp.Value;
+ if (prim.Textures?.FaceTextures[faceIndex] == null) { continue; }
+ if (prim.Textures.FaceTextures[faceIndex].TextureID == textureID)
{
- if (prim.Textures?.FaceTextures[faceIndex] != null)
- {
- if (prim.Textures.FaceTextures[faceIndex].TextureID == textureID)
- {
- Logger.Log(
- $"Primitive {prim.ID.ToString()} ({prim.LocalID}) has face index {faceIndex} set to {textureID.ToString()}",
- Helpers.LogLevel.Info, Client);
- }
- }
+ Logger.Log(
+ $"Primitive {prim.ID.ToString()} ({prim.LocalID}) has face index {faceIndex} set to {textureID.ToString()}",
+ Helpers.LogLevel.Info, Client);
}
- );
+ }
return "Done searching";
}
- else
- {
- return "Usage: findtexture [face-index] [texture-uuid]";
- }
+
+ return "Usage: findtexture [face-index] [texture-uuid]";
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Prims/PrimInfoCommand.cs b/Programs/examples/TestClient/Commands/Prims/PrimInfoCommand.cs
index 627b3505..156fffa3 100644
--- a/Programs/examples/TestClient/Commands/Prims/PrimInfoCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/PrimInfoCommand.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Threading;
namespace OpenMetaverse.TestClient
@@ -17,73 +18,73 @@ namespace OpenMetaverse.TestClient
UUID primID;
if (args.Length != 1)
- return "Usage: priminfo [prim-uuid]";
-
- if (UUID.TryParse(args[0], out primID))
{
- Primitive target = Client.Network.CurrentSim.ObjectsPrimitives.Find(
- prim => prim.ID == primID
- );
+ return "Usage: priminfo [prim-uuid]";
+ }
- if (target != null)
+ if (!UUID.TryParse(args[0], out primID))
+ {
+ return $"{args[0]} is not a valid UUID";
+ }
+
+ var kvp = Client.Network.CurrentSim.ObjectsPrimitives.FirstOrDefault(
+ prim => prim.Value.ID == primID);
+
+ if (kvp.Value == null)
+ {
+ return $"Could not find object {primID}";
+ }
+
+ var target = kvp.Value;
+ if (target.Text != string.Empty)
+ {
+ Logger.Log("Text: " + target.Text, Helpers.LogLevel.Info, Client);
+ }
+ if (target.Light != null)
+ {
+ Logger.Log("Light: " + target.Light, Helpers.LogLevel.Info, Client);
+ }
+ if (target.ParticleSys.CRC != 0)
+ {
+ Logger.Log("Particles: " + target.ParticleSys, Helpers.LogLevel.Info, Client);
+ }
+
+ if (target.Textures != null)
+ {
+ Logger.Log($"Default texture: {target.Textures.DefaultTexture.TextureID.ToString()}",
+ Helpers.LogLevel.Info);
+
+ for (int i = 0; i < target.Textures.FaceTextures.Length; i++)
{
- if (target.Text != string.Empty)
+ if (target.Textures.FaceTextures[i] != null)
{
- Logger.Log("Text: " + target.Text, Helpers.LogLevel.Info, Client);
+ Logger.Log($"Face {i}: {target.Textures.FaceTextures[i].TextureID.ToString()}",
+ Helpers.LogLevel.Info, Client);
}
- if(target.Light != null)
- Logger.Log("Light: " + target.Light, Helpers.LogLevel.Info, Client);
-
- if (target.ParticleSys.CRC != 0)
- Logger.Log("Particles: " + target.ParticleSys, Helpers.LogLevel.Info, Client);
-
- Logger.Log("TextureEntry:", Helpers.LogLevel.Info, Client);
- if (target.Textures != null)
- {
- Logger.Log($"Default texure: {target.Textures.DefaultTexture.TextureID.ToString()}",
- Helpers.LogLevel.Info);
-
- for (int i = 0; i < target.Textures.FaceTextures.Length; i++)
- {
- if (target.Textures.FaceTextures[i] != null)
- {
- Logger.Log($"Face {i}: {target.Textures.FaceTextures[i].TextureID.ToString()}",
- Helpers.LogLevel.Info, Client);
- }
- }
- }
- else
- {
- Logger.Log("null", Helpers.LogLevel.Info, Client);
- }
-
- AutoResetEvent propsEvent = new AutoResetEvent(false);
- EventHandler propsCallback =
- delegate(object sender, ObjectPropertiesEventArgs e)
- {
- Logger.Log(
- $"Category: {e.Properties.Category}\nFolderID: {e.Properties.FolderID}\nFromTaskID: {e.Properties.FromTaskID}\nInventorySerial: {e.Properties.InventorySerial}\nItemID: {e.Properties.ItemID}\nCreationDate: {e.Properties.CreationDate}", Helpers.LogLevel.Info);
- propsEvent.Set();
- };
-
- Client.Objects.ObjectProperties += propsCallback;
-
- Client.Objects.SelectObject(Client.Network.CurrentSim, target.LocalID, true);
-
- propsEvent.WaitOne(TimeSpan.FromSeconds(10), false);
- Client.Objects.ObjectProperties -= propsCallback;
-
- return "Done.";
- }
- else
- {
- return "Could not find prim " + primID;
}
}
else
{
- return "Usage: priminfo [prim-uuid]";
+ Logger.Log("null", Helpers.LogLevel.Info, Client);
}
+
+ AutoResetEvent propsEvent = new AutoResetEvent(false);
+ EventHandler propsCallback =
+ delegate(object sender, ObjectPropertiesEventArgs e)
+ {
+ Logger.Log(
+ $"Category: {e.Properties.Category}\nFolderID: {e.Properties.FolderID}\nFromTaskID: {e.Properties.FromTaskID}\nInventorySerial: {e.Properties.InventorySerial}\nItemID: {e.Properties.ItemID}\nCreationDate: {e.Properties.CreationDate}", Helpers.LogLevel.Info);
+ propsEvent.Set();
+ };
+
+ Client.Objects.ObjectProperties += propsCallback;
+
+ Client.Objects.SelectObject(Client.Network.CurrentSim, target.LocalID, true);
+
+ propsEvent.WaitOne(TimeSpan.FromSeconds(10), false);
+ Client.Objects.ObjectProperties -= propsCallback;
+
+ return "Done.";
}
}
}
diff --git a/Programs/examples/TestClient/Commands/Prims/PrimRegexCommand.cs b/Programs/examples/TestClient/Commands/Prims/PrimRegexCommand.cs
index 5dc7ac6b..37dc0c9d 100644
--- a/Programs/examples/TestClient/Commands/Prims/PrimRegexCommand.cs
+++ b/Programs/examples/TestClient/Commands/Prims/PrimRegexCommand.cs
@@ -20,46 +20,46 @@ namespace OpenMetaverse.TestClient
try
{
- // Build the predicat from the args list
- string predicatPrim = args.Aggregate(string.Empty, (current, t) => current + (t + " "));
- predicatPrim = predicatPrim.TrimEnd();
+ // Build the predicate from the args list
+ var predicatePrim = args.Aggregate(string.Empty, (current, t) => current + (t + " "));
+ predicatePrim = predicatePrim.TrimEnd();
// Build Regex
- Regex regexPrimName = new Regex(predicatPrim.ToLower());
+ var regexPrimName = new Regex(predicatePrim.ToLower());
// Print result
Logger.Log(
- $"Searching prim for [{predicatPrim}] ({Client.Network.CurrentSim.ObjectsPrimitives.Count} prims loaded in simulator)\n", Helpers.LogLevel.Info, Client);
+ $"Searching prim for [{predicatePrim}] ({Client.Network.CurrentSim.ObjectsPrimitives.Count} prims loaded in simulator)\n",
+ Helpers.LogLevel.Info, Client);
- Client.Network.CurrentSim.ObjectsPrimitives.ForEach(
- delegate(Primitive prim)
+ foreach (var kvp in Client.Network.CurrentSim.ObjectsPrimitives)
+ {
+ if (kvp.Value == null) { continue; }
+
+ var prim = kvp.Value;
+ var name = "(unknown)";
+ var description = "(unknown)";
+
+ var match = (prim.Text != null && regexPrimName.IsMatch(prim.Text.ToLower()));
+
+ if (prim.Properties != null && !match)
{
- bool match = false;
- string name = "(unknown)";
- string description = "(unknown)";
-
-
- match = (prim.Text != null && regexPrimName.IsMatch(prim.Text.ToLower()));
-
- if (prim.Properties != null && !match)
- {
- match = regexPrimName.IsMatch(prim.Properties.Name.ToLower());
- if (!match)
- match = regexPrimName.IsMatch(prim.Properties.Description.ToLower());
- }
-
- if (match)
- {
- if (prim.Properties != null)
- {
- name = prim.Properties.Name;
- description = prim.Properties.Description;
- }
- Logger.Log(
- $"\nNAME={name}\nID = {prim.ID}\nFLAGS = {prim.Flags.ToString()}\nTEXT = '{prim.Text}'\nDESC='{description}'", Helpers.LogLevel.Info, Client);
- }
+ match = regexPrimName.IsMatch(prim.Properties.Name.ToLower());
+ if (!match)
+ match = regexPrimName.IsMatch(prim.Properties.Description.ToLower());
}
- );
+
+ if (!match) { continue; }
+
+ if (prim.Properties != null)
+ {
+ name = prim.Properties.Name;
+ description = prim.Properties.Description;
+ }
+ Logger.Log(
+ $"\nNAME={name}\nID = {prim.ID}\nFLAGS = {prim.Flags.ToString()}\nTEXT = '{prim.Text}'\nDESC='{description}'",
+ Helpers.LogLevel.Info, Client);
+ }
}
catch (System.Exception e)
{
diff --git a/Programs/examples/TestClient/Commands/System/SetMasterKeyCommand.cs b/Programs/examples/TestClient/Commands/System/SetMasterKeyCommand.cs
index 4d15f826..eccc858a 100644
--- a/Programs/examples/TestClient/Commands/System/SetMasterKeyCommand.cs
+++ b/Programs/examples/TestClient/Commands/System/SetMasterKeyCommand.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
namespace OpenMetaverse.TestClient
{
@@ -19,18 +20,14 @@ namespace OpenMetaverse.TestClient
lock (Client.Network.Simulators)
{
- foreach (var sim in Client.Network.Simulators)
+ foreach (var master in Client.Network.Simulators
+ .Select(sim => sim.ObjectsAvatars.FirstOrDefault(
+ kvp => kvp.Value.ID == Client.MasterKey))
+ .Where(master => master.Value != null))
{
- Avatar master = sim.ObjectsAvatars.Find(
- avatar => avatar.ID == Client.MasterKey
- );
-
- if (master != null)
- {
- Client.Self.InstantMessage(master.ID,
- "You are now my master. IM me with \"help\" for a command list.");
- break;
- }
+ Client.Self.InstantMessage(master.Value.ID,
+ "You are now my master. IM me with \"help\" for a command list.");
+ break;
}
}