From bf5c81d77e492cd6df5517ecab32cd64168b01c2 Mon Sep 17 00:00:00 2001
From: unknown
Date: Wed, 12 May 2010 15:59:48 -0700
Subject: * Initial commit of the slimupdates2 rewrite. This pass maintains the
original behavior of avatar update sending and has a simplified set of
IClientAPI methods for sending avatar/prim updates
---
.../Region/ClientStack/LindenUDP/LLClientView.cs | 627 ++++++++++-----------
.../Region/ClientStack/LindenUDP/LLUDPServer.cs | 18 +-
2 files changed, 304 insertions(+), 341 deletions(-)
(limited to 'OpenSim/Region/ClientStack/LindenUDP')
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1f3582c..6154da4 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -50,43 +50,17 @@ 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
+ public class EntityUpdate
{
- 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
- }
+ public ISceneEntity Entity;
+ public PrimUpdateFlags Flags;
- #endregion Enums
+ public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags)
+ {
+ Entity = entity;
+ Flags = flags;
+ }
+ }
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
@@ -350,9 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private readonly IGroupsModule m_GroupsModule;
private int m_cachedTextureSerial;
- protected PriorityQueue m_avatarTerseUpdates;
- private PriorityQueue m_primTerseUpdates;
- private PriorityQueue m_primFullUpdates;
+ private PriorityQueue m_entityUpdates;
///
/// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -463,9 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_scene = scene;
- m_avatarTerseUpdates = new PriorityQueue();
- m_primTerseUpdates = new PriorityQueue();
- m_primFullUpdates = new PriorityQueue(m_scene.Entities.Count);
+ m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
m_fullUpdateDataBlocksBuilder = new List();
m_killRecord = new HashSet();
@@ -1519,7 +1489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
kill.Header.Reliable = true;
kill.Header.Zerocoded = true;
- lock (m_primFullUpdates.SyncRoot)
+ lock (m_entityUpdates.SyncRoot)
{
m_killRecord.Add(localID);
OutPacket(kill, ThrottleOutPacketType.State);
@@ -3419,71 +3389,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// Send an ObjectUpdate packet with information about an avatar
///
- public void SendAvatarData(SendAvatarData data)
+ public void SendAvatarDataImmediate(ISceneEntity avatar)
{
+ ScenePresence presence = avatar as ScenePresence;
+ if (presence == null)
+ return;
+
ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
objupdate.Header.Zerocoded = true;
- objupdate.RegionData.RegionHandle = data.RegionHandle;
+ objupdate.RegionData.RegionHandle = presence.RegionHandle;
objupdate.RegionData.TimeDilation = ushort.MaxValue;
objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
- objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
+ objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
OutPacket(objupdate, ThrottleOutPacketType.Task);
}
- ///
- /// Send a terse positional/rotation/velocity update about an avatar
- /// to the client. This avatar can be that of the client itself.
- ///
- public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
- {
- if (data.Priority == double.NaN)
- {
- m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
- return;
- }
-
- Quaternion rotation = data.Rotation;
- if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
- rotation = Quaternion.Identity;
-
- ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
-
- lock (m_avatarTerseUpdates.SyncRoot)
- m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
-
- // If we received an update about our own avatar, process the avatar update priority queue immediately
- if (data.AgentID == m_agentId)
- ProcessAvatarTerseUpdates();
- }
-
- protected void ProcessAvatarTerseUpdates()
- {
- ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
- terse.Header.Reliable = false;
- terse.Header.Zerocoded = true;
-
- //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
- terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
- terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
-
- lock (m_avatarTerseUpdates.SyncRoot)
- {
- int count = Math.Min(m_avatarTerseUpdates.Count, m_udpServer.AvatarTerseUpdatesPerPacket);
- if (count == 0)
- return;
-
- terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
- for (int i = 0; i < count; i++)
- terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
- }
-
- // HACK: Using the task category until the tiered reprioritization code is in
- OutPacket(terse, ThrottleOutPacketType.Task);
- }
-
public void SendCoarseLocationUpdate(List users, List CoarseLocations)
{
if (!IsActive) return; // We don't need to update inactive clients.
@@ -3528,172 +3451,188 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Primitive Packet/Data Sending Methods
- public void SendPrimitiveToClient(SendPrimitiveData data)
+ ///
+ /// Generate one of the object update packets based on PrimUpdateFlags
+ /// and broadcast the packet to clients
+ ///
+ public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
-// string text = data.text;
-// if (text.IndexOf("\n") >= 0)
-// text = text.Remove(text.IndexOf("\n"));
-// m_log.DebugFormat(
-// "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}",
-// data.localID, text, Name);
-
- if (data.priority == double.NaN)
- {
- m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
- return;
- }
-
- Quaternion rotation = data.rotation;
- if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
- rotation = Quaternion.Identity;
-
- if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
- return;
- if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
- return;
+ double priority;
- ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
+ if (entity is SceneObjectPart)
+ priority = ((SceneObjectPart)entity).ParentGroup.GetUpdatePriority(this);
+ else if (entity is ScenePresence)
+ priority = ((ScenePresence)entity).GetUpdatePriority(this);
+ else
+ priority = 0.0d;
- lock (m_primFullUpdates.SyncRoot)
- m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
+ lock (m_entityUpdates.SyncRoot)
+ m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId);
}
- void ProcessPrimFullUpdates()
+ private void ProcessEntityUpdates(int maxUpdates)
{
- ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
- outPacket.Header.Zerocoded = true;
+ Lazy> objectUpdateBlocks = new Lazy>();
+ Lazy> compressedUpdateBlocks = new Lazy>();
+ Lazy> terseUpdateBlocks = new Lazy>();
- outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
- outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
+ int updatesThisCall = 0;
- lock (m_primFullUpdates.SyncRoot)
+ lock (m_entityUpdates.SyncRoot)
{
- int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket);
- if (count == 0)
- return;
-
- m_fullUpdateDataBlocksBuilder.Clear();
-
- for (int i = 0; i < count; i++)
+ EntityUpdate update;
+ while (m_entityUpdates.TryDequeue(out update))
{
- ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue();
+ #region UpdateFlags to packet type conversion
+
+ PrimUpdateFlags updateFlags = update.Flags;
- if (!m_killRecord.Contains(block.ID))
+ bool canUseCompressed = true;
+ bool canUseImproved = true;
+
+ // Compressed object updates only make sense for LL primitives
+ if (!(update.Entity is SceneObjectPart))
+ canUseCompressed = false;
+
+ if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
{
- m_fullUpdateDataBlocksBuilder.Add(block);
-
-// string text = Util.FieldToString(outPacket.ObjectData[i].Text);
-// if (text.IndexOf("\n") >= 0)
-// text = text.Remove(text.IndexOf("\n"));
-// m_log.DebugFormat(
-// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}",
-// outPacket.ObjectData[i].ID, text, Name);
+ canUseCompressed = false;
+ canUseImproved = false;
+ }
+ else
+ {
+ if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
+ updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Joint))
+ {
+ canUseCompressed = false;
+ }
+
+ if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
+ updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
+ updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Text) ||
+ updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
+ updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
+ updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Material) ||
+ updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
+ updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
+ updateFlags.HasFlag(PrimUpdateFlags.Joint))
+ {
+ canUseImproved = false;
+ }
+ }
+
+ #endregion UpdateFlags to packet type conversion
+
+ #region Block Construction
+
+ // TODO: Remove this once we can build compressed updates
+ canUseCompressed = false;
+
+ if (!canUseImproved && !canUseCompressed)
+ {
+ if (update.Entity is ScenePresence)
+ objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
+ else
+ objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
}
-// else
-// {
-// m_log.WarnFormat(
-// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name);
-// }
+ else if (!canUseImproved)
+ {
+ compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
+ }
+ else
+ {
+ terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
+ }
+
+ #endregion Block Construction
+
+ ++updatesThisCall;
+ if (maxUpdates > 0 && updatesThisCall >= maxUpdates)
+ break;
}
+ }
- outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray();
-
- OutPacket(outPacket, ThrottleOutPacketType.State);
- }
- }
+ #region Packet Sending
- public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
- {
- if (data.Priority == double.NaN)
+ const float TIME_DILATION = 1.0f;
+ ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
+
+ if (objectUpdateBlocks.IsValueCreated)
{
- m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
- return;
- }
+ List blocks = objectUpdateBlocks.Value;
- Quaternion rotation = data.Rotation;
- if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
- rotation = Quaternion.Identity;
+ ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
+ packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+ packet.RegionData.TimeDilation = timeDilation;
+ packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
- if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
- return;
+ for (int i = 0; i < blocks.Count; i++)
+ packet.ObjectData[i] = blocks[i];
+
+ OutPacket(packet, ThrottleOutPacketType.Task, true);
+ }
- ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
+ if (compressedUpdateBlocks.IsValueCreated)
+ {
+ List blocks = compressedUpdateBlocks.Value;
- lock (m_primTerseUpdates.SyncRoot)
- m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
- }
+ ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
+ packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+ packet.RegionData.TimeDilation = timeDilation;
+ packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
- void ProcessPrimTerseUpdates()
- {
- ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
- outPacket.Header.Reliable = false;
- outPacket.Header.Zerocoded = true;
+ for (int i = 0; i < blocks.Count; i++)
+ packet.ObjectData[i] = blocks[i];
- outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
- outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
+ OutPacket(packet, ThrottleOutPacketType.Task, true);
+ }
- lock (m_primTerseUpdates.SyncRoot)
+ if (terseUpdateBlocks.IsValueCreated)
{
- int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket);
- if (count == 0)
- return;
+ List blocks = terseUpdateBlocks.Value;
+
+ ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
+ packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+ packet.RegionData.TimeDilation = timeDilation;
+ packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
- outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
- for (int i = 0; i < count; i++)
- outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
+ for (int i = 0; i < blocks.Count; i++)
+ packet.ObjectData[i] = blocks[i];
+
+ OutPacket(packet, ThrottleOutPacketType.Task, true);
}
- OutPacket(outPacket, ThrottleOutPacketType.State);
+ #endregion Packet Sending
}
- public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
+ public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
- PriorityQueue.UpdatePriorityHandler terse_update_priority_handler =
- delegate(ref double priority, uint local_id)
- {
- priority = handler(new UpdatePriorityData(priority, local_id));
- return priority != double.NaN;
- };
- PriorityQueue.UpdatePriorityHandler update_priority_handler =
+ //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
+
+ PriorityQueue.UpdatePriorityHandler update_priority_handler =
delegate(ref double priority, uint local_id)
{
priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN;
};
- if ((type & StateUpdateTypes.AvatarTerse) != 0)
- {
- lock (m_avatarTerseUpdates.SyncRoot)
- m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
- }
-
- if ((type & StateUpdateTypes.PrimitiveFull) != 0)
- {
- lock (m_primFullUpdates.SyncRoot)
- m_primFullUpdates.Reprioritize(update_priority_handler);
- }
-
- if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
- {
- lock (m_primTerseUpdates.SyncRoot)
- m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
- }
+ lock (m_entityUpdates.SyncRoot)
+ m_entityUpdates.Reprioritize(update_priority_handler);
}
public void FlushPrimUpdates()
{
- while (m_primFullUpdates.Count > 0)
- {
- ProcessPrimFullUpdates();
- }
- while (m_primTerseUpdates.Count > 0)
- {
- ProcessPrimTerseUpdates();
- }
- while (m_avatarTerseUpdates.Count > 0)
- {
- ProcessAvatarTerseUpdates();
- }
+ m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
+
+ while (m_entityUpdates.Count > 0)
+ ProcessEntityUpdates(-1);
}
#endregion Primitive Packet/Data Sending Methods
@@ -3726,26 +3665,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
{
- lock (m_avatarTerseUpdates.SyncRoot)
- {
- if (m_avatarTerseUpdates.Count > 0)
- ProcessAvatarTerseUpdates();
- }
- }
-
- if ((categories & ThrottleOutPacketTypeFlags.State) != 0)
- {
- lock (m_primFullUpdates.SyncRoot)
- {
- if (m_primFullUpdates.Count > 0)
- ProcessPrimFullUpdates();
- }
-
- lock (m_primTerseUpdates.SyncRoot)
- {
- if (m_primTerseUpdates.Count > 0)
- ProcessPrimTerseUpdates();
- }
+ if (m_entityUpdates.Count > 0)
+ ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback);
}
if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -4403,22 +4324,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Helper Methods
- protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
+ protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
{
- return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
- data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
- }
+ #region ScenePresence/SOP Handling
- protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
- {
- return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity,
- data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
- }
+ bool avatar = (entity is ScenePresence);
+ uint localID = entity.LocalId;
+ uint attachPoint;
+ Vector4 collisionPlane;
+ Vector3 position, velocity, acceleration, angularVelocity;
+ Quaternion rotation;
+ byte[] textureEntry;
+
+ if (entity is ScenePresence)
+ {
+ ScenePresence presence = (ScenePresence)entity;
+
+ attachPoint = 0;
+ collisionPlane = presence.CollisionPlane;
+ position = presence.OffsetPosition;
+ velocity = presence.Velocity;
+ acceleration = Vector3.Zero;
+ angularVelocity = Vector3.Zero;
+ rotation = presence.Rotation;
+
+ if (sendTexture)
+ textureEntry = presence.Appearance.Texture.GetBytes();
+ else
+ textureEntry = null;
+ }
+ else
+ {
+ SceneObjectPart part = (SceneObjectPart)entity;
+
+ attachPoint = part.AttachmentPoint;
+ collisionPlane = Vector4.Zero;
+ position = part.RelativePosition;
+ velocity = part.Velocity;
+ acceleration = part.Acceleration;
+ angularVelocity = part.AngularVelocity;
+ rotation = part.RotationOffset;
+ textureEntry = part.Shape.TextureEntry;
+ }
+
+ #endregion ScenePresence/SOP Handling
- protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint,
- Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
- Vector3 angularVelocity, byte[] textureEntry)
- {
int pos = 0;
byte[] data = new byte[(avatar ? 60 : 44)];
@@ -4490,12 +4440,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return block;
}
- protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data)
+ protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
{
byte[] objectData = new byte[76];
- Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support
- data.Position.ToBytes(objectData, 16);
+ data.CollisionPlane.ToBytes(objectData, 0);
+ data.OffsetPosition.ToBytes(objectData, 16);
//data.Velocity.ToBytes(objectData, 28);
//data.Acceleration.ToBytes(objectData, 40);
data.Rotation.ToBytes(objectData, 52);
@@ -4505,12 +4455,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.Data = Utils.EmptyBytes;
update.ExtraParams = new byte[1];
- update.FullID = data.AvatarID;
- update.ID = data.AvatarLocalID;
+ update.FullID = data.UUID;
+ update.ID = data.LocalId;
update.Material = (byte)Material.Flesh;
update.MediaURL = Utils.EmptyBytes;
- update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " +
- data.LastName + "\nTitle STRING RW SV " + data.GroupTitle);
+ update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
+ data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
update.ObjectData = objectData;
update.ParentID = data.ParentID;
update.PathCurve = 16;
@@ -4519,102 +4469,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.PCode = (byte)PCode.Avatar;
update.ProfileCurve = 1;
update.PSBlock = Utils.EmptyBytes;
- update.Scale = new Vector3(0.45f,0.6f,1.9f);
+ update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
update.Text = Utils.EmptyBytes;
update.TextColor = new byte[4];
update.TextureAnim = Utils.EmptyBytes;
- update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes;
- update.UpdateFlags = (uint)(PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectOwnerModify);//61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags
+ update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
+ update.UpdateFlags = (uint)(
+ PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
+ PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
+ PrimFlags.ObjectOwnerModify);
return update;
}
- protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data)
+ protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
{
byte[] objectData = new byte[60];
- data.pos.ToBytes(objectData, 0);
- data.vel.ToBytes(objectData, 12);
- data.acc.ToBytes(objectData, 24);
- data.rotation.ToBytes(objectData, 36);
- data.rvel.ToBytes(objectData, 48);
+ data.RelativePosition.ToBytes(objectData, 0);
+ data.Velocity.ToBytes(objectData, 12);
+ data.Acceleration.ToBytes(objectData, 24);
+ data.RotationOffset.ToBytes(objectData, 36);
+ data.AngularVelocity.ToBytes(objectData, 48);
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
- update.ClickAction = (byte)data.clickAction;
+ update.ClickAction = (byte)data.ClickAction;
update.CRC = 0;
- update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes;
- update.FullID = data.objectID;
- update.ID = data.localID;
+ update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
+ update.FullID = data.UUID;
+ update.ID = data.LocalId;
//update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
//update.JointPivot = Vector3.Zero;
//update.JointType = 0;
- update.Material = data.material;
+ update.Material = data.Material;
update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
- if (data.attachment)
+ if (data.IsAttachment)
{
- update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId);
- update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
+ update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
+ update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
}
else
{
update.NameValue = Utils.EmptyBytes;
- update.State = data.primShape.State;
+ update.State = data.Shape.State;
}
+
update.ObjectData = objectData;
- update.ParentID = data.parentID;
- update.PathBegin = data.primShape.PathBegin;
- update.PathCurve = data.primShape.PathCurve;
- update.PathEnd = data.primShape.PathEnd;
- update.PathRadiusOffset = data.primShape.PathRadiusOffset;
- update.PathRevolutions = data.primShape.PathRevolutions;
- update.PathScaleX = data.primShape.PathScaleX;
- update.PathScaleY = data.primShape.PathScaleY;
- update.PathShearX = data.primShape.PathShearX;
- update.PathShearY = data.primShape.PathShearY;
- update.PathSkew = data.primShape.PathSkew;
- update.PathTaperX = data.primShape.PathTaperX;
- update.PathTaperY = data.primShape.PathTaperY;
- update.PathTwist = data.primShape.PathTwist;
- update.PathTwistBegin = data.primShape.PathTwistBegin;
- update.PCode = data.primShape.PCode;
- update.ProfileBegin = data.primShape.ProfileBegin;
- update.ProfileCurve = data.primShape.ProfileCurve;
- update.ProfileEnd = data.primShape.ProfileEnd;
- update.ProfileHollow = data.primShape.ProfileHollow;
- update.PSBlock = data.particleSystem ?? Utils.EmptyBytes;
- update.TextColor = data.color ?? Color4.Black.GetBytes(true);
- update.TextureAnim = data.textureanim ?? Utils.EmptyBytes;
- update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes;
- update.Scale = data.primShape.Scale;
- update.Text = Util.StringToBytes256(data.text);
- update.UpdateFlags = (uint)data.flags;
-
- if (data.SoundId != UUID.Zero)
- {
- update.Sound = data.SoundId;
- update.OwnerID = data.ownerID;
- update.Gain = (float)data.SoundVolume;
+ update.ParentID = data.ParentID;
+ update.PathBegin = data.Shape.PathBegin;
+ update.PathCurve = data.Shape.PathCurve;
+ update.PathEnd = data.Shape.PathEnd;
+ update.PathRadiusOffset = data.Shape.PathRadiusOffset;
+ update.PathRevolutions = data.Shape.PathRevolutions;
+ update.PathScaleX = data.Shape.PathScaleX;
+ update.PathScaleY = data.Shape.PathScaleY;
+ update.PathShearX = data.Shape.PathShearX;
+ update.PathShearY = data.Shape.PathShearY;
+ update.PathSkew = data.Shape.PathSkew;
+ update.PathTaperX = data.Shape.PathTaperX;
+ update.PathTaperY = data.Shape.PathTaperY;
+ update.PathTwist = data.Shape.PathTwist;
+ update.PathTwistBegin = data.Shape.PathTwistBegin;
+ update.PCode = data.Shape.PCode;
+ update.ProfileBegin = data.Shape.ProfileBegin;
+ update.ProfileCurve = data.Shape.ProfileCurve;
+ update.ProfileEnd = data.Shape.ProfileEnd;
+ update.ProfileHollow = data.Shape.ProfileHollow;
+ update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
+ update.TextColor = data.GetTextColor().GetBytes(false);
+ update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
+ update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
+ update.Scale = data.Shape.Scale;
+ update.Text = Util.StringToBytes256(data.Text);
+
+ #region PrimFlags
+
+ PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
+
+ // Don't send the CreateSelected flag to everyone
+ flags &= ~PrimFlags.CreateSelected;
+
+ if (recipientID == data.OwnerID)
+ {
+ if ((data.Flags & PrimFlags.CreateSelected) != 0)
+ {
+ // Only send this flag once, then unset it
+ flags |= PrimFlags.CreateSelected;
+ data.Flags &= ~PrimFlags.CreateSelected;
+ }
+ }
+
+ update.UpdateFlags = (uint)flags;
+
+ #endregion PrimFlags
+
+ if (data.Sound != UUID.Zero)
+ {
+ update.Sound = data.Sound;
+ update.OwnerID = data.OwnerID;
+ update.Gain = (float)data.SoundGain;
update.Radius = (float)data.SoundRadius;
update.Flags = data.SoundFlags;
}
- switch ((PCode)data.primShape.PCode)
+ switch ((PCode)data.Shape.PCode)
{
case PCode.Grass:
case PCode.Tree:
case PCode.NewTree:
- update.Data = new byte[] { data.primShape.State };
+ update.Data = new byte[] { data.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;
}
@@ -4622,6 +4586,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return update;
}
+ protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
+ {
+ // TODO: Implement this
+ return null;
+ }
+
public void SendNameReply(UUID profileId, string firstname, string lastname)
{
UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
@@ -11644,7 +11614,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
}
- internal TValue Dequeue()
+ internal bool TryDequeue(out TValue value)
{
for (int i = 0; i < m_heaps.Length; ++i)
{
@@ -11652,10 +11622,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
MinHeapItem item = m_heaps[i].RemoveMin();
m_lookupTable.Remove(item.LocalID);
- return item.Value;
+ value = item.Value;
+ return true;
}
}
- throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
+
+ value = default(TValue);
+ return false;
}
internal void Reprioritize(UpdatePriorityHandler handler)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 41e41e4..1b81105 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// The measured resolution of Environment.TickCount
public readonly float TickCountResolution;
- /// Number of terse prim updates to put on the queue each time the
+ /// Number of prim updates to put on the queue each time the
/// OnQueueEmpty event is triggered for updates
- public readonly int PrimTerseUpdatesPerPacket;
- /// Number of terse avatar updates to put on the queue each time the
- /// OnQueueEmpty event is triggered for updates
- public readonly int AvatarTerseUpdatesPerPacket;
- /// Number of full prim updates to put on the queue each time the
- /// OnQueueEmpty event is triggered for updates
- public readonly int PrimFullUpdatesPerPacket;
+ public readonly int PrimUpdatesPerCallback;
/// Number of texture packets to put on the queue each time the
/// OnQueueEmpty event is triggered for textures
public readonly int TextureSendLimit;
@@ -191,9 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
- PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25);
- AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
- PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
+ PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
TextureSendLimit = config.GetInt("TextureSendLimit", 20);
m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -201,9 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
else
{
- PrimTerseUpdatesPerPacket = 25;
- AvatarTerseUpdatesPerPacket = 10;
- PrimFullUpdatesPerPacket = 100;
+ PrimUpdatesPerCallback = 100;
TextureSendLimit = 20;
}
--
cgit v1.1