diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 8487adc7f5..82a2cdd037 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -51,6 +51,44 @@ using Nini.Config;
namespace OpenSim.Region.ClientStack.LindenUDP
{
+ #region Enums
+
+ ///
+ /// Specifies the fields that have been changed when sending a prim or
+ /// avatar update
+ ///
+ [Flags]
+ public enum PrimUpdateFlags : uint
+ {
+ None = 0,
+ AttachmentPoint = 1 << 0,
+ Material = 1 << 1,
+ ClickAction = 1 << 2,
+ Scale = 1 << 3,
+ ParentID = 1 << 4,
+ PrimFlags = 1 << 5,
+ PrimData = 1 << 6,
+ MediaURL = 1 << 7,
+ ScratchPad = 1 << 8,
+ Textures = 1 << 9,
+ TextureAnim = 1 << 10,
+ NameValue = 1 << 11,
+ Position = 1 << 12,
+ Rotation = 1 << 13,
+ Velocity = 1 << 14,
+ Acceleration = 1 << 15,
+ AngularVelocity = 1 << 16,
+ CollisionPlane = 1 << 17,
+ Text = 1 << 18,
+ Particles = 1 << 19,
+ ExtraData = 1 << 20,
+ Sound = 1 << 21,
+ Joint = 1 << 22,
+ FullUpdate = UInt32.MaxValue
+ }
+
+ #endregion Enums
+
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
///
@@ -3159,6 +3197,195 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
+ #region Prim/Avatar Updates
+
+ /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
+ {
+ bool canUseCompressed, canUseImproved;
+ UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
+
+ if (!canUseImproved && !canUseCompressed)
+ SendFullObjectUpdate(obj, creatorFlags, updateFlags);
+ else if (!canUseImproved)
+ SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
+ else
+ SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
+ }
+
+ void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
+ {
+ IClientAPI owner;
+ if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
+ {
+ LLClientView llOwner = (LLClientView)owner;
+
+ // Send an update out to the owner
+ ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
+ updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
+ //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
+ updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
+ updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
+
+ m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
+ }
+
+ // Send an update out to everyone else
+ ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
+ updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
+ //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
+ updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
+ updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
+
+ m_scene.ClientManager.ForEach(
+ delegate(IClientAPI client)
+ {
+ if (client.AgentId != obj.OwnerID && client is LLClientView)
+ {
+ LLClientView llClient = (LLClientView)client;
+ m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
+ }
+ }
+ );
+ }
+
+ void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
+ {
+ }
+
+ void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
+ {
+ }
+
+ void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
+ {
+ canUseCompressed = true;
+ canUseImproved = true;
+
+ if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
+ {
+ canUseCompressed = false;
+ canUseImproved = false;
+ }
+ else
+ {
+ if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
+ (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
+ (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
+ (updateFlags & PrimUpdateFlags.Joint) != 0)
+ {
+ canUseCompressed = false;
+ }
+
+ if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
+ (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
+ (updateFlags & PrimUpdateFlags.Scale) != 0 ||
+ (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
+ (updateFlags & PrimUpdateFlags.Text) != 0 ||
+ (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
+ (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
+ (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
+ (updateFlags & PrimUpdateFlags.Sound) != 0 ||
+ (updateFlags & PrimUpdateFlags.Particles) != 0 ||
+ (updateFlags & PrimUpdateFlags.Material) != 0 ||
+ (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
+ (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
+ (updateFlags & PrimUpdateFlags.Joint) != 0)
+ {
+ canUseImproved = false;
+ }
+ }
+ }
+
+ static ObjectUpdatePacket.ObjectDataBlock BuildUpdateBlockFromPrim(SceneObjectPart prim, UUID assetID, PrimFlags flags, uint crc)
+ {
+ byte[] objectData = new byte[60];
+ prim.OffsetPosition.ToBytes(objectData, 0);
+ prim.Velocity.ToBytes(objectData, 12);
+ prim.Acceleration.ToBytes(objectData, 24);
+ prim.RotationOffset.ToBytes(objectData, 36);
+ prim.AngularVelocity.ToBytes(objectData, 48);
+
+ ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
+ update.ClickAction = (byte)prim.ClickAction;
+ update.CRC = crc;
+ update.ExtraParams = prim.Shape.ExtraParams ?? Utils.EmptyBytes;
+ update.Flags = (byte)flags;
+ update.FullID = prim.UUID;
+ update.ID = prim.LocalId;
+ //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
+ //update.JointPivot = Vector3.Zero;
+ //update.JointType = 0;
+ update.Material = prim.Material;
+ update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
+ if (prim.IsAttachment)
+ update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + assetID);
+ else
+ update.NameValue = Utils.EmptyBytes;
+ update.ObjectData = objectData;
+ update.ParentID = prim.ParentID;
+ update.PathBegin = prim.Shape.PathBegin;
+ update.PathCurve = prim.Shape.PathCurve;
+ update.PathEnd = prim.Shape.PathEnd;
+ update.PathRadiusOffset = prim.Shape.PathRadiusOffset;
+ update.PathRevolutions = prim.Shape.PathRevolutions;
+ update.PathScaleX = prim.Shape.PathScaleX;
+ update.PathScaleY = prim.Shape.PathScaleY;
+ update.PathShearX = prim.Shape.PathShearX;
+ update.PathShearY = prim.Shape.PathShearY;
+ update.PathSkew = prim.Shape.PathSkew;
+ update.PathTaperX = prim.Shape.PathTaperX;
+ update.PathTaperY = prim.Shape.PathTaperY;
+ update.PathTwist = prim.Shape.PathTwist;
+ update.PathTwistBegin = prim.Shape.PathTwistBegin;
+ update.PCode = prim.Shape.PCode;
+ update.ProfileBegin = prim.Shape.ProfileBegin;
+ update.ProfileCurve = prim.Shape.ProfileCurve;
+ update.ProfileEnd = prim.Shape.ProfileEnd;
+ update.ProfileHollow = prim.Shape.ProfileHollow;
+ update.PSBlock = prim.ParticleSystem ?? Utils.EmptyBytes;
+ update.TextColor = new Color4(prim.Color).GetBytes(true);
+ update.TextureAnim = prim.TextureAnimation ?? Utils.EmptyBytes;
+ update.TextureEntry = prim.Shape.TextureEntry ?? Utils.EmptyBytes;
+ update.Scale = prim.Scale;
+ update.State = prim.Shape.State;
+ update.Text = Util.StringToBytes256(prim.Text);
+ update.UpdateFlags = (uint)flags;
+
+ if (prim.Sound != UUID.Zero)
+ {
+ update.Sound = prim.Sound;
+ update.OwnerID = prim.OwnerID;
+ update.Gain = (float)prim.SoundGain;
+ update.Radius = (float)prim.SoundRadius;
+ }
+
+ switch ((PCode)prim.Shape.PCode)
+ {
+ case PCode.Grass:
+ case PCode.Tree:
+ case PCode.NewTree:
+ update.Data = new byte[] { prim.Shape.State };
+ break;
+ default:
+ // TODO: Support ScratchPad
+ //if (prim.ScratchPad != null)
+ //{
+ // update.Data = new byte[prim.ScratchPad.Length];
+ // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
+ //}
+ //else
+ //{
+ // update.Data = Utils.EmptyBytes;
+ //}
+ update.Data = Utils.EmptyBytes;
+ break;
+ }
+
+ return update;
+ }*/
+
+ #endregion Prim/Avatar Updates
+
#region Avatar Packet/data sending Methods
///
@@ -3365,7 +3592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return;
if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0)
return;
-
+
if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
rotation = Quaternion.Identity;
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 66a9b5a540..cd59bdb613 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -224,11 +224,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
foreach (Scene s in m_scenes)
{
- s.ForEachScenePresence(delegate(ScenePresence presence)
- {
- TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName,
- c.Type, message, sourceType);
- });
+ s.ForEachScenePresence(
+ delegate(ScenePresence presence)
+ {
+ TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType);
+ }
+ );
}
}
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 4896edfdf6..3bb162e469 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -756,7 +756,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
public void sendRegionHandshakeToAll()
{
- m_scene.Broadcast(sendRegionHandshake);
+ m_scene.ForEachClient(sendRegionHandshake);
}
public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index d2b5cb19e5..332d3ce59e 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -1061,7 +1061,7 @@ namespace OpenSim.Region.CoreModules.World.Land
{
land.LandData.OwnerID = ownerID;
- m_scene.Broadcast(SendParcelOverlay);
+ m_scene.ForEachClient(SendParcelOverlay);
land.SendLandUpdateToClient(remote_client);
}
}
@@ -1083,7 +1083,7 @@ namespace OpenSim.Region.CoreModules.World.Land
land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
else
land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
- m_scene.Broadcast(SendParcelOverlay);
+ m_scene.ForEachClient(SendParcelOverlay);
land.SendLandUpdateToClient(remote_client);
}
}
@@ -1107,7 +1107,7 @@ namespace OpenSim.Region.CoreModules.World.Land
land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
land.LandData.IsGroupOwned = false;
- m_scene.Broadcast(SendParcelOverlay);
+ m_scene.ForEachClient(SendParcelOverlay);
land.SendLandUpdateToClient(remote_client);
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index d3d397dde2..d13d4fb8ec 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1193,15 +1193,6 @@ namespace OpenSim.Region.Framework.Scenes
m_eventManager.TriggerOnFrame();
}
- ///
- /// Perform delegate action on all clients subscribing to updates from this region.
- ///
- ///
- public void Broadcast(Action whatToDo)
- {
- ForEachScenePresence(delegate(ScenePresence presence) { whatToDo(presence.ControllingClient); });
- }
-
///
/// Backup the scene. This acts as the main method of the backup thread.
///
@@ -3048,17 +3039,13 @@ namespace OpenSim.Region.Framework.Scenes
}
m_eventManager.TriggerOnRemovePresence(agentID);
- Broadcast(delegate(IClientAPI client)
- {
- try
- {
- client.SendKillObject(avatar.RegionHandle, avatar.LocalId);
- }
- catch (NullReferenceException)
- {
- //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
- }
- });
+ ForEachClient(
+ delegate(IClientAPI client)
+ {
+ //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
+ try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); }
+ catch (NullReferenceException) { }
+ });
ForEachScenePresence(
delegate(ScenePresence presence) { presence.CoarseLocationChange(); });
@@ -3143,7 +3130,7 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
}
- Broadcast(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
+ ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
}
#endregion
@@ -4211,7 +4198,7 @@ namespace OpenSim.Region.Framework.Scenes
public void ForEachClient(Action action)
{
- m_sceneGraph.ForEachClient(action);
+ ClientManager.ForEach(action);
}
public void ForEachSOG(Action action)
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 9cd2247b3a..04397adcec 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1107,23 +1107,6 @@ namespace OpenSim.Region.Framework.Scenes
return UUID.Zero;
}
- protected internal void ForEachClient(Action action)
- {
- List splist = GetScenePresences();
- foreach (ScenePresence presence in splist)
- {
- try
- {
- action(presence.ControllingClient);
- }
- catch (Exception e)
- {
- // Catch it and move on. This includes situations where splist has inconsistent info
- m_log.WarnFormat("[SCENE]: Problem processing action in ForEachClient: ", e.Message);
- }
- }
- }
-
protected internal void ForEachSOG(Action action)
{
List objlist = new List(SceneObjectGroupsByFullID.Values);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 801a7db3a5..377cb6e987 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -853,16 +853,6 @@ if (m_shape != null) {
return m_offsetPosition + m_groupPosition; }
}
- public UUID ObjectCreator
- {
- get { return _creatorID; }
- }
-
- public UUID ObjectOwner
- {
- get { return _ownerID; }
- }
-
public SceneObjectGroup ParentGroup
{
get { return m_parentGroup; }
@@ -1440,7 +1430,7 @@ if (m_shape != null) {
// Move afterwards ResetIDs as it clears the localID
dupe.LocalId = localID;
// This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
- dupe._lastOwnerID = ObjectOwner;
+ dupe._lastOwnerID = OwnerID;
byte[] extraP = new byte[Shape.ExtraParams.Length];
Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2a06f9eb9a..387db4456b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2455,11 +2455,10 @@ namespace OpenSim.Region.Framework.Scenes
m_perfMonMS = Environment.TickCount;
Vector3 pos = m_pos;
- Vector3 vel = Velocity;
- Quaternion rot = m_bodyRot;
pos.Z -= m_appearance.HipOffset;
- remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, new Vector3(pos.X, pos.Y, pos.Z),
- new Vector3(vel.X, vel.Y, vel.Z), rot, m_uuid);
+
+ remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue),
+ LocalId, pos, Velocity, m_bodyRot, m_uuid);
m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
m_scene.StatsReporter.AddAgentUpdates(1);
@@ -2473,7 +2472,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_perfMonMS = Environment.TickCount;
- m_scene.Broadcast(SendTerseUpdateToClient);
+ m_scene.ForEachClient(SendTerseUpdateToClient);
m_lastVelocity = m_velocity;
lastPhysPos = AbsolutePosition;
@@ -2774,7 +2773,7 @@ namespace OpenSim.Region.Framework.Scenes
if (m_isChildAgent)
return;
- m_scene.Broadcast(
+ m_scene.ForEachClient(
delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); });
}
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
index ce50f9e34d..4521f8ef6a 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
@@ -259,7 +259,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
if (e.InnerException != null)
m_log.Error("[MRM] " + e.InnerException);
- m_scene.Broadcast(delegate(IClientAPI user)
+ m_scene.ForEachClient(delegate(IClientAPI user)
{
user.SendAlertMessage(
"MRM UnAuthorizedAccess: " + e);
@@ -268,7 +268,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
catch (Exception e)
{
m_log.Info("[MRM] Error: " + e);
- m_scene.Broadcast(delegate(IClientAPI user)
+ m_scene.ForEachClient(delegate(IClientAPI user)
{
user.SendAlertMessage(
"Compile error while building MRM script, check OpenSim console for more information.");