* 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

slimupdates2
unknown 2010-05-12 15:59:48 -07:00
parent 8368494554
commit bf5c81d77e
14 changed files with 712 additions and 704 deletions

View File

@ -1026,23 +1026,6 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow
}
public void SendAvatarData(SendAvatarData data)
{
//ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID);
UUID ownerID = data.AvatarID;
MXPSendAvatarData(data.FirstName + " " + data.LastName, ownerID, UUID.Zero, data.AvatarID, data.AvatarLocalID, data.Position, data.Rotation);
}
public void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
MovementEventMessage me = new MovementEventMessage();
me.ObjectIndex = data.LocalID;
me.Location = ToOmVector(data.Position);
me.Orientation = ToOmQuaternion(data.Rotation);
Session.Send(me);
}
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
// Minimap function, not used.
@ -1058,23 +1041,31 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow
}
public void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel,
data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction,
data.material, data.textureanim);
//ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID);
ScenePresence presence = (ScenePresence)avatar;
UUID ownerID = presence.UUID;
MXPSendAvatarData(presence.Firstname + " " + presence.Lastname, ownerID, UUID.Zero, presence.UUID, presence.LocalId, presence.AbsolutePosition, presence.Rotation);
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
MovementEventMessage me = new MovementEventMessage();
me.ObjectIndex = data.LocalID;
me.Location = ToOmVector(data.Position);
me.Orientation = ToOmQuaternion(data.Rotation);
Session.Send(me);
//MovementEventMessage me = new MovementEventMessage();
//me.ObjectIndex = data.LocalID;
//me.Location = ToOmVector(data.Position);
//me.Orientation = ToOmQuaternion(data.Rotation);
//MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel,
// data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction,
// data.material, data.textureanim);
//Session.Send(me);
throw new System.NotImplementedException();
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -584,16 +584,6 @@ namespace OpenSim.Client.Sirikata.ClientStack
throw new System.NotImplementedException();
}
public void SendAvatarData(SendAvatarData data)
{
throw new System.NotImplementedException();
}
public void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
throw new System.NotImplementedException();
}
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
throw new System.NotImplementedException();
@ -609,22 +599,17 @@ namespace OpenSim.Client.Sirikata.ClientStack
throw new System.NotImplementedException();
}
public void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
throw new System.NotImplementedException();
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
throw new System.NotImplementedException();
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}
public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}
@ -634,6 +619,11 @@ namespace OpenSim.Client.Sirikata.ClientStack
throw new System.NotImplementedException();
}
public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
{
throw new System.NotImplementedException();
}
public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item)
{
throw new System.NotImplementedException();

View File

@ -590,16 +590,6 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
throw new System.NotImplementedException();
}
public void SendAvatarData(SendAvatarData data)
{
throw new System.NotImplementedException();
}
public void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
throw new System.NotImplementedException();
}
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
throw new System.NotImplementedException();
@ -615,17 +605,17 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
throw new System.NotImplementedException();
}
public void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
throw new System.NotImplementedException();
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
throw new System.NotImplementedException();
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}

View File

@ -571,207 +571,6 @@ namespace OpenSim.Framework
public float dwell;
}
public struct SendAvatarData
{
public readonly ulong RegionHandle;
public readonly string FirstName;
public readonly string LastName;
public readonly string GroupTitle;
public readonly UUID AvatarID;
public readonly uint AvatarLocalID;
public readonly Vector3 Position;
public readonly byte[] TextureEntry;
public readonly uint ParentID;
public readonly Quaternion Rotation;
public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID,
uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation)
{
RegionHandle = regionHandle;
FirstName = firstName;
LastName = lastName;
GroupTitle = groupTitle;
AvatarID = avatarID;
AvatarLocalID = avatarLocalID;
Position = position;
TextureEntry = textureEntry;
ParentID = parentID;
Rotation = rotation;
}
}
public struct SendAvatarTerseData
{
public readonly ulong RegionHandle;
public readonly ushort TimeDilation;
public readonly uint LocalID;
public readonly Vector3 Position;
public readonly Vector3 Velocity;
public readonly Vector3 Acceleration;
public readonly Quaternion Rotation;
public readonly Vector4 CollisionPlane;
public readonly UUID AgentID;
public readonly byte[] TextureEntry;
public readonly double Priority;
public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity,
Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority)
{
RegionHandle = regionHandle;
TimeDilation = timeDilation;
LocalID = localID;
Position = position;
Velocity = velocity;
Acceleration = acceleration;
Rotation = rotation;
CollisionPlane = collisionPlane;
AgentID = agentid;
TextureEntry = textureEntry;
Priority = priority;
}
}
public struct SendPrimitiveTerseData
{
public readonly ulong RegionHandle;
public readonly ushort TimeDilation;
public readonly uint LocalID;
public readonly Vector3 Position;
public readonly Quaternion Rotation;
public readonly Vector3 Velocity;
public readonly Vector3 Acceleration;
public readonly Vector3 AngularVelocity;
public readonly UUID AssetID;
public readonly UUID OwnerID;
public readonly int AttachPoint;
public readonly byte[] TextureEntry;
public readonly double Priority;
public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity,
UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority)
{
RegionHandle = regionHandle;
TimeDilation = timeDilation;
LocalID = localID;
Position = position;
Rotation = rotation;
Velocity = velocity;
Acceleration = acceleration;
AngularVelocity = rotationalvelocity;
AssetID = assetID;
OwnerID = ownerID;
AttachPoint = attachPoint;
TextureEntry = textureEntry;
Priority = priority;
}
}
public struct SendPrimitiveData
{
private ulong m_regionHandle;
private ushort m_timeDilation;
private uint m_localID;
private PrimitiveBaseShape m_primShape;
private Vector3 m_pos;
private Vector3 m_vel;
private Vector3 m_acc;
private Quaternion m_rotation;
private Vector3 m_rvel;
private PrimFlags m_flags;
private UUID m_objectID;
private UUID m_ownerID;
private string m_text;
private byte[] m_color;
private uint m_parentID;
private byte[] m_particleSystem;
private byte m_clickAction;
private byte m_material;
private byte[] m_textureanim;
private bool m_attachment;
private uint m_AttachPoint;
private UUID m_AssetId;
private UUID m_SoundId;
private double m_SoundVolume;
private byte m_SoundFlags;
private double m_SoundRadius;
private double m_priority;
public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) :
this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID,
ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero,
UUID.Zero, 0, 0, 0, priority) { }
public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
uint flags,
UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
byte[] particleSystem,
byte clickAction, byte material, byte[] textureanim, bool attachment,
uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
double SoundRadius, double priority)
{
this.m_regionHandle = regionHandle;
this.m_timeDilation = timeDilation;
this.m_localID = localID;
this.m_primShape = primShape;
this.m_pos = pos;
this.m_vel = vel;
this.m_acc = acc;
this.m_rotation = rotation;
this.m_rvel = rvel;
this.m_flags = (PrimFlags)flags;
this.m_objectID = objectID;
this.m_ownerID = ownerID;
this.m_text = text;
this.m_color = color;
this.m_parentID = parentID;
this.m_particleSystem = particleSystem;
this.m_clickAction = clickAction;
this.m_material = material;
this.m_textureanim = textureanim;
this.m_attachment = attachment;
this.m_AttachPoint = AttachPoint;
this.m_AssetId = AssetId;
this.m_SoundId = SoundId;
this.m_SoundVolume = SoundVolume;
this.m_SoundFlags = SoundFlags;
this.m_SoundRadius = SoundRadius;
this.m_priority = priority;
}
public ulong regionHandle { get { return this.m_regionHandle; } }
public ushort timeDilation { get { return this.m_timeDilation; } }
public uint localID { get { return this.m_localID; } }
public PrimitiveBaseShape primShape { get { return this.m_primShape; } }
public Vector3 pos { get { return this.m_pos; } }
public Vector3 vel { get { return this.m_vel; } }
public Vector3 acc { get { return this.m_acc; } }
public Quaternion rotation { get { return this.m_rotation; } }
public Vector3 rvel { get { return this.m_rvel; } }
public PrimFlags flags { get { return this.m_flags; } }
public UUID objectID { get { return this.m_objectID; } }
public UUID ownerID { get { return this.m_ownerID; } }
public string text { get { return this.m_text; } }
public byte[] color { get { return this.m_color; } }
public uint parentID { get { return this.m_parentID; } }
public byte[] particleSystem { get { return this.m_particleSystem; } }
public byte clickAction { get { return this.m_clickAction; } }
public byte material { get { return this.m_material; } }
public byte[] textureanim { get { return this.m_textureanim; } }
public bool attachment { get { return this.m_attachment; } }
public uint AttachPoint { get { return this.m_AttachPoint; } }
public UUID AssetId { get { return this.m_AssetId; } }
public UUID SoundId { get { return this.m_SoundId; } }
public double SoundVolume { get { return this.m_SoundVolume; } }
public byte SoundFlags { get { return this.m_SoundFlags; } }
public double SoundRadius { get { return this.m_SoundRadius; } }
public double priority { get { return this.m_priority; } }
}
public struct UpdatePriorityData {
private double m_priority;
private uint m_localID;
@ -785,14 +584,46 @@ namespace OpenSim.Framework
public uint localID { get { return this.m_localID; } }
}
/// <summary>
/// Specifies the fields that have been changed when sending a prim or
/// avatar update
/// </summary>
[Flags]
public enum StateUpdateTypes
public enum PrimUpdateFlags : uint
{
None = 0,
AvatarTerse = 1,
PrimitiveTerse = AvatarTerse << 1,
PrimitiveFull = PrimitiveTerse << 1,
All = AvatarTerse | PrimitiveTerse | PrimitiveFull,
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 static class PrimUpdateFlagsExtensions
{
public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag)
{
return (updateFlags & flag) == flag;
}
}
public interface IClientAPI
@ -1186,27 +1017,20 @@ namespace OpenSim.Framework
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
void SendPayPrice(UUID objectID, int[] payPrice);
void SendAvatarData(SendAvatarData data);
void SendAvatarTerseUpdate(SendAvatarTerseData data);
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
void SetChildAgentThrottle(byte[] throttle);
void SendPrimitiveToClient(SendPrimitiveData data);
void SendPrimTerseUpdate(SendPrimitiveTerseData data);
void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
void SendAvatarDataImmediate(ISceneEntity avatar);
void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
void ReprioritizeUpdates(UpdatePriorityHandler handler);
void FlushPrimUpdates();
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
List<InventoryFolderBase> folders, int version, bool fetchFolders,
bool fetchItems);
void FlushPrimUpdates();
void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item);
/// <summary>

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
namespace OpenSim.Framework
{
public interface ISceneEntity
{
UUID UUID { get; }
uint LocalId { get; }
}
}

236
OpenSim/Framework/Lazy.cs Normal file
View File

@ -0,0 +1,236 @@
//
// Lazy.cs
//
// Authors:
// Zoltan Varga (vargaz@gmail.com)
// Marek Safar (marek.safar@gmail.com)
//
// Copyright (C) 2009 Novell
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;
using System.Diagnostics;
namespace OpenSim.Framework
{
public enum LazyThreadSafetyMode
{
None,
PublicationOnly,
ExecutionAndPublication
}
[SerializableAttribute]
[ComVisibleAttribute(false)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
public class Lazy<T>
{
T value;
bool inited;
LazyThreadSafetyMode mode;
Func<T> factory;
object monitor;
Exception exception;
public Lazy()
: this(LazyThreadSafetyMode.ExecutionAndPublication)
{
}
public Lazy(Func<T> valueFactory)
: this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
{
}
public Lazy(bool isThreadSafe)
: this(() => Activator.CreateInstance<T>(), isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
{
}
public Lazy(Func<T> valueFactory, bool isThreadSafe)
: this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
{
}
public Lazy(LazyThreadSafetyMode mode)
: this(() => Activator.CreateInstance<T>(), mode)
{
}
public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
{
if (valueFactory == null)
throw new ArgumentNullException("valueFactory");
this.factory = valueFactory;
if (mode != LazyThreadSafetyMode.None)
monitor = new object();
this.mode = mode;
}
// Don't trigger expensive initialization
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public T Value
{
get
{
if (inited)
return value;
if (exception != null)
throw exception;
return InitValue();
}
}
T InitValue()
{
switch (mode)
{
case LazyThreadSafetyMode.None:
{
var init_factory = factory;
if (init_factory == null)
throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
try
{
factory = null;
T v = init_factory();
value = v;
Thread.MemoryBarrier();
inited = true;
}
catch (Exception ex)
{
exception = ex;
throw;
}
break;
}
case LazyThreadSafetyMode.PublicationOnly:
{
var init_factory = factory;
T v;
//exceptions are ignored
if (init_factory != null)
v = init_factory();
else
v = default(T);
lock (monitor)
{
if (inited)
return value;
value = v;
Thread.MemoryBarrier();
inited = true;
factory = null;
}
break;
}
case LazyThreadSafetyMode.ExecutionAndPublication:
{
lock (monitor)
{
if (inited)
return value;
if (factory == null)
throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
var init_factory = factory;
try
{
factory = null;
T v = init_factory();
value = v;
Thread.MemoryBarrier();
inited = true;
}
catch (Exception ex)
{
exception = ex;
throw;
}
}
break;
}
default:
throw new InvalidOperationException("Invalid LazyThreadSafetyMode " + mode);
}
if (monitor == null)
{
value = factory();
inited = true;
}
else
{
lock (monitor)
{
if (inited)
return value;
if (factory == null)
throw new InvalidOperationException("The initialization function tries to access Value on this instance");
var init_factory = factory;
try
{
factory = null;
T v = init_factory();
value = v;
Thread.MemoryBarrier();
inited = true;
}
catch
{
factory = init_factory;
throw;
}
}
}
return value;
}
public bool IsValueCreated
{
get
{
return inited;
}
}
public override string ToString()
{
if (inited)
return value.ToString();
else
return "Value is not created";
}
}
}

View File

@ -50,43 +50,17 @@ using Nini.Config;
namespace OpenSim.Region.ClientStack.LindenUDP
{
#region Enums
/// <summary>
/// Specifies the fields that have been changed when sending a prim or
/// avatar update
/// </summary>
[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<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
private PriorityQueue<double, EntityUpdate> m_entityUpdates;
/// <value>
/// 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<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
m_entityUpdates = new PriorityQueue<double, EntityUpdate>(m_scene.Entities.Count);
m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
m_killRecord = new HashSet<uint>();
@ -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
/// <summary>
/// Send an ObjectUpdate packet with information about an avatar
/// </summary>
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);
}
/// <summary>
/// Send a terse positional/rotation/velocity update about an avatar
/// to the client. This avatar can be that of the client itself.
/// </summary>
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<UUID> users, List<Vector3> 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)
/// <summary>
/// Generate one of the object update packets based on PrimUpdateFlags
/// and broadcast the packet to clients
/// </summary>
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;
}
double priority;
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 (entity is SceneObjectPart)
priority = ((SceneObjectPart)entity).ParentGroup.GetUpdatePriority(this);
else if (entity is ScenePresence)
priority = ((ScenePresence)entity).GetUpdatePriority(this);
else
priority = 0.0d;
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;
ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
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<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
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
if (!m_killRecord.Contains(block.ID))
PrimUpdateFlags updateFlags = update.Flags;
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
// {
// m_log.WarnFormat(
// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name);
// }
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 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);
}
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
if (data.Priority == double.NaN)
{
m_log.Error("[LLClientView] SendPrimTerseUpdate 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;
#region Packet Sending
if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
return;
const float TIME_DILATION = 1.0f;
ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
lock (m_primTerseUpdates.SyncRoot)
m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
}
void ProcessPrimTerseUpdates()
{
ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
outPacket.Header.Reliable = false;
outPacket.Header.Zerocoded = true;
outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
lock (m_primTerseUpdates.SyncRoot)
if (objectUpdateBlocks.IsValueCreated)
{
int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket);
if (count == 0)
return;
List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
for (int i = 0; i < count; i++)
outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
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];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
OutPacket(packet, ThrottleOutPacketType.Task, true);
}
OutPacket(outPacket, ThrottleOutPacketType.State);
if (compressedUpdateBlocks.IsValueCreated)
{
List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
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];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
OutPacket(packet, ThrottleOutPacketType.Task, true);
}
if (terseUpdateBlocks.IsValueCreated)
{
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> 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];
for (int i = 0; i < blocks.Count; i++)
packet.ObjectData[i] = blocks[i];
OutPacket(packet, ThrottleOutPacketType.Task, true);
}
#endregion Packet Sending
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
delegate(ref double priority, uint local_id)
{
priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN;
};
PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
//m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
PriorityQueue<double, EntityUpdate>.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.ObjectData = objectData;
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)
{
update.Sound = data.SoundId;
update.OwnerID = data.ownerID;
update.Gain = (float)data.SoundVolume;
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)

View File

@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>The measured resolution of Environment.TickCount</summary>
public readonly float TickCountResolution;
/// <summary>Number of terse prim updates to put on the queue each time the
/// <summary>Number of prim updates to put on the queue each time the
/// OnQueueEmpty event is triggered for updates</summary>
public readonly int PrimTerseUpdatesPerPacket;
/// <summary>Number of terse avatar updates to put on the queue each time the
/// OnQueueEmpty event is triggered for updates</summary>
public readonly int AvatarTerseUpdatesPerPacket;
/// <summary>Number of full prim updates to put on the queue each time the
/// OnQueueEmpty event is triggered for updates</summary>
public readonly int PrimFullUpdatesPerPacket;
public readonly int PrimUpdatesPerCallback;
/// <summary>Number of texture packets to put on the queue each time the
/// OnQueueEmpty event is triggered for textures</summary>
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;
}

View File

@ -528,14 +528,6 @@ namespace OpenSim.Region.Examples.SimpleModule
{
}
public virtual void SendAvatarData(SendAvatarData data)
{
}
public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
}
public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
}
@ -548,15 +540,15 @@ namespace OpenSim.Region.Examples.SimpleModule
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
#endregion Enumerations
public class SceneObjectPart : IScriptHost
public class SceneObjectPart : IScriptHost, ISceneEntity
{
/// <value>
/// Denote all sides of the prim
@ -712,6 +712,24 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public Vector3 RelativePosition
{
get
{
if (IsRoot)
{
if (IsAttachment)
return AttachedPos;
else
return AbsolutePosition;
}
else
{
return OffsetPosition;
}
}
}
public Quaternion RotationOffset
{
get
@ -973,7 +991,6 @@ namespace OpenSim.Region.Framework.Scenes
get { return AggregateScriptEvents; }
}
public Quaternion SitTargetOrientation
{
get { return m_sitTargetOrientation; }
@ -2925,11 +2942,7 @@ namespace OpenSim.Region.Framework.Scenes
//if (LocalId != ParentGroup.RootPart.LocalId)
//isattachment = ParentGroup.RootPart.IsAttachment;
byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape,
lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID,
m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient)));
remoteClient.SendPrimUpdate(this, PrimUpdateFlags.FullUpdate);
}
/// <summary>
@ -4640,11 +4653,7 @@ namespace OpenSim.Region.Framework.Scenes
// Causes this thread to dig into the Client Thread Data.
// Remember your locking here!
remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle,
m_parentGroup.GetTimeDilation(), LocalId, lPos,
RotationOffset, Velocity, Acceleration,
AngularVelocity, FromItemID,
OwnerID, (int)AttachmentPoint, null, ParentGroup.GetUpdatePriority(remoteClient)));
remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
}
public void AddScriptLPS(int count)
@ -4694,7 +4703,8 @@ namespace OpenSim.Region.Framework.Scenes
public Color4 GetTextColor()
{
return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A));
Color color = Color;
return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
}
}
}

View File

@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence);
public class ScenePresence : EntityBase
public class ScenePresence : EntityBase, ISceneEntity
{
// ~ScenePresence()
// {
@ -478,6 +478,12 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public Vector3 OffsetPosition
{
get { return m_pos; }
set { m_pos = value; }
}
/// <summary>
/// Current velocity of the avatar.
/// </summary>
@ -1036,8 +1042,9 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
}
ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
//ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
// AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
}
public void AddNeighbourRegion(ulong regionHandle, string cap)
@ -2360,8 +2367,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
pos, velocity, Vector3.Zero, m_bodyRot, CollisionPlane, m_uuid, null, GetUpdatePriority(remoteClient)));
remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
m_scene.StatsReporter.AddAgentUpdates(1);
@ -2457,9 +2463,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset;
remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
LocalId, pos, m_appearance.Texture.GetBytes(),
m_parentID, m_bodyRot));
remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
m_scene.StatsReporter.AddAgentUpdates(1);
}
@ -2527,8 +2531,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset;
m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
m_controllingClient.SendAvatarDataImmediate(this);
SendInitialFullUpdateToAllClients();
SendAppearanceToAllOtherAgents();
@ -2638,9 +2641,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset;
m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
m_controllingClient.SendAvatarDataImmediate(this);
}
public void SetWearable(int wearableId, AvatarWearable wearable)
@ -3906,7 +3907,7 @@ namespace OpenSim.Region.Framework.Scenes
private void Reprioritize(object sender, ElapsedEventArgs e)
{
m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority);
m_controllingClient.ReprioritizeUpdates(UpdatePriority);
lock (m_reprioritization_timer)
{

View File

@ -1045,16 +1045,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void SendAvatarData(SendAvatarData data)
{
}
public void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
}
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
@ -1065,22 +1055,22 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void SetChildAgentThrottle(byte[] throttle)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
}
public void SendPrimitiveToClient(SendPrimitiveData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void FlushPrimUpdates()
{
}
@ -1090,11 +1080,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void FlushPrimUpdates()
{
}
public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item)
{
@ -1420,6 +1405,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public virtual void SetChildAgentThrottle(byte[] throttle)
{
}
public byte[] GetThrottlesPacked(float multiplier)
{
return new byte[0];

View File

@ -618,14 +618,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
public virtual void SendAvatarData(SendAvatarData data)
{
}
public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
}
public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
}
@ -638,15 +630,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -621,14 +621,6 @@ namespace OpenSim.Tests.Common.Mock
{
}
public virtual void SendAvatarData(SendAvatarData data)
{
}
public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
{
}
public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
}
@ -641,15 +633,15 @@ namespace OpenSim.Tests.Common.Mock
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
public void SendAvatarDataImmediate(ISceneEntity avatar)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}