Initial commit of the slimupdate refactoring. This changes the way ScenePresence and SOP updates are sent by specifying an enum of what fields changed instead of what packet type to send, isolating packet sending logic to LLClientView and allowing more terse packets to be sent in some cases.

slimupdates
John Hurliman 2010-05-04 16:20:43 -07:00
parent 40df4e7203
commit 91878f79b9
16 changed files with 698 additions and 818 deletions

View File

@ -1026,28 +1026,17 @@ 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.
}
public void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
// TODO: Implement this
throw new System.NotImplementedException();
}
public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
// Need to translate to MXP somehow
@ -1058,23 +1047,7 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow
}
public void SendPrimitiveToClient(SendPrimitiveData data)
{
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);
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
MovementEventMessage me = new MovementEventMessage();
me.ObjectIndex = data.LocalID;
me.Location = ToOmVector(data.Position);
me.Orientation = ToOmQuaternion(data.Rotation);
Session.Send(me);
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -584,21 +584,16 @@ 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();
}
public void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
throw new System.NotImplementedException();
}
public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
throw new System.NotImplementedException();
@ -609,17 +604,7 @@ namespace OpenSim.Client.Sirikata.ClientStack
throw new System.NotImplementedException();
}
public void SendPrimitiveToClient(SendPrimitiveData data)
{
throw new System.NotImplementedException();
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
throw new System.NotImplementedException();
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}

View File

@ -590,21 +590,16 @@ 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();
}
public void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
throw new System.NotImplementedException();
}
public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
throw new System.NotImplementedException();
@ -615,17 +610,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
throw new System.NotImplementedException();
}
public void SendPrimitiveToClient(SendPrimitiveData data)
{
throw new System.NotImplementedException();
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
throw new System.NotImplementedException();
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}

View File

@ -33,6 +33,52 @@ using OpenMetaverse.Packets;
namespace OpenSim.Framework
{
#region Enums
/// <summary>
/// Specifies the fields that have been changed when sending a prim or
/// avatar update
/// </summary>
[Flags]
public enum PrimUpdateFlags : uint
{
None = 0,
AttachmentPoint = 1 << 0,
Material = 1 << 1,
ClickAction = 1 << 2,
Scale = 1 << 3,
ParentID = 1 << 4,
PrimFlags = 1 << 5,
PrimData = 1 << 6,
MediaURL = 1 << 7,
ScratchPad = 1 << 8,
Textures = 1 << 9,
TextureAnim = 1 << 10,
NameValue = 1 << 11,
Position = 1 << 12,
Rotation = 1 << 13,
Velocity = 1 << 14,
Acceleration = 1 << 15,
AngularVelocity = 1 << 16,
CollisionPlane = 1 << 17,
Text = 1 << 18,
Particles = 1 << 19,
ExtraData = 1 << 20,
Sound = 1 << 21,
Joint = 1 << 22,
FullUpdate = UInt32.MaxValue
}
public static class PrimUpdateFlagsExtensions
{
public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag)
{
return (updateFlags & flag) == flag;
}
}
#endregion Enums
#region Client API Delegate definitions
public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args);
@ -571,207 +617,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,16 +630,6 @@ namespace OpenSim.Framework
public uint localID { get { return this.m_localID; } }
}
[Flags]
public enum StateUpdateTypes
{
None = 0,
AvatarTerse = 1,
PrimitiveTerse = AvatarTerse << 1,
PrimitiveFull = PrimitiveTerse << 1,
All = AvatarTerse | PrimitiveTerse | PrimitiveFull,
}
public interface IClientAPI
{
Vector3 StartPos { get; set; }
@ -1186,20 +1021,14 @@ 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 SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags);
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 ReprioritizeUpdates(UpdatePriorityHandler handler);
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
List<InventoryFolderBase> folders, int version, bool fetchFolders,

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Net;
using OpenMetaverse;
using OpenMetaverse.Packets;
namespace OpenSim.Framework
{
public interface ISceneEntity
{
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;
protected 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
@ -365,7 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
/// ownerless phantom.
///
/// All manipulation of this set has to occur under a m_primFullUpdate.SyncRoot lock
/// All manipulation of this set has to occur under a m_entityUpdates.SyncRoot lock
///
/// </value>
protected HashSet<uint> m_killRecord;
@ -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);
@ -3414,76 +3384,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
#region Avatar Packet/Data Sending Methods
/// <summary>
/// Send an ObjectUpdate packet with information about an avatar
/// </summary>
public void SendAvatarData(SendAvatarData data)
{
ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
objupdate.Header.Zerocoded = true;
objupdate.RegionData.RegionHandle = data.RegionHandle;
objupdate.RegionData.TimeDilation = ushort.MaxValue;
objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
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.
@ -3524,176 +3424,215 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(loc, ThrottleOutPacketType.Task);
}
#endregion Avatar Packet/Data Sending Methods
#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 SendEntityUpdate(double priority, 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;
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()
{
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);
lock (m_primFullUpdates.SyncRoot)
lock (m_entityUpdates.SyncRoot)
{
int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket);
if (count == 0)
return;
EntityUpdate update;
m_fullUpdateDataBlocksBuilder.Clear();
for (int i = 0; i < count; i++)
while ((update = m_entityUpdates.Dequeue()) != null)
{
ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue();
if (m_killRecord.Contains(update.Entity.LocalId))
continue;
if (!m_killRecord.Contains(block.ID))
#region UpdateFlags to packet type conversion
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));
}
else if (!canUseImproved)
{
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
}
else
{
bool avatar = (update.Entity is ScenePresence);
uint localID = update.Entity.LocalId;
uint attachPoint;
Vector4 collisionPlane;
Vector3 position, velocity, acceleration, angularVelocity;
Quaternion rotation;
byte[] textureEntry;
if (update.Entity is ScenePresence)
{
ScenePresence presence = (ScenePresence)update.Entity;
attachPoint = 0;
collisionPlane = presence.CollisionPlane;
position = presence.OffsetPosition;
velocity = presence.Velocity;
acceleration = Vector3.Zero;
angularVelocity = Vector3.Zero;
rotation = presence.Rotation;
if (updateFlags.HasFlag(PrimUpdateFlags.Textures))
textureEntry = presence.Appearance.Texture.GetBytes();
else
textureEntry = null;
}
else
{
SceneObjectPart part = (SceneObjectPart)update.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;
}
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(avatar, localID, attachPoint, collisionPlane, position,
velocity, acceleration, rotation, angularVelocity, textureEntry));
}
#endregion Block Construction
}
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 =
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();
}
while (m_entityUpdates.Count > 0)
ProcessEntityUpdates();
}
#endregion Primitive Packet/Data Sending Methods
@ -3724,27 +3663,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
{
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
{
lock (m_avatarTerseUpdates.SyncRoot)
{
if (m_avatarTerseUpdates.Count > 0)
ProcessAvatarTerseUpdates();
}
}
if ((categories & ThrottleOutPacketTypeFlags.State) != 0)
{
lock (m_primFullUpdates.SyncRoot)
lock (m_entityUpdates.SyncRoot)
{
if (m_primFullUpdates.Count > 0)
ProcessPrimFullUpdates();
}
lock (m_primTerseUpdates.SyncRoot)
{
if (m_primTerseUpdates.Count > 0)
ProcessPrimTerseUpdates();
if (m_entityUpdates.Count > 0)
ProcessEntityUpdates();
}
}
@ -4403,19 +4327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Helper Methods
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
{
return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
}
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);
}
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint,
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, uint attachPoint,
Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
Vector3 angularVelocity, byte[] textureEntry)
{
@ -4490,12 +4402,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 +4417,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;
@ -4523,98 +4435,92 @@ namespace OpenSim.Region.ClientStack.LindenUDP
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)
{
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);
update.UpdateFlags = (uint)data.Flags;
if (data.Sound != UUID.Zero)
{
update.Sound = data.SoundId;
update.OwnerID = data.ownerID;
update.Gain = (float)data.SoundVolume;
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 +4528,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);
@ -11655,7 +11567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return item.Value;
}
}
throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
return default(TValue);
}
internal void Reprioritize(UpdatePriorityHandler handler)

View File

@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
if (m_Cache != null)
m_Cache.Cache(asset);
if (asset.Temporary || asset.Local)
if (asset.Local)
return asset.ID;
return m_AssetService.Store(asset);

View File

@ -528,18 +528,14 @@ 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)
{
}
public virtual void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
}
@ -548,15 +544,7 @@ namespace OpenSim.Region.Examples.SimpleModule
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public virtual void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -1490,16 +1490,15 @@ namespace OpenSim.Region.Framework.Scenes
public void SendFullUpdateToClient(IClientAPI remoteClient)
{
RootPart.SendFullUpdate(
remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
RootPart.SendFullUpdateToClient(
remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID), PrimUpdateFlags.FullUpdate);
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
if (part != RootPart)
part.SendFullUpdate(
remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
part.SendFullUpdateToClient(remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID), PrimUpdateFlags.FullUpdate);
}
}
}

View File

@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
#endregion Enumerations
public class SceneObjectPart : IScriptHost
public class SceneObjectPart : ISceneEntity, IScriptHost
{
/// <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
@ -2830,34 +2848,6 @@ namespace OpenSim.Region.Framework.Scenes
// m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
// }
/// <summary>
/// Send a full update to the client for the given part
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="clientFlags"></param>
protected internal void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
{
// m_log.DebugFormat(
// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
if (IsRoot)
{
if (IsAttachment)
{
SendFullUpdateToClient(remoteClient, AttachedPos, clientFlags);
}
else
{
SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags);
}
}
else
{
SendFullUpdateToClient(remoteClient, clientFlags);
}
}
/// <summary>
/// Send a full update for this part to all clients.
/// </summary>
@ -2865,7 +2855,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID));
SendFullUpdateToClient(avatar.ControllingClient, avatar.GenerateClientFlags(UUID), PrimUpdateFlags.FullUpdate);
});
}
@ -2879,29 +2869,17 @@ namespace OpenSim.Region.Framework.Scenes
{
// Ugly reference :(
if (avatar.UUID != agentID)
SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID));
SendFullUpdateToClient(avatar.ControllingClient, avatar.GenerateClientFlags(UUID), PrimUpdateFlags.FullUpdate);
});
}
/// <summary>
/// Sends a full update to the client
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="clientFlags"></param>
public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags)
{
Vector3 lPos;
lPos = OffsetPosition;
SendFullUpdateToClient(remoteClient, lPos, clientflags);
}
/// <summary>
/// Sends a full update to the client
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="lPos"></param>
/// <param name="clientFlags"></param>
public void SendFullUpdateToClient(IClientAPI remoteClient, Vector3 lPos, uint clientFlags)
public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientFlags, PrimUpdateFlags updateFlags)
{
// Suppress full updates during attachment editing
//
@ -2925,11 +2903,33 @@ 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.SendEntityUpdate(ParentGroup.GetUpdatePriority(remoteClient), this, updateFlags);
}
public void SendTerseUpdateToClient(IClientAPI remoteClient)
{
if (ParentGroup == null || ParentGroup.IsDeleted)
return;
Vector3 lPos = OffsetPosition;
if (IsAttachment)
{
if (ParentGroup.RootPart != this)
return;
lPos = ParentGroup.RootPart.AttachedPos;
}
else
{
if (ParentGroup.RootPart == this)
lPos = AbsolutePosition;
}
// Causes this thread to dig into the Client Thread Data.
// Remember your locking here!
remoteClient.SendEntityUpdate(ParentGroup.GetUpdatePriority(remoteClient), this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation |
PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
}
/// <summary>
@ -4617,35 +4617,6 @@ namespace OpenSim.Region.Framework.Scenes
}
#endregion Public Methods
public void SendTerseUpdateToClient(IClientAPI remoteClient)
{
if (ParentGroup == null || ParentGroup.IsDeleted)
return;
Vector3 lPos = OffsetPosition;
if (IsAttachment)
{
if (ParentGroup.RootPart != this)
return;
lPos = ParentGroup.RootPart.AttachedPos;
}
else
{
if (ParentGroup.RootPart == this)
lPos = AbsolutePosition;
}
// 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)));
}
public void AddScriptLPS(int count)
{
@ -4694,7 +4665,7 @@ namespace OpenSim.Region.Framework.Scenes
public Color4 GetTextColor()
{
return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A));
return new Color4(m_color.R, m_color.G, m_color.B, (byte)(255 - m_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()
// {
@ -479,6 +479,12 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public Vector3 OffsetPosition
{
get { return m_pos; }
set { m_pos = value; }
}
/// <summary>
/// Current velocity of the avatar.
/// </summary>
@ -1032,8 +1038,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)));
CollisionPlane = new Vector4(0f, 0f, 1f, AbsolutePosition.Z - 0.5f);
ControllingClient.SendEntityUpdate(GetUpdatePriority(ControllingClient), this, PrimUpdateFlags.Position | PrimUpdateFlags.Velocity);
}
public void AddNeighbourRegion(ulong regionHandle, string cap)
@ -2356,8 +2363,8 @@ 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.SendEntityUpdate(GetUpdatePriority(remoteClient), this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation |
PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity | PrimUpdateFlags.CollisionPlane);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
m_scene.StatsReporter.AddAgentUpdates(1);
@ -2453,9 +2460,8 @@ 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.SendEntityUpdate(GetUpdatePriority(remoteAvatar.m_controllingClient), this, PrimUpdateFlags.FullUpdate);
m_scene.StatsReporter.AddAgentUpdates(1);
}
@ -2523,8 +2529,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.SendEntityUpdate(GetUpdatePriority(m_controllingClient), this, PrimUpdateFlags.FullUpdate);
SendInitialFullUpdateToAllClients();
SendAppearanceToAllOtherAgents();
@ -2634,9 +2639,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.SendEntityUpdate(GetUpdatePriority(m_controllingClient), this, PrimUpdateFlags.Textures);
}
public void SetWearable(int wearableId, AvatarWearable wearable)
@ -3902,7 +3905,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

@ -118,8 +118,8 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampFull);
part.SendFullUpdate(m_presence.ControllingClient,
m_presence.GenerateClientFlags(part.UUID));
part.SendFullUpdateToClient(m_presence.ControllingClient,
m_presence.GenerateClientFlags(part.UUID), PrimUpdateFlags.FullUpdate);
// We'll update to the part's timestamp rather than
// the current time to avoid the race condition
@ -161,8 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
continue;
}
part.SendFullUpdate(m_presence.ControllingClient,
m_presence.GenerateClientFlags(part.UUID));
part.SendFullUpdateToClient(m_presence.ControllingClient, m_presence.GenerateClientFlags(part.UUID), PrimUpdateFlags.FullUpdate);
}
}
}

View File

@ -1045,21 +1045,15 @@ 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)
{
}
public void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
@ -1070,17 +1064,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void SendPrimitiveToClient(SendPrimitiveData data)
{
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -618,18 +618,14 @@ 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)
{
}
public void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
}
@ -638,15 +634,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public virtual void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}

View File

@ -621,18 +621,14 @@ 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)
{
}
public virtual void SendEntityUpdate(double priority, ISceneEntity entity, PrimUpdateFlags updateFlags)
{
}
public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{
}
@ -641,15 +637,7 @@ namespace OpenSim.Tests.Common.Mock
{
}
public virtual void SendPrimitiveToClient(SendPrimitiveData data)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
public virtual void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}