Compare commits

...

8 Commits

Author SHA1 Message Date
John Hurliman 93469d3d58 * Implemented the actual ObjectUpdate network optimizations. Sends single prim updates instead of group updates in most cases and avoids sending unnecessary or duplicate ObjectUpdate packets 2010-05-05 18:07:09 -07:00
John Hurliman 95130df78a * Changed many more "terse" and "full" update sending and update scheduling methods to take PrimUpdateFlags instead
* Disabled m_killRecord until the issue of avatars keeping the same localID when TPing away and back can be resolved
2010-05-05 16:51:41 -07:00
John Hurliman d5a5cae58b * Fixed a regression where all object updates were sent to the client the first time OnQueueEmpty fired
* Removed PrimTerseUpdatesPerPacket, AvatarTerseUpdatesPerPacket, PrimFullUpdatesPerPacket, and replaced with PrimUpdatesPerCallback
* Changed CreateImprovedTerseBlock() to work with SceneObjectPart and ScenePresence
2010-05-05 13:14:03 -07:00
John Hurliman ce106a0c0b * Only call the expensive client flag generation method for ObjectUpdate packets when we have to 2010-05-05 11:39:08 -07:00
John Hurliman 98a9ae40c5 * Moved special PrimFlags.CreateSelected handling into LLClientView
* Changed many SendXUpdateToY() methods to SendUpdateToY(PrimUpdateFlags updateFlags), consolidated several methods
2010-05-04 17:12:53 -07:00
John Hurliman 91878f79b9 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. 2010-05-04 16:20:43 -07:00
John Hurliman 40df4e7203 Merge branch 'master' of ssh://opensimulator.org/var/git/opensim 2010-05-04 13:58:43 -07:00
John Hurliman 32e9fb2634 * Added HttpStreamHandler, a generic HTTP handler that does not require creating a new class for each request handler
* Added WebUtil.UrlEncode() that converts spaces to %20 instead of + (to match incoming HTTP request strings)
* Fixed a potential startup issue in SimianProfiles
* Added new handlers to SimianGrid for incoming messages
2010-05-04 13:58:21 -07:00
37 changed files with 1305 additions and 1313 deletions

View File

@ -1026,28 +1026,17 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow // 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) public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{ {
// Minimap function, not used. // 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) public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
{ {
// Need to translate to MXP somehow // Need to translate to MXP somehow
@ -1058,23 +1047,7 @@ namespace OpenSim.Client.MXP.ClientStack
// Need to translate to MXP somehow // Need to translate to MXP somehow
} }
public void SendPrimitiveToClient(SendPrimitiveData data) public void ReprioritizeUpdates(UpdatePriorityHandler handler)
{
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)
{ {
} }

View File

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

View File

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

View File

@ -245,7 +245,6 @@ namespace OpenSim.Data.Tests
pbshap.ProfileEnd = ushort.MaxValue; pbshap.ProfileEnd = ushort.MaxValue;
pbshap.ProfileHollow = ushort.MaxValue; pbshap.ProfileHollow = ushort.MaxValue;
Vector3 scale = new Vector3(random.Next(),random.Next(),random.Next()); Vector3 scale = new Vector3(random.Next(),random.Next(),random.Next());
byte updatef = (byte) random.Next(127);
RegionInfo regionInfo = new RegionInfo(); RegionInfo regionInfo = new RegionInfo();
regionInfo.RegionID = region3; regionInfo.RegionID = region3;
@ -284,7 +283,6 @@ namespace OpenSim.Data.Tests
sop.LinkNum = linknum; sop.LinkNum = linknum;
sop.ClickAction = clickaction; sop.ClickAction = clickaction;
sop.Scale = scale; sop.Scale = scale;
sop.UpdateFlag = updatef;
//Tests if local part accepted the parameters: //Tests if local part accepted the parameters:
Assert.That(regionh,Is.EqualTo(sop.RegionHandle), "Assert.That(regionh,Is.EqualTo(sop.RegionHandle))"); Assert.That(regionh,Is.EqualTo(sop.RegionHandle), "Assert.That(regionh,Is.EqualTo(sop.RegionHandle))");
@ -317,7 +315,6 @@ namespace OpenSim.Data.Tests
Assert.That(linknum,Is.EqualTo(sop.LinkNum), "Assert.That(linknum,Is.EqualTo(sop.LinkNum))"); Assert.That(linknum,Is.EqualTo(sop.LinkNum), "Assert.That(linknum,Is.EqualTo(sop.LinkNum))");
Assert.That(clickaction,Is.EqualTo(sop.ClickAction), "Assert.That(clickaction,Is.EqualTo(sop.ClickAction))"); Assert.That(clickaction,Is.EqualTo(sop.ClickAction), "Assert.That(clickaction,Is.EqualTo(sop.ClickAction))");
Assert.That(scale,Is.EqualTo(sop.Scale), "Assert.That(scale,Is.EqualTo(sop.Scale))"); Assert.That(scale,Is.EqualTo(sop.Scale), "Assert.That(scale,Is.EqualTo(sop.Scale))");
Assert.That(updatef,Is.EqualTo(sop.UpdateFlag), "Assert.That(updatef,Is.EqualTo(sop.UpdateFlag))");
// This is necessary or object will not be inserted in DB // This is necessary or object will not be inserted in DB
sop.ObjectFlags = 0; sop.ObjectFlags = 0;
@ -417,7 +414,6 @@ namespace OpenSim.Data.Tests
PrimitiveBaseShape pbshap = new PrimitiveBaseShape(); PrimitiveBaseShape pbshap = new PrimitiveBaseShape();
pbshap = PrimitiveBaseShape.Default; pbshap = PrimitiveBaseShape.Default;
Vector3 scale = new Vector3(random.Next(),random.Next(),random.Next()); Vector3 scale = new Vector3(random.Next(),random.Next(),random.Next());
byte updatef = (byte) random.Next(127);
// Updates the region with new values // Updates the region with new values
SceneObjectGroup sog2 = FindSOG("Adam West", region3); SceneObjectGroup sog2 = FindSOG("Adam West", region3);
@ -447,7 +443,6 @@ namespace OpenSim.Data.Tests
sog2.RootPart.LinkNum = linknum; sog2.RootPart.LinkNum = linknum;
sog2.RootPart.ClickAction = clickaction; sog2.RootPart.ClickAction = clickaction;
sog2.RootPart.Scale = scale; sog2.RootPart.Scale = scale;
sog2.RootPart.UpdateFlag = updatef;
db.StoreObject(sog2, region3); db.StoreObject(sog2, region3);
List<SceneObjectGroup> sogs = db.LoadObjects(region3); List<SceneObjectGroup> sogs = db.LoadObjects(region3);

View File

@ -33,6 +33,52 @@ using OpenMetaverse.Packets;
namespace OpenSim.Framework 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 #region Client API Delegate definitions
public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args); public delegate void ViewerEffectEventHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args);
@ -571,207 +617,6 @@ namespace OpenSim.Framework
public float dwell; 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 { public struct UpdatePriorityData {
private double m_priority; private double m_priority;
private uint m_localID; private uint m_localID;
@ -785,16 +630,6 @@ namespace OpenSim.Framework
public uint localID { get { return this.m_localID; } } 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 public interface IClientAPI
{ {
Vector3 StartPos { get; set; } Vector3 StartPos { get; set; }
@ -1186,20 +1021,14 @@ namespace OpenSim.Framework
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
void SendPayPrice(UUID objectID, int[] payPrice); void SendPayPrice(UUID objectID, int[] payPrice);
void SendAvatarData(SendAvatarData data);
void SendAvatarTerseUpdate(SendAvatarTerseData data);
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 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 AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
void SetChildAgentThrottle(byte[] throttle); void SetChildAgentThrottle(byte[] throttle);
void SendPrimitiveToClient(SendPrimitiveData data); void ReprioritizeUpdates(UpdatePriorityHandler handler);
void SendPrimTerseUpdate(SendPrimitiveTerseData data);
void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
List<InventoryFolderBase> folders, int version, bool fetchFolders, 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

@ -40,6 +40,39 @@ using OpenMetaverse.StructuredData;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
/// <summary>
/// A generic HTTP request handler
/// </summary>
public class HttpStreamHandler : IStreamHandler
{
public delegate void HttpStreamCallback(OSHttpRequest httpRequest, OSHttpResponse httpResponse);
private string m_contentType;
private string m_httpMethod;
private string m_path;
private HttpStreamCallback m_callback;
public string ContentType { get { return m_contentType; } }
public string HttpMethod { get { return m_httpMethod; } }
public string Path { get { return m_path; } }
/// <summary>
/// Constructor
/// </summary>
public HttpStreamHandler(string contentType, string httpMethod, string path, HttpStreamCallback callback)
{
m_contentType = contentType;
m_httpMethod = httpMethod;
m_path = path;
m_callback = callback;
}
public void Handle(string path, Stream request, Stream response, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
m_callback(httpRequest, httpResponse);
}
}
/// <summary> /// <summary>
/// Miscellaneous static methods and extension methods related to the web /// Miscellaneous static methods and extension methods related to the web
/// </summary> /// </summary>
@ -176,6 +209,16 @@ namespace OpenSim.Framework
return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } }; return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } };
} }
/// <summary>
/// Encodes a URL string
/// </summary>
/// <param name="str">Unencoded string to encode</param>
/// <returns>URL-encoded string</returns>
public static string UrlEncode(string str)
{
return HttpUtility.UrlEncode(str).Replace("+", "%20");
}
#region Uri #region Uri
/// <summary> /// <summary>

View File

@ -50,43 +50,17 @@ using Nini.Config;
namespace OpenSim.Region.ClientStack.LindenUDP namespace OpenSim.Region.ClientStack.LindenUDP
{ {
#region Enums public class EntityUpdate
/// <summary>
/// Specifies the fields that have been changed when sending a prim or
/// avatar update
/// </summary>
[Flags]
public enum PrimUpdateFlags : uint
{ {
None = 0, public ISceneEntity Entity;
AttachmentPoint = 1 << 0, public PrimUpdateFlags Flags;
Material = 1 << 1,
ClickAction = 1 << 2,
Scale = 1 << 3,
ParentID = 1 << 4,
PrimFlags = 1 << 5,
PrimData = 1 << 6,
MediaURL = 1 << 7,
ScratchPad = 1 << 8,
Textures = 1 << 9,
TextureAnim = 1 << 10,
NameValue = 1 << 11,
Position = 1 << 12,
Rotation = 1 << 13,
Velocity = 1 << 14,
Acceleration = 1 << 15,
AngularVelocity = 1 << 16,
CollisionPlane = 1 << 17,
Text = 1 << 18,
Particles = 1 << 19,
ExtraData = 1 << 20,
Sound = 1 << 21,
Joint = 1 << 22,
FullUpdate = UInt32.MaxValue
}
#endregion Enums public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags)
{
Entity = entity;
Flags = flags;
}
}
public delegate bool PacketMethod(IClientAPI simClient, Packet packet); public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
@ -350,9 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private readonly IGroupsModule m_GroupsModule; private readonly IGroupsModule m_GroupsModule;
private int m_cachedTextureSerial; private int m_cachedTextureSerial;
protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; protected PriorityQueue<double, EntityUpdate> m_entityUpdates;
private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
/// <value> /// <value>
/// List used in construction of data blocks for an object update packet. This is to stop us having to /// 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 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
/// ownerless phantom. /// 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> /// </value>
protected HashSet<uint> m_killRecord; protected HashSet<uint> m_killRecord;
@ -463,9 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_scene = scene; m_scene = scene;
m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); m_entityUpdates = new PriorityQueue<double, EntityUpdate>(m_scene.Entities.Count);
m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
m_killRecord = new HashSet<uint>(); m_killRecord = new HashSet<uint>();
@ -1519,7 +1489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
kill.Header.Reliable = true; kill.Header.Reliable = true;
kill.Header.Zerocoded = true; kill.Header.Zerocoded = true;
lock (m_primFullUpdates.SyncRoot) lock (m_entityUpdates.SyncRoot)
{ {
m_killRecord.Add(localID); m_killRecord.Add(localID);
OutPacket(kill, ThrottleOutPacketType.State); OutPacket(kill, ThrottleOutPacketType.State);
@ -3414,76 +3384,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion #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) public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{ {
if (!IsActive) return; // We don't need to update inactive clients. if (!IsActive) return; // We don't need to update inactive clients.
@ -3524,176 +3424,182 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(loc, ThrottleOutPacketType.Task); OutPacket(loc, ThrottleOutPacketType.Task);
} }
#endregion Avatar Packet/Data Sending Methods
#region Primitive 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; lock (m_entityUpdates.SyncRoot)
// if (text.IndexOf("\n") >= 0) m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId);
// 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);
} }
void ProcessPrimFullUpdates() private void ProcessEntityUpdates(int maxUpdates)
{ {
ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
outPacket.Header.Zerocoded = true; 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; int updatesThisCall = 0;
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); EntityUpdate update;
if (count == 0)
return;
m_fullUpdateDataBlocksBuilder.Clear(); while ((update = m_entityUpdates.Dequeue()) != null)
for (int i = 0; i < count; i++)
{ {
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); canUseCompressed = false;
canUseImproved = false;
// 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);
} }
// else else
// { {
// m_log.WarnFormat( if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name); 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) #region Packet Sending
{
if (data.Priority == double.NaN) const float TIME_DILATION = 1.0f;
ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
if (objectUpdateBlocks.IsValueCreated)
{ {
m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update"); List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
return;
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);
} }
Quaternion rotation = data.Rotation; if (compressedUpdateBlocks.IsValueCreated)
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;
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)
{ {
int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket); List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
if (count == 0)
return;
outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
for (int i = 0; i < count; i++) packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue(); 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);
} }
OutPacket(outPacket, ThrottleOutPacketType.State); 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 = //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
delegate(ref double priority, uint local_id)
{ PriorityQueue<double, EntityUpdate>.UpdatePriorityHandler update_priority_handler =
priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN;
};
PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
delegate(ref double priority, uint local_id) delegate(ref double priority, uint local_id)
{ {
priority = handler(new UpdatePriorityData(priority, local_id)); priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN; return priority != double.NaN;
}; };
if ((type & StateUpdateTypes.AvatarTerse) != 0) lock (m_entityUpdates.SyncRoot)
{ m_entityUpdates.Reprioritize(update_priority_handler);
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);
}
} }
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
while (m_primFullUpdates.Count > 0) m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
{
ProcessPrimFullUpdates(); while (m_entityUpdates.Count > 0)
} ProcessEntityUpdates(-1);
while (m_primTerseUpdates.Count > 0)
{
ProcessPrimTerseUpdates();
}
while (m_avatarTerseUpdates.Count > 0)
{
ProcessAvatarTerseUpdates();
}
} }
#endregion Primitive Packet/Data Sending Methods #endregion Primitive Packet/Data Sending Methods
@ -3724,28 +3630,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
{ {
if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
{
lock (m_avatarTerseUpdates.SyncRoot)
{
if (m_avatarTerseUpdates.Count > 0)
ProcessAvatarTerseUpdates();
}
}
if ((categories & ThrottleOutPacketTypeFlags.State) != 0) if ((categories & ThrottleOutPacketTypeFlags.State) != 0)
{ {
lock (m_primFullUpdates.SyncRoot) if (m_entityUpdates.Count > 0)
{ ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback);
if (m_primFullUpdates.Count > 0)
ProcessPrimFullUpdates();
}
lock (m_primTerseUpdates.SyncRoot)
{
if (m_primTerseUpdates.Count > 0)
ProcessPrimTerseUpdates();
}
} }
if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@ -4403,22 +4291,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Helper Methods #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, #region ScenePresence/SOP Handling
data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
}
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) bool avatar = (entity is ScenePresence);
{ uint localID = entity.LocalId;
return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity, uint attachPoint;
data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); 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; int pos = 0;
byte[] data = new byte[(avatar ? 60 : 44)]; byte[] data = new byte[(avatar ? 60 : 44)];
@ -4490,12 +4407,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return block; return block;
} }
protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data) protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
{ {
byte[] objectData = new byte[76]; byte[] objectData = new byte[76];
Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support data.CollisionPlane.ToBytes(objectData, 0);
data.Position.ToBytes(objectData, 16); data.OffsetPosition.ToBytes(objectData, 16);
//data.Velocity.ToBytes(objectData, 28); //data.Velocity.ToBytes(objectData, 28);
//data.Acceleration.ToBytes(objectData, 40); //data.Acceleration.ToBytes(objectData, 40);
data.Rotation.ToBytes(objectData, 52); data.Rotation.ToBytes(objectData, 52);
@ -4505,12 +4422,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.Data = Utils.EmptyBytes; update.Data = Utils.EmptyBytes;
update.ExtraParams = new byte[1]; update.ExtraParams = new byte[1];
update.FullID = data.AvatarID; update.FullID = data.UUID;
update.ID = data.AvatarLocalID; update.ID = data.LocalId;
update.Material = (byte)Material.Flesh; update.Material = (byte)Material.Flesh;
update.MediaURL = Utils.EmptyBytes; update.MediaURL = Utils.EmptyBytes;
update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " + update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
data.LastName + "\nTitle STRING RW SV " + data.GroupTitle); data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
update.ObjectData = objectData; update.ObjectData = objectData;
update.ParentID = data.ParentID; update.ParentID = data.ParentID;
update.PathCurve = 16; update.PathCurve = 16;
@ -4523,98 +4440,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.Text = Utils.EmptyBytes; update.Text = Utils.EmptyBytes;
update.TextColor = new byte[4]; update.TextColor = new byte[4];
update.TextureAnim = Utils.EmptyBytes; update.TextureAnim = Utils.EmptyBytes;
update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes; 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);//61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags update.UpdateFlags = (uint)(
PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
PrimFlags.ObjectOwnerModify);
return update; return update;
} }
protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data) protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
{ {
byte[] objectData = new byte[60]; byte[] objectData = new byte[60];
data.pos.ToBytes(objectData, 0); data.RelativePosition.ToBytes(objectData, 0);
data.vel.ToBytes(objectData, 12); data.Velocity.ToBytes(objectData, 12);
data.acc.ToBytes(objectData, 24); data.Acceleration.ToBytes(objectData, 24);
data.rotation.ToBytes(objectData, 36); data.RotationOffset.ToBytes(objectData, 36);
data.rvel.ToBytes(objectData, 48); data.AngularVelocity.ToBytes(objectData, 48);
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
update.ClickAction = (byte)data.clickAction; update.ClickAction = (byte)data.ClickAction;
update.CRC = 0; update.CRC = 0;
update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes; update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
update.FullID = data.objectID; update.FullID = data.UUID;
update.ID = data.localID; update.ID = data.LocalId;
//update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
//update.JointPivot = Vector3.Zero; //update.JointPivot = Vector3.Zero;
//update.JointType = 0; //update.JointType = 0;
update.Material = data.material; update.Material = data.Material;
update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 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.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16)); update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
} }
else else
{ {
update.NameValue = Utils.EmptyBytes; 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; if ((data.Flags & PrimFlags.CreateSelected) != 0)
update.OwnerID = data.ownerID; {
update.Gain = (float)data.SoundVolume; // 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.Radius = (float)data.SoundRadius;
update.Flags = data.SoundFlags; update.Flags = data.SoundFlags;
} }
switch ((PCode)data.primShape.PCode) switch ((PCode)data.Shape.PCode)
{ {
case PCode.Grass: case PCode.Grass:
case PCode.Tree: case PCode.Tree:
case PCode.NewTree: case PCode.NewTree:
update.Data = new byte[] { data.primShape.State }; update.Data = new byte[] { data.Shape.State };
break; break;
default: 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; update.Data = Utils.EmptyBytes;
break; break;
} }
@ -4622,6 +4553,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return update; return update;
} }
protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
{
// TODO: Implement this
return null;
}
public void SendNameReply(UUID profileId, string firstname, string lastname) public void SendNameReply(UUID profileId, string firstname, string lastname)
{ {
UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
@ -11655,7 +11592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return item.Value; return item.Value;
} }
} }
throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); return default(TValue);
} }
internal void Reprioritize(UpdatePriorityHandler handler) internal void Reprioritize(UpdatePriorityHandler handler)

View File

@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>The measured resolution of Environment.TickCount</summary> /// <summary>The measured resolution of Environment.TickCount</summary>
public readonly float TickCountResolution; 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> /// OnQueueEmpty event is triggered for updates</summary>
public readonly int PrimTerseUpdatesPerPacket; public readonly int PrimUpdatesPerCallback;
/// <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;
/// <summary>Number of texture packets to put on the queue each time the /// <summary>Number of texture packets to put on the queue each time the
/// OnQueueEmpty event is triggered for textures</summary> /// OnQueueEmpty event is triggered for textures</summary>
public readonly int TextureSendLimit; public readonly int TextureSendLimit;
@ -191,9 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25); PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
TextureSendLimit = config.GetInt("TextureSendLimit", 20); TextureSendLimit = config.GetInt("TextureSendLimit", 20);
m_defaultRTO = config.GetInt("DefaultRTO", 0); m_defaultRTO = config.GetInt("DefaultRTO", 0);
@ -201,9 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
else else
{ {
PrimTerseUpdatesPerPacket = 25; PrimUpdatesPerCallback = 100;
AvatarTerseUpdatesPerPacket = 10;
PrimFullUpdatesPerPacket = 100;
TextureSendLimit = 20; TextureSendLimit = 20;
} }

View File

@ -1446,7 +1446,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent)) if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent))
{ {
grp.OffsetForNewRegion(oldGroupPosition); grp.OffsetForNewRegion(oldGroupPosition);
grp.ScheduleGroupForFullUpdate(); grp.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
@ -1465,7 +1465,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
bool successYN = false; bool successYN = false;
grp.RootPart.UpdateFlag = 0; grp.RootPart.ClearPendingUpdate();
//int primcrossingXMLmethod = 0; //int primcrossingXMLmethod = 0;
if (destination != null) if (destination != null)

View File

@ -511,7 +511,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// if not, we set it's position in world. // if not, we set it's position in world.
if (!attachment) if (!attachment)
{ {
group.ScheduleGroupForFullUpdate(); group.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
float offsetHeight = 0; float offsetHeight = 0;
pos = m_Scene.GetNewRezLocation( pos = m_Scene.GetNewRezLocation(
@ -603,7 +603,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0);
rootPart.ParentGroup.ResumeScripts(); rootPart.ParentGroup.ResumeScripts();
rootPart.ScheduleFullUpdate(); rootPart.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
if (!m_Scene.Permissions.BypassPermissions()) if (!m_Scene.Permissions.BypassPermissions())

View File

@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
if (m_Cache != null) if (m_Cache != null)
m_Cache.Cache(asset); m_Cache.Cache(asset);
if (asset.Temporary || asset.Local) if (asset.Local)
return asset.ID; return asset.ID;
return m_AssetService.Store(asset); 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 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) 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 ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{ {
} }

View File

@ -26,6 +26,7 @@
*/ */
using System; using System;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces namespace OpenSim.Region.Framework.Interfaces
@ -34,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
{ {
void Reset(); void Reset();
void Close(); void Close();
void QueuePartForUpdate(SceneObjectPart part); void QueuePartForUpdate(SceneObjectPart part, PrimUpdateFlags updateFlags);
void SendPrimUpdates(); void SendPrimUpdates();
} }
} }

View File

@ -1857,10 +1857,10 @@ namespace OpenSim.Region.Framework.Scenes
{ {
group.RootPart.ApplyImpulse((vel * group.GetMass()), false); group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
group.Velocity = vel; group.Velocity = vel;
rootPart.ScheduleFullUpdate(); rootPart.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); group.CreateScriptInstances(param, true, DefaultScriptEngine, 2);
rootPart.ScheduleFullUpdate(); rootPart.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
if (!Permissions.BypassPermissions()) if (!Permissions.BypassPermissions())
{ {
@ -1929,7 +1929,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
sog.SetOwnerId(ownerID); sog.SetOwnerId(ownerID);
sog.SetGroup(groupID, remoteClient); sog.SetGroup(groupID, remoteClient);
sog.ScheduleGroupForFullUpdate(); sog.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
foreach (SceneObjectPart child in sog.Children.Values) foreach (SceneObjectPart child in sog.Children.Values)
child.Inventory.ChangeInventoryOwner(ownerID); child.Inventory.ChangeInventoryOwner(ownerID);

View File

@ -124,7 +124,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (((SceneObjectGroup)ent).LocalId == primLocalID) if (((SceneObjectGroup)ent).LocalId == primLocalID)
{ {
((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); ((SceneObjectGroup)ent).SendUpdateToClient(remoteClient, PrimUpdateFlags.FullUpdate);
return; return;
} }
} }
@ -207,8 +207,6 @@ namespace OpenSim.Region.Framework.Scenes
if (part.ParentGroup.IsAttachment) if (part.ParentGroup.IsAttachment)
isAttachment = true; isAttachment = true;
else
part.ParentGroup.ScheduleGroupForFullUpdate();
// If it's not an attachment, and we are allowed to move it, // If it's not an attachment, and we are allowed to move it,
// then we might have done so. If we moved across a parcel // then we might have done so. If we moved across a parcel

View File

@ -2051,8 +2051,6 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.SetGroup(groupID, null); sceneObject.SetGroup(groupID, null);
} }
sceneObject.ScheduleGroupForFullUpdate();
return sceneObject; return sceneObject;
} }
@ -2541,7 +2539,7 @@ namespace OpenSim.Region.Framework.Scenes
sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false);
RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
grp.SendGroupFullUpdate(); grp.SendGroupUpdate(PrimUpdateFlags.FullUpdate);
} }
else else
{ {
@ -4037,7 +4035,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (ent is SceneObjectGroup) if (ent is SceneObjectGroup)
{ {
((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); ((SceneObjectGroup)ent).ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
} }
@ -4538,7 +4536,7 @@ namespace OpenSim.Region.Framework.Scenes
part.GetProperties(remoteClient); part.GetProperties(remoteClient);
part.TriggerScriptChangedEvent(Changed.OWNER); part.TriggerScriptChangedEvent(Changed.OWNER);
group.ResumeScripts(); group.ResumeScripts();
part.ScheduleFullUpdate(); part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
break; break;

View File

@ -297,7 +297,7 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.AttachToScene(m_parentScene); sceneObject.AttachToScene(m_parentScene);
if (sendClientUpdates) if (sendClientUpdates)
sceneObject.ScheduleGroupForFullUpdate(); sceneObject.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
lock (sceneObject) lock (sceneObject)
{ {
@ -1297,7 +1297,9 @@ namespace OpenSim.Region.Framework.Scenes
// so that if the object is locked the client moving the object // so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before // get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world. // This keeps the moving user's client in sync with the rest of the world.
group.SendGroupTerseUpdate(); SceneObjectPart movingPart = group.GetChildPart(objectID);
if (movingPart != null)
movingPart.SendUpdateToAllClients(PrimUpdateFlags.Position);
} }
} }
@ -1338,7 +1340,9 @@ namespace OpenSim.Region.Framework.Scenes
// so that if the object is locked the client moving the object // so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before // get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world. // This keeps the moving user's client in sync with the rest of the world.
group.SendGroupTerseUpdate(); SceneObjectPart rotatingPart = group.GetChildPart(objectID);
if (rotatingPart != null)
rotatingPart.SendUpdateToAllClients(PrimUpdateFlags.Rotation);
} }
} }
@ -1508,7 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes
parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected);
parentGroup.TriggerScriptChangedEvent(Changed.LINK); parentGroup.TriggerScriptChangedEvent(Changed.LINK);
parentGroup.HasGroupChanged = true; parentGroup.HasGroupChanged = true;
parentGroup.ScheduleGroupForFullUpdate(); parentGroup.ScheduleGroupForUpdate(PrimUpdateFlags.ParentID);
} }
finally finally
@ -1608,7 +1612,7 @@ namespace OpenSim.Region.Framework.Scenes
List<uint> linkIDs = new List<uint>(); List<uint> linkIDs = new List<uint>();
foreach (SceneObjectPart newChild in newSet) foreach (SceneObjectPart newChild in newSet)
newChild.UpdateFlag = 0; newChild.ClearPendingUpdate();
LinkObjects(newRoot, newSet); LinkObjects(newRoot, newSet);
if (!affectedGroups.Contains(newRoot.ParentGroup)) if (!affectedGroups.Contains(newRoot.ParentGroup))
@ -1623,7 +1627,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
g.TriggerScriptChangedEvent(Changed.LINK); g.TriggerScriptChangedEvent(Changed.LINK);
g.HasGroupChanged = true; // Persist g.HasGroupChanged = true; // Persist
g.ScheduleGroupForFullUpdate(); g.ScheduleGroupForUpdate(PrimUpdateFlags.ParentID);
} }
} }
finally finally
@ -1731,7 +1735,7 @@ namespace OpenSim.Region.Framework.Scenes
copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0);
copy.HasGroupChanged = true; copy.HasGroupChanged = true;
copy.ScheduleGroupForFullUpdate(); copy.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
copy.ResumeScripts(); copy.ResumeScripts();
// required for physics to update it's position // required for physics to update it's position

View File

@ -1001,7 +1001,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
IsSelected = false; // fudge.... IsSelected = false; // fudge....
ScheduleGroupForFullUpdate(); RootPart.ScheduleUpdate(PrimUpdateFlags.ParentID);
} }
} }
else else
@ -1052,7 +1052,7 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.RemFlag(PrimFlags.TemporaryOnRez); RootPart.RemFlag(PrimFlags.TemporaryOnRez);
AttachToBackup(); AttachToBackup();
m_scene.EventManager.TriggerParcelPrimCountTainted(); m_scene.EventManager.TriggerParcelPrimCountTainted();
m_rootPart.ScheduleFullUpdate(); m_rootPart.ScheduleUpdate(PrimUpdateFlags.ParentID);
m_rootPart.ClearUndoState(); m_rootPart.ClearUndoState();
} }
@ -1277,7 +1277,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!silent) if (!silent)
{ {
part.UpdateFlag = 0; part.ClearPendingUpdate();
if (part == m_rootPart) if (part == m_rootPart)
avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
} }
@ -1339,7 +1339,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.RemoveGroupTarget(this); m_scene.RemoveGroupTarget(this);
} }
ScheduleGroupForFullUpdate(); ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
public override void SetText(string text, Vector3 color, double alpha) public override void SetText(string text, Vector3 color, double alpha)
@ -1351,7 +1351,7 @@ namespace OpenSim.Region.Framework.Scenes
Text = text; Text = text;
HasGroupChanged = true; HasGroupChanged = true;
m_rootPart.ScheduleFullUpdate(); m_rootPart.ScheduleUpdate(PrimUpdateFlags.Text);
} }
/// <summary> /// <summary>
@ -1488,18 +1488,16 @@ namespace OpenSim.Region.Framework.Scenes
#endregion #endregion
public void SendFullUpdateToClient(IClientAPI remoteClient) public void SendUpdateToClient(IClientAPI remoteClient, PrimUpdateFlags updateFlags)
{ {
RootPart.SendFullUpdate( RootPart.SendUpdateToClient(remoteClient, updateFlags);
remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.SendFullUpdate( part.SendUpdateToClient(remoteClient, updateFlags);
remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
} }
} }
} }
@ -1565,7 +1563,7 @@ namespace OpenSim.Region.Framework.Scenes
if (userExposed) if (userExposed)
{ {
SetRootPartOwner(m_rootPart, cAgentID, cGroupID); SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
m_rootPart.ScheduleFullUpdate(); m_rootPart.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
List<SceneObjectPart> partList; List<SceneObjectPart> partList;
@ -1592,7 +1590,7 @@ namespace OpenSim.Region.Framework.Scenes
if (userExposed) if (userExposed)
{ {
SetPartOwner(newPart, cAgentID, cGroupID); SetPartOwner(newPart, cAgentID, cGroupID);
newPart.ScheduleFullUpdate(); newPart.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
} }
@ -1603,7 +1601,7 @@ namespace OpenSim.Region.Framework.Scenes
dupe.HasGroupChanged = true; dupe.HasGroupChanged = true;
dupe.AttachToBackup(); dupe.AttachToBackup();
ScheduleGroupForFullUpdate(); ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
return dupe; return dupe;
@ -1856,7 +1854,7 @@ namespace OpenSim.Region.Framework.Scenes
ApplyNextOwnerPermissions(); ApplyNextOwnerPermissions();
} }
part.ScheduleFullUpdate(); part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
/// <summary> /// <summary>
@ -1942,13 +1940,13 @@ namespace OpenSim.Region.Framework.Scenes
if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f))
{ {
m_rootPart.UpdateFlag = 1; m_rootPart.PendingUpdateFlags |= PrimUpdateFlags.Position;
lastPhysGroupPos = AbsolutePosition; lastPhysGroupPos = AbsolutePosition;
} }
if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f))
{ {
m_rootPart.UpdateFlag = 1; m_rootPart.PendingUpdateFlags |= PrimUpdateFlags.Rotation;
lastPhysGroupRot = GroupRotation; lastPhysGroupRot = GroupRotation;
} }
@ -1961,31 +1959,18 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void ScheduleFullUpdateToAvatar(ScenePresence presence) public void ScheduleUpdateToAvatar(ScenePresence presence, PrimUpdateFlags updateFlags)
{ {
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
RootPart.AddFullUpdateToAvatar(presence); RootPart.AddUpdateToAvatar(presence, updateFlags);
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.AddFullUpdateToAvatar(presence); part.AddUpdateToAvatar(presence, updateFlags);
}
}
}
public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
{
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.AddTerseUpdateToAvatar(presence);
} }
} }
} }
@ -1993,35 +1978,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Schedule a full update for this scene object /// Schedule a full update for this scene object
/// </summary> /// </summary>
public void ScheduleGroupForFullUpdate() public void ScheduleGroupForUpdate(PrimUpdateFlags updateFlags)
{ {
// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID);
checkAtTargets(); checkAtTargets();
RootPart.ScheduleFullUpdate(); RootPart.ScheduleUpdate(updateFlags);
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.ScheduleFullUpdate(); part.ScheduleUpdate(updateFlags);
}
}
}
/// <summary>
/// Schedule a terse update for this scene object
/// </summary>
public void ScheduleGroupForTerseUpdate()
{
// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.ScheduleTerseUpdate();
} }
} }
} }
@ -2029,39 +1998,25 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Immediately send a full update for this scene object. /// Immediately send a full update for this scene object.
/// </summary> /// </summary>
public void SendGroupFullUpdate() public void SendGroupUpdate(PrimUpdateFlags updateFlags)
{ {
if (IsDeleted) if (IsDeleted)
return; return;
// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
RootPart.SendFullUpdateToAllClients(); RootPart.SendUpdateToAllClients(updateFlags);
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
if (part != RootPart) if (part != RootPart)
part.SendFullUpdateToAllClients(); part.SendUpdateToAllClients(updateFlags);
} }
} }
} }
/// <summary>
/// Immediately send an update for this scene object's root prim only.
/// This is for updates regarding the object as a whole, and none of its parts in particular.
/// Note: this may not be used by opensim (it probably should) but it's used by
/// external modules.
/// </summary>
public void SendGroupRootTerseUpdate()
{
if (IsDeleted)
return;
RootPart.SendTerseUpdateToAllClients();
}
public void QueueForUpdateCheck() public void QueueForUpdateCheck()
{ {
if (m_scene == null) // Need to check here as it's null during object creation if (m_scene == null) // Need to check here as it's null during object creation
@ -2070,23 +2025,6 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.SceneGraph.AddToUpdateList(this); m_scene.SceneGraph.AddToUpdateList(this);
} }
/// <summary>
/// Immediately send a terse update for this scene object.
/// </summary>
public void SendGroupTerseUpdate()
{
if (IsDeleted)
return;
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
part.SendTerseUpdateToAllClients();
}
}
}
#endregion #endregion
#region SceneGroupPart Methods #region SceneGroupPart Methods
@ -2492,7 +2430,7 @@ namespace OpenSim.Region.Framework.Scenes
public void NonPhysicalGrabMovement(Vector3 pos) public void NonPhysicalGrabMovement(Vector3 pos)
{ {
AbsolutePosition = pos; AbsolutePosition = pos;
m_rootPart.SendTerseUpdateToAllClients(); m_rootPart.SendUpdateToAllClients(PrimUpdateFlags.Position);
} }
/// <summary> /// <summary>
@ -2812,7 +2750,7 @@ namespace OpenSim.Region.Framework.Scenes
//if (part.UUID != m_rootPart.UUID) //if (part.UUID != m_rootPart.UUID)
HasGroupChanged = true; HasGroupChanged = true;
ScheduleGroupForFullUpdate(); ScheduleGroupForUpdate(PrimUpdateFlags.Scale);
//if (part.UUID == m_rootPart.UUID) //if (part.UUID == m_rootPart.UUID)
//{ //{
@ -2964,7 +2902,6 @@ namespace OpenSim.Region.Framework.Scenes
part.IgnoreUndoUpdate = false; part.IgnoreUndoUpdate = false;
part.StoreUndoState(); part.StoreUndoState();
HasGroupChanged = true; HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
} }
} }
@ -3001,11 +2938,12 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = pos; AbsolutePosition = pos;
HasGroupChanged = true; HasGroupChanged = true;
} }
//we need to do a terse update even if the move wasn't allowed //we need to do a terse update even if the move wasn't allowed
// so that the position is reset in the client (the object snaps back) // so that the position is reset in the client (the object snaps back)
ScheduleGroupForTerseUpdate(); m_rootPart.ScheduleUpdate(PrimUpdateFlags.Position);
} }
/// <summary> /// <summary>
@ -3070,7 +3008,7 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = newPos; AbsolutePosition = newPos;
HasGroupChanged = true; HasGroupChanged = true;
ScheduleGroupForTerseUpdate(); ScheduleGroupForUpdate(PrimUpdateFlags.Position | PrimUpdateFlags.Rotation);
} }
public void OffsetForNewRegion(Vector3 offset) public void OffsetForNewRegion(Vector3 offset)
@ -3102,7 +3040,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
HasGroupChanged = true; HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
} }
/// <summary> /// <summary>
@ -3128,7 +3065,6 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = pos; AbsolutePosition = pos;
HasGroupChanged = true; HasGroupChanged = true;
ScheduleGroupForTerseUpdate();
} }
/// <summary> /// <summary>
@ -3214,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion newRot = primsRot * oldParentRot; Quaternion newRot = primsRot * oldParentRot;
newRot *= Quaternion.Inverse(axRot); newRot *= Quaternion.Inverse(axRot);
prim.RotationOffset = newRot; prim.RotationOffset = newRot;
prim.ScheduleTerseUpdate(); prim.ScheduleUpdate(PrimUpdateFlags.Position | PrimUpdateFlags.Rotation);
} }
} }
} }
@ -3226,7 +3162,7 @@ namespace OpenSim.Region.Framework.Scenes
childpart.StoreUndoState(); childpart.StoreUndoState();
} }
} }
m_rootPart.ScheduleTerseUpdate(); m_rootPart.ScheduleUpdate(PrimUpdateFlags.Position | PrimUpdateFlags.Rotation);
} }
#endregion #endregion

View File

@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
#endregion Enumerations #endregion Enumerations
public class SceneObjectPart : IScriptHost public class SceneObjectPart : ISceneEntity, IScriptHost
{ {
/// <value> /// <value>
/// Denote all sides of the prim /// Denote all sides of the prim
@ -168,14 +168,11 @@ namespace OpenSim.Region.Framework.Scenes
public double SoundRadius; public double SoundRadius;
[XmlIgnore] [XmlIgnore]
public uint TimeStampFull; public uint TimeStampUpdate;
[XmlIgnore] [XmlIgnore]
public uint TimeStampLastActivity; // Will be used for AutoReturn public uint TimeStampLastActivity; // Will be used for AutoReturn
[XmlIgnore]
public uint TimeStampTerse;
[XmlIgnore] [XmlIgnore]
public UUID FromItemID; public UUID FromItemID;
@ -282,15 +279,8 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_passTouches; private bool m_passTouches;
/// <summary> /// <summary>Modified fields that need to be broadcast</summary>
/// Only used internally to schedule client updates. private PrimUpdateFlags m_pendingUpdateFlags;
/// 0 - no update is scheduled
/// 1 - terse update scheduled
/// 2 - full update scheduled
///
/// TODO - This should be an enumeration
/// </summary>
private byte m_updateFlag;
protected Vector3 m_acceleration; protected Vector3 m_acceleration;
protected Vector3 m_angularVelocity; protected Vector3 m_angularVelocity;
@ -712,6 +702,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 public Quaternion RotationOffset
{ {
get get
@ -943,10 +951,10 @@ namespace OpenSim.Region.Framework.Scenes
TriggerScriptChangedEvent(Changed.SCALE); TriggerScriptChangedEvent(Changed.SCALE);
} }
} }
public byte UpdateFlag public PrimUpdateFlags PendingUpdateFlags
{ {
get { return m_updateFlag; } get { return m_pendingUpdateFlags; }
set { m_updateFlag = value; } set { m_pendingUpdateFlags = value; }
} }
#endregion #endregion
@ -1187,14 +1195,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Clear all pending updates of parts to clients
/// </summary>
private void ClearUpdateSchedule()
{
m_updateFlag = 0;
}
private void SendObjectPropertiesToClient(UUID AgentID) private void SendObjectPropertiesToClient(UUID AgentID)
{ {
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@ -1235,6 +1235,14 @@ namespace OpenSim.Region.Framework.Scenes
#region Public Methods #region Public Methods
/// <summary>
/// Clear all pending updates of parts to clients
/// </summary>
public void ClearPendingUpdate()
{
m_pendingUpdateFlags = PrimUpdateFlags.None;
}
public void ResetExpire() public void ResetExpire()
{ {
Expires = DateTime.Now + new TimeSpan(600000000); Expires = DateTime.Now + new TimeSpan(600000000);
@ -1257,17 +1265,17 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Tell all scene presences that they should send updates for this part to their clients /// Tell all scene presences that they should send updates for this part to their clients
/// </summary> /// </summary>
public void AddFullUpdateToAllAvatars() public void AddUpdateToAllAvatars(PrimUpdateFlags updateFlags)
{ {
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{ {
avatar.SceneViewer.QueuePartForUpdate(this); avatar.SceneViewer.QueuePartForUpdate(this, updateFlags);
}); });
} }
public void AddFullUpdateToAvatar(ScenePresence presence) public void AddUpdateToAvatar(ScenePresence presence, PrimUpdateFlags updateFlags)
{ {
presence.SceneViewer.QueuePartForUpdate(this); presence.SceneViewer.QueuePartForUpdate(this, updateFlags);
} }
public void AddNewParticleSystem(Primitive.ParticleSystem pSystem) public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
@ -1280,20 +1288,6 @@ namespace OpenSim.Region.Framework.Scenes
m_particleSystem = new byte[0]; m_particleSystem = new byte[0];
} }
/// Terse updates
public void AddTerseUpdateToAllAvatars()
{
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
avatar.SceneViewer.QueuePartForUpdate(this);
});
}
public void AddTerseUpdateToAvatar(ScenePresence presence)
{
presence.SceneViewer.QueuePartForUpdate(this);
}
public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
{ {
byte[] data = new byte[16]; byte[] data = new byte[16];
@ -2570,19 +2564,19 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (PhysActor != null) if (PhysActor != null)
{ {
Vector3 newpos = PhysActor.Position;
Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); if (m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.N) |
m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.S) |
if (m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.N) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.S) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.E) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.E) |
m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
{ {
m_parentGroup.AbsolutePosition = newpos; m_parentGroup.AbsolutePosition = newpos;
return; return;
} }
//m_parentGroup.RootPart.m_groupPosition = newpos;
} }
ScheduleTerseUpdate();
//SendTerseUpdateToAllClients(); ScheduleUpdate(PrimUpdateFlags.Position);
} }
public void PreloadSound(string sound) public void PreloadSound(string sound)
@ -2670,7 +2664,7 @@ namespace OpenSim.Region.Framework.Scenes
m_shape.Scale = scale; m_shape.Scale = scale;
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.Scale);
} }
public void RotLookAt(Quaternion target, float strength, float damping) public void RotLookAt(Quaternion target, float strength, float damping)
@ -2710,58 +2704,24 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Schedules this prim for a full update /// Schedules this prim for an update
/// </summary> /// </summary>
public void ScheduleFullUpdate() public void ScheduleUpdate(PrimUpdateFlags updateFlags)
{ {
// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId);
if (m_parentGroup != null) if (m_parentGroup != null)
{
m_parentGroup.QueueForUpdateCheck(); m_parentGroup.QueueForUpdateCheck();
}
int timeNow = Util.UnixTimeSinceEpoch(); int timeNow = Util.UnixTimeSinceEpoch();
// If multiple updates are scheduled on the same second, we still need to perform all of them // If multiple updates are scheduled on the same second, we still need to perform all of them
// So we'll force the issue by bumping up the timestamp so that later processing sees these need // So we'll force the issue by bumping up the timestamp so that later processing sees these need
// to be performed. // to be performed.
if (timeNow <= TimeStampFull) if (timeNow <= TimeStampUpdate)
{ TimeStampUpdate += 1;
TimeStampFull += 1;
}
else else
{ TimeStampUpdate = (uint)timeNow;
TimeStampFull = (uint)timeNow;
}
m_updateFlag = 2; m_pendingUpdateFlags |= updateFlags;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
// UUID, Name, TimeStampFull);
}
/// <summary>
/// Schedule a terse update for this prim. Terse updates only send position,
/// rotation, velocity, rotational velocity and shape information.
/// </summary>
public void ScheduleTerseUpdate()
{
if (m_updateFlag < 1)
{
if (m_parentGroup != null)
{
m_parentGroup.HasGroupChanged = true;
m_parentGroup.QueueForUpdateCheck();
}
TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
m_updateFlag = 1;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
// UUID, Name, TimeStampTerse);
}
} }
public void ScriptSetPhantomStatus(bool Phantom) public void ScriptSetPhantomStatus(bool Phantom)
@ -2821,51 +2781,14 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
// /// <summary>
// ///
// /// </summary>
// /// <param name="remoteClient"></param>
// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
// {
// 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> /// <summary>
/// Send a full update for this part to all clients. /// Send a full update for this part to all clients.
/// </summary> /// </summary>
public void SendFullUpdateToAllClients() public void SendUpdateToAllClients(PrimUpdateFlags updateFlags)
{ {
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{ {
SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID)); SendUpdateToClient(avatar.ControllingClient, updateFlags);
}); });
} }
@ -2873,63 +2796,30 @@ namespace OpenSim.Region.Framework.Scenes
/// Send a full update to all clients except the one nominated. /// Send a full update to all clients except the one nominated.
/// </summary> /// </summary>
/// <param name="agentID"></param> /// <param name="agentID"></param>
public void SendFullUpdateToAllClientsExcept(UUID agentID) public void SendUpdateToAllClientsExcept(PrimUpdateFlags updateFlags, UUID agentID)
{ {
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{ {
// Ugly reference :( // Ugly reference :(
if (avatar.UUID != agentID) if (avatar.UUID != agentID)
SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID)); SendUpdateToClient(avatar.ControllingClient, updateFlags);
}); });
} }
/// <summary> /// <summary>
/// Sends a full update to the client /// Sends an update for this object to a client
/// </summary> /// </summary>
/// <param name="remoteClient"></param> public void SendUpdateToClient(IClientAPI remoteClient, PrimUpdateFlags updateFlags)
/// <param name="clientFlags"></param>
public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags)
{ {
Vector3 lPos; // Sanity check
lPos = OffsetPosition; if (ParentGroup == null || ParentGroup.IsDeleted)
SendFullUpdateToClient(remoteClient, lPos, clientflags); return;
}
/// <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)
{
// Suppress full updates during attachment editing // Suppress full updates during attachment editing
// if (ParentGroup.IsSelected && IsAttachment && updateFlags == PrimUpdateFlags.FullUpdate)
if (ParentGroup.IsSelected && IsAttachment)
return; return;
if (ParentGroup.IsDeleted) remoteClient.SendEntityUpdate(ParentGroup.GetUpdatePriority(remoteClient), this, updateFlags);
return;
clientFlags &= ~(uint) PrimFlags.CreateSelected;
if (remoteClient.AgentId == _ownerID)
{
if ((uint) (_flags & PrimFlags.CreateSelected) != 0)
{
clientFlags |= (uint) PrimFlags.CreateSelected;
_flags &= ~PrimFlags.CreateSelected;
}
}
//bool isattachment = IsAttachment;
//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)));
} }
/// <summary> /// <summary>
@ -2938,50 +2828,59 @@ namespace OpenSim.Region.Framework.Scenes
public void SendScheduledUpdates() public void SendScheduledUpdates()
{ {
const float ROTATION_TOLERANCE = 0.01f; const float ROTATION_TOLERANCE = 0.01f;
const float VELOCITY_TOLERANCE = 0.001f;
const float POSITION_TOLERANCE = 0.05f; const float POSITION_TOLERANCE = 0.05f;
const int TIME_MS_TOLERANCE = 3000; const int TIME_MS_TOLERANCE = 3000;
if (m_updateFlag == 1) #region PrimUpdateFlags Management
{
// Throw away duplicate or insignificant updates
if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
!Acceleration.Equals(m_lastAcceleration) ||
!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
!AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
!OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
{
AddTerseUpdateToAllAvatars();
ClearUpdateSchedule();
// This causes the Scene to 'poll' physical objects every couple of frames // Check if any of the movement fields changes and set flags accordingly
// bad, so it's been replaced by an event driven method. PrimUpdateFlags updateFlags = m_pendingUpdateFlags;
//if ((ObjectFlags & (uint)PrimFlags.Physics) != 0)
//{
// Only send the constant terse updates on physical objects!
//ScheduleTerseUpdate();
//}
// Update the "last" values if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
m_lastPosition = OffsetPosition; updateFlags |= PrimUpdateFlags.Rotation;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastTerseSent = Environment.TickCount;
}
}
else else
updateFlags &= ~PrimUpdateFlags.Rotation;
if (!Acceleration.Equals(m_lastAcceleration))
updateFlags |= PrimUpdateFlags.Acceleration;
else
updateFlags &= ~PrimUpdateFlags.Acceleration;
if (!Velocity.Equals(m_lastVelocity))
updateFlags |= PrimUpdateFlags.Velocity;
else
updateFlags &= ~PrimUpdateFlags.Velocity;
if (!AngularVelocity.Equals(m_lastAngularVelocity))
updateFlags |= PrimUpdateFlags.AngularVelocity;
else
updateFlags &= ~PrimUpdateFlags.AngularVelocity;
if (!RelativePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
updateFlags |= PrimUpdateFlags.Position;
else
updateFlags &= ~PrimUpdateFlags.Position;
// For good measure
//if (Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
// updateFlags |= PrimUpdateFlags.Position;
#endregion PrimUpdateFlags Management
if (updateFlags != PrimUpdateFlags.None)
{ {
if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes AddUpdateToAllAvatars(updateFlags);
{
AddFullUpdateToAllAvatars(); // Update the "last" values
ClearUpdateSchedule(); m_lastPosition = RelativePosition;
} m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastTerseSent = Environment.TickCount;
} }
ClearUpdateSchedule();
ClearPendingUpdate();
} }
/// <summary> /// <summary>
@ -3075,17 +2974,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Send a terse update to all clients
/// </summary>
public void SendTerseUpdateToAllClients()
{
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
SendTerseUpdateToClient(avatar.ControllingClient);
});
}
public void SetAttachmentPoint(uint AttachmentPoint) public void SetAttachmentPoint(uint AttachmentPoint)
{ {
this.AttachmentPoint = AttachmentPoint; this.AttachmentPoint = AttachmentPoint;
@ -3386,7 +3274,7 @@ namespace OpenSim.Region.Framework.Scenes
_groupID = groupID; _groupID = groupID;
if (client != null) if (client != null)
GetProperties(client); GetProperties(client);
m_updateFlag = 2; m_pendingUpdateFlags |= PrimUpdateFlags.FullUpdate;
} }
/// <summary> /// <summary>
@ -3448,14 +3336,13 @@ namespace OpenSim.Region.Framework.Scenes
Text = text; Text = text;
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.Text);
} }
public void StopLookAt() public void StopLookAt()
{ {
m_parentGroup.stopLookAt(); m_parentGroup.stopLookAt();
m_parentGroup.RootPart.ScheduleUpdate(PrimUpdateFlags.Rotation);
m_parentGroup.ScheduleGroupForTerseUpdate();
} }
/// <summary> /// <summary>
@ -3476,9 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes
public void StopMoveToTarget() public void StopMoveToTarget()
{ {
m_parentGroup.stopMoveToTarget(); m_parentGroup.stopMoveToTarget();
m_parentGroup.RootPart.ScheduleUpdate(PrimUpdateFlags.Position | PrimUpdateFlags.Rotation);
m_parentGroup.ScheduleGroupForTerseUpdate();
//m_parentGroup.ScheduleGroupForFullUpdate();
} }
public void StoreUndoState() public void StoreUndoState()
@ -4025,7 +3910,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.ExtraData);
} }
public void UpdateGroupPosition(Vector3 pos) public void UpdateGroupPosition(Vector3 pos)
@ -4036,7 +3921,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
GroupPosition = newPos; GroupPosition = newPos;
ScheduleTerseUpdate(); ScheduleUpdate(PrimUpdateFlags.Position);
} }
} }
@ -4054,21 +3939,19 @@ namespace OpenSim.Region.Framework.Scenes
(pos.Y != OffsetPosition.Y) || (pos.Y != OffsetPosition.Y) ||
(pos.Z != OffsetPosition.Z)) (pos.Z != OffsetPosition.Z))
{ {
Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
if (ParentGroup.RootPart.GetStatusSandbox()) if (ParentGroup.RootPart.GetStatusSandbox())
{ {
if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, pos) > 10)
{ {
ParentGroup.RootPart.ScriptSetPhysicsStatus(false); ParentGroup.RootPart.ScriptSetPhysicsStatus(false);
newPos = OffsetPosition; pos = OffsetPosition;
ParentGroup.Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), ParentGroup.Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
ChatTypeEnum.DebugChannel, 0x7FFFFFFF, ParentGroup.RootPart.AbsolutePosition, Name, UUID, false); ChatTypeEnum.DebugChannel, 0x7FFFFFFF, ParentGroup.RootPart.AbsolutePosition, Name, UUID, false);
} }
} }
OffsetPosition = newPos; OffsetPosition = pos;
ScheduleTerseUpdate(); ScheduleUpdate(PrimUpdateFlags.Position);
} }
} }
@ -4111,10 +3994,9 @@ namespace OpenSim.Region.Framework.Scenes
baseMask; baseMask;
break; break;
} }
SendFullUpdateToAllClients();
SendUpdateToAllClients(PrimUpdateFlags.PrimFlags);
SendObjectPropertiesToClient(AgentID); SendObjectPropertiesToClient(AgentID);
} }
} }
@ -4349,7 +4231,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.PrimFlags);
} }
public void UpdateRotation(Quaternion rot) public void UpdateRotation(Quaternion rot)
@ -4361,7 +4243,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
RotationOffset = rot; RotationOffset = rot;
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleTerseUpdate(); ScheduleUpdate(PrimUpdateFlags.Rotation);
} }
} }
@ -4405,7 +4287,7 @@ namespace OpenSim.Region.Framework.Scenes
ParentGroup.RootPart.Rezzed = DateTime.UtcNow; ParentGroup.RootPart.Rezzed = DateTime.UtcNow;
ParentGroup.HasGroupChanged = true; ParentGroup.HasGroupChanged = true;
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.PrimData);
} }
/// <summary> /// <summary>
@ -4452,7 +4334,7 @@ namespace OpenSim.Region.Framework.Scenes
//This is madness.. //This is madness..
//ParentGroup.ScheduleGroupForFullUpdate(); //ParentGroup.ScheduleGroupForFullUpdate();
//This is sparta //This is sparta
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.Textures);
} }
public void aggregateScriptEvents() public void aggregateScriptEvents()
@ -4520,7 +4402,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents() since m_parentGroup == null", Name, LocalId); // "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents() since m_parentGroup == null", Name, LocalId);
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.FullUpdate);
return; return;
} }
@ -4543,7 +4425,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId); // "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
ScheduleFullUpdate(); ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
@ -4618,35 +4500,6 @@ namespace OpenSim.Region.Framework.Scenes
#endregion Public Methods #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) public void AddScriptLPS(int count)
{ {
m_parentGroup.AddScriptLPS(count); m_parentGroup.AddScriptLPS(count);
@ -4694,7 +4547,7 @@ namespace OpenSim.Region.Framework.Scenes
public Color4 GetTextColor() 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

@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1); m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate(); m_part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
return; return;
} }
@ -306,7 +306,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1); m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate(); m_part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
} }
@ -697,7 +697,7 @@ namespace OpenSim.Region.Framework.Scenes
m_part.RemFlag(PrimFlags.Scripted); m_part.RemFlag(PrimFlags.Scripted);
} }
m_part.ScheduleFullUpdate(); m_part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
return type; return type;
} }

View File

@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence);
public class ScenePresence : EntityBase public class ScenePresence : EntityBase, ISceneEntity
{ {
// ~ScenePresence() // ~ScenePresence()
// { // {
@ -479,6 +479,12 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public Vector3 OffsetPosition
{
get { return m_pos; }
set { m_pos = value; }
}
/// <summary> /// <summary>
/// Current velocity of the avatar. /// Current velocity of the avatar.
/// </summary> /// </summary>
@ -777,15 +783,9 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Add the part to the queue of parts for which we need to send an update to the client /// Add the part to the queue of parts for which we need to send an update to the client
/// </summary> /// </summary>
/// <param name="part"></param> public void QueuePartForUpdate(SceneObjectPart part, PrimUpdateFlags updateFlags)
public void QueuePartForUpdate(SceneObjectPart part)
{ {
m_sceneViewer.QueuePartForUpdate(part); m_sceneViewer.QueuePartForUpdate(part, updateFlags);
}
public uint GenerateClientFlags(UUID ObjectID)
{
return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
} }
/// <summary> /// <summary>
@ -1032,8 +1032,9 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
} }
ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, CollisionPlane = new Vector4(0f, 0f, 1f, AbsolutePosition.Z - 0.5f);
AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
ControllingClient.SendEntityUpdate(GetUpdatePriority(ControllingClient), this, PrimUpdateFlags.Position | PrimUpdateFlags.Velocity);
} }
public void AddNeighbourRegion(ulong regionHandle, string cap) public void AddNeighbourRegion(ulong regionHandle, string cap)
@ -1571,7 +1572,7 @@ namespace OpenSim.Region.Framework.Scenes
// Commented out this code since it could never have executed, but might still be informative. // Commented out this code since it could never have executed, but might still be informative.
// if (proxyObjectGroup != null) // if (proxyObjectGroup != null)
// { // {
proxyObjectGroup.SendGroupFullUpdate(); proxyObjectGroup.SendGroupUpdate(PrimUpdateFlags.FullUpdate);
remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
m_scene.DeleteSceneObject(proxyObjectGroup, false); m_scene.DeleteSceneObject(proxyObjectGroup, false);
// } // }
@ -2356,8 +2357,8 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); //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, remoteClient.SendEntityUpdate(GetUpdatePriority(remoteClient), this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation |
pos, velocity, Vector3.Zero, m_bodyRot, CollisionPlane, m_uuid, null, GetUpdatePriority(remoteClient))); PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity | PrimUpdateFlags.CollisionPlane);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
m_scene.StatsReporter.AddAgentUpdates(1); m_scene.StatsReporter.AddAgentUpdates(1);
@ -2453,9 +2454,8 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos; Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset; pos.Z += m_appearance.HipOffset;
remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, remoteAvatar.m_controllingClient.SendEntityUpdate(GetUpdatePriority(remoteAvatar.m_controllingClient), this, PrimUpdateFlags.FullUpdate);
LocalId, pos, m_appearance.Texture.GetBytes(),
m_parentID, m_bodyRot));
m_scene.StatsReporter.AddAgentUpdates(1); m_scene.StatsReporter.AddAgentUpdates(1);
} }
@ -2523,8 +2523,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos; Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset; pos.Z += m_appearance.HipOffset;
m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, m_controllingClient.SendEntityUpdate(GetUpdatePriority(m_controllingClient), this, PrimUpdateFlags.FullUpdate);
pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
SendInitialFullUpdateToAllClients(); SendInitialFullUpdateToAllClients();
SendAppearanceToAllOtherAgents(); SendAppearanceToAllOtherAgents();
@ -2634,9 +2633,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 pos = m_pos; Vector3 pos = m_pos;
pos.Z += m_appearance.HipOffset; pos.Z += m_appearance.HipOffset;
m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, m_controllingClient.SendEntityUpdate(GetUpdatePriority(m_controllingClient), this, PrimUpdateFlags.Textures);
pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
} }
public void SetWearable(int wearableId, AvatarWearable wearable) public void SetWearable(int wearableId, AvatarWearable wearable)
@ -3902,7 +3899,7 @@ namespace OpenSim.Region.Framework.Scenes
private void Reprioritize(object sender, ElapsedEventArgs e) private void Reprioritize(object sender, ElapsedEventArgs e)
{ {
m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority); m_controllingClient.ReprioritizeUpdates(UpdatePriority);
lock (m_reprioritization_timer) lock (m_reprioritization_timer)
{ {

View File

@ -38,6 +38,12 @@ namespace OpenSim.Region.Framework.Scenes
{ {
public class SceneViewer : ISceneViewer public class SceneViewer : ISceneViewer
{ {
public class ScenePartUpdate
{
public UUID FullID;
public uint LastUpdateTime;
}
protected ScenePresence m_presence; protected ScenePresence m_presence;
protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
protected Queue<SceneObjectGroup> m_pendingObjects; protected Queue<SceneObjectGroup> m_pendingObjects;
@ -56,13 +62,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Add the part to the queue of parts for which we need to send an update to the client /// Add the part to the queue of parts for which we need to send an update to the client
/// </summary> /// </summary>
/// <param name="part"></param> public void QueuePartForUpdate(SceneObjectPart part, PrimUpdateFlags updateFlags)
public void QueuePartForUpdate(SceneObjectPart part)
{ {
lock (m_partsUpdateQueue) lock (m_partsUpdateQueue)
{ m_partsUpdateQueue.Enqueue(part, updateFlags);
m_partsUpdateQueue.Enqueue(part);
}
} }
public void SendPrimUpdates() public void SendPrimUpdates()
@ -94,14 +97,15 @@ namespace OpenSim.Region.Framework.Scenes
// Don't even queue if we have sent this one // Don't even queue if we have sent this one
// //
if (!m_updateTimes.ContainsKey(g.UUID)) if (!m_updateTimes.ContainsKey(g.UUID))
g.ScheduleFullUpdateToAvatar(m_presence); g.ScheduleUpdateToAvatar(m_presence, PrimUpdateFlags.FullUpdate);
} }
while (m_partsUpdateQueue.Count > 0) SceneObjectPart part;
{ PrimUpdateFlags updateFlags;
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
if (part.ParentGroup == null || part.ParentGroup.IsDeleted) while (m_partsUpdateQueue.TryDequeue(out part, out updateFlags))
{
if (part.ParentGroup.IsDeleted)
continue; continue;
if (m_updateTimes.ContainsKey(part.UUID)) if (m_updateTimes.ContainsKey(part.UUID))
@ -111,15 +115,13 @@ namespace OpenSim.Region.Framework.Scenes
// We deal with the possibility that two updates occur at // We deal with the possibility that two updates occur at
// the same unix time at the update point itself. // the same unix time at the update point itself.
if ((update.LastFullUpdateTime < part.TimeStampFull) || if ((update.LastUpdateTime < part.TimeStampUpdate) || part.IsAttachment)
part.IsAttachment)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}", // "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampFull); // part.Name, part.UUID, part.TimeStampFull);
part.SendFullUpdate(m_presence.ControllingClient, part.SendUpdateToClient(m_presence.ControllingClient, updateFlags);
m_presence.GenerateClientFlags(part.UUID));
// We'll update to the part's timestamp rather than // We'll update to the part's timestamp rather than
// the current time to avoid the race condition // the current time to avoid the race condition
@ -128,18 +130,7 @@ namespace OpenSim.Region.Framework.Scenes
// updates which occurred on the same tick or the // updates which occurred on the same tick or the
// next tick of the last update would be ignored. // next tick of the last update would be ignored.
update.LastFullUpdateTime = part.TimeStampFull; update.LastUpdateTime = part.TimeStampUpdate;
}
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampTerse);
part.SendTerseUpdateToClient(m_presence.ControllingClient);
update.LastTerseUpdateTime = part.TimeStampTerse;
} }
} }
else else
@ -147,7 +138,7 @@ namespace OpenSim.Region.Framework.Scenes
//never been sent to client before so do full update //never been sent to client before so do full update
ScenePartUpdate update = new ScenePartUpdate(); ScenePartUpdate update = new ScenePartUpdate();
update.FullID = part.UUID; update.FullID = part.UUID;
update.LastFullUpdateTime = part.TimeStampFull; update.LastUpdateTime = part.TimeStampUpdate;
m_updateTimes.Add(part.UUID, update); m_updateTimes.Add(part.UUID, update);
// Attachment handling // Attachment handling
@ -157,12 +148,11 @@ namespace OpenSim.Region.Framework.Scenes
if (part != part.ParentGroup.RootPart) if (part != part.ParentGroup.RootPart)
continue; continue;
part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient); part.ParentGroup.SendUpdateToClient(m_presence.ControllingClient, PrimUpdateFlags.FullUpdate);
continue; continue;
} }
part.SendFullUpdate(m_presence.ControllingClient, part.SendUpdateToClient(m_presence.ControllingClient, PrimUpdateFlags.FullUpdate);
m_presence.GenerateClientFlags(part.UUID));
} }
} }
} }
@ -192,19 +182,5 @@ namespace OpenSim.Region.Framework.Scenes
} }
Reset(); Reset();
} }
public class ScenePartUpdate
{
public UUID FullID;
public uint LastFullUpdateTime;
public uint LastTerseUpdateTime;
public ScenePartUpdate()
{
FullID = UUID.Zero;
LastFullUpdateTime = 0;
LastTerseUpdateTime = 0;
}
}
} }
} }

View File

@ -72,8 +72,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0)); grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
// Required for linking // Required for linking
grp1.RootPart.UpdateFlag = 0; grp1.RootPart.ClearPendingUpdate();
grp2.RootPart.UpdateFlag = 0; grp2.RootPart.ClearPendingUpdate();
// Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
grp1.LinkToGroup(grp2); grp1.LinkToGroup(grp2);
@ -165,10 +165,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
grp4.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 90 * Utils.DEG_TO_RAD, 0)); grp4.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 90 * Utils.DEG_TO_RAD, 0));
// Required for linking // Required for linking
grp1.RootPart.UpdateFlag = 0; grp1.RootPart.ClearPendingUpdate();
grp2.RootPart.UpdateFlag = 0; grp2.RootPart.ClearPendingUpdate();
grp3.RootPart.UpdateFlag = 0; grp3.RootPart.ClearPendingUpdate();
grp4.RootPart.UpdateFlag = 0; grp4.RootPart.ClearPendingUpdate();
// Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
grp1.LinkToGroup(grp2); grp1.LinkToGroup(grp2);
@ -199,8 +199,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
} }
// Required for linking // Required for linking
grp1.RootPart.UpdateFlag = 0; grp1.RootPart.ClearPendingUpdate();
grp3.RootPart.UpdateFlag = 0; grp3.RootPart.ClearPendingUpdate();
// root part should have no offset position or rotation // root part should have no offset position or rotation
Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity, Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity,

View File

@ -30,16 +30,21 @@ using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security.Permissions; using System.Security.Permissions;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Scenes.Types namespace OpenSim.Region.Framework.Scenes.Types
{ {
public class UpdateQueue public class UpdateQueue
{ {
private Queue<SceneObjectPart> m_queue; private struct Update
{
private Dictionary<UUID, bool> m_ids; public SceneObjectPart Entity;
public PrimUpdateFlags UpdateFlags;
}
private Queue<Update> m_queue;
private HashSet<UUID> m_ids;
private object m_syncObject = new object(); private object m_syncObject = new object();
public int Count public int Count
@ -49,8 +54,8 @@ namespace OpenSim.Region.Framework.Scenes.Types
public UpdateQueue() public UpdateQueue()
{ {
m_queue = new Queue<SceneObjectPart>(); m_queue = new Queue<Update>();
m_ids = new Dictionary<UUID, bool>(); m_ids = new HashSet<UUID>();
} }
public void Clear() public void Clear()
@ -62,30 +67,33 @@ namespace OpenSim.Region.Framework.Scenes.Types
} }
} }
public void Enqueue(SceneObjectPart part) public void Enqueue(SceneObjectPart part, PrimUpdateFlags updateFlags)
{ {
lock (m_syncObject) lock (m_syncObject)
{ {
if (!m_ids.ContainsKey(part.UUID)) { if (m_ids.Add(part.UUID))
m_ids.Add(part.UUID, true); m_queue.Enqueue(new Update { Entity = part, UpdateFlags = updateFlags });
m_queue.Enqueue(part);
}
} }
} }
public SceneObjectPart Dequeue() public bool TryDequeue(out SceneObjectPart part, out PrimUpdateFlags updateFlags)
{ {
SceneObjectPart part = null;
lock (m_syncObject) lock (m_syncObject)
{ {
if (m_queue.Count > 0) if (m_queue.Count > 0)
{ {
part = m_queue.Dequeue(); Update update = m_queue.Dequeue();
part = update.Entity;
updateFlags = update.UpdateFlags;
m_ids.Remove(part.UUID); m_ids.Remove(part.UUID);
return true;
} }
} }
return part; part = null;
updateFlags = 0;
return false;
} }
} }
} }

View File

@ -26,6 +26,7 @@
*/ */
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.Framework.Scenes namespace OpenSim.Region.Framework.Scenes
@ -41,17 +42,12 @@ namespace OpenSim.Region.Framework.Scenes
if (part != null) if (part != null)
{ {
if (part.ParentID == 0) if (part.ParentID == 0)
{
Position = part.ParentGroup.AbsolutePosition; Position = part.ParentGroup.AbsolutePosition;
Rotation = part.RotationOffset;
Scale = part.Shape.Scale;
}
else else
{
Position = part.OffsetPosition; Position = part.OffsetPosition;
Rotation = part.RotationOffset;
Scale = part.Shape.Scale; Rotation = part.RotationOffset;
} Scale = part.Shape.Scale;
} }
} }
@ -83,56 +79,48 @@ namespace OpenSim.Region.Framework.Scenes
if (part != null) if (part != null)
{ {
part.Undoing = true; part.Undoing = true;
PrimUpdateFlags updateFlags = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation;
if (part.ParentID == 0) if (part.ParentID == 0)
{ part.ParentGroup.AbsolutePosition = Position;
if (Position != Vector3.Zero)
part.ParentGroup.AbsolutePosition = Position;
part.RotationOffset = Rotation;
if (Scale != Vector3.Zero)
part.Resize(Scale);
part.ParentGroup.ScheduleGroupForTerseUpdate();
}
else else
{ part.OffsetPosition = Position;
if (Position != Vector3.Zero)
part.OffsetPosition = Position;
part.UpdateRotation(Rotation);
if (Scale != Vector3.Zero)
part.Resize(Scale); part.ScheduleTerseUpdate();
}
part.Undoing = false;
part.RotationOffset = Rotation;
if (Scale != part.Scale)
{
part.Scale = Scale;
updateFlags |= PrimUpdateFlags.Scale;
}
part.Undoing = false;
part.ScheduleUpdate(updateFlags);
} }
} }
public void PlayfwdState(SceneObjectPart part) public void PlayfwdState(SceneObjectPart part)
{ {
if (part != null) if (part != null)
{ {
part.Undoing = true; part.Undoing = true;
PrimUpdateFlags updateFlags = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation;
if (part.ParentID == 0) if (part.ParentID == 0)
{ part.ParentGroup.AbsolutePosition = Position;
if (Position != Vector3.Zero)
part.ParentGroup.AbsolutePosition = Position;
if (Rotation != Quaternion.Identity)
part.UpdateRotation(Rotation);
if (Scale != Vector3.Zero)
part.Resize(Scale);
part.ParentGroup.ScheduleGroupForTerseUpdate();
}
else else
{ part.OffsetPosition = Position;
if (Position != Vector3.Zero)
part.OffsetPosition = Position;
if (Rotation != Quaternion.Identity)
part.UpdateRotation(Rotation);
if (Scale != Vector3.Zero)
part.Resize(Scale);
part.ScheduleTerseUpdate();
}
part.Undoing = false;
part.RotationOffset = Rotation;
if (Scale != part.Scale)
{
part.Scale = Scale;
updateFlags |= PrimUpdateFlags.Scale;
}
part.Undoing = false;
part.ScheduleUpdate(updateFlags);
} }
} }
} }

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 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) 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 ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}
public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{ {
} }

View File

@ -284,7 +284,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
((SceneObjectGroup)ent).ApplyPhysics(true); ((SceneObjectGroup)ent).ApplyPhysics(true);
((SceneObjectGroup)ent).AttachToBackup(); ((SceneObjectGroup)ent).AttachToBackup();
((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected.
((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); ((SceneObjectGroup)ent).ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -193,20 +193,14 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
public void SendFullUpdate(IClientAPI client) public void SendFullUpdate(IClientAPI client)
{ {
// Not sure what clientFlags should be but 0 seems to work m_Entity.SendUpdateToClient(client, PrimUpdateFlags.FullUpdate);
SendFullUpdate(client, 0);
}
public void SendFullUpdate(IClientAPI client, uint clientFlags)
{
m_Entity.SendFullUpdateToClient(client);
} }
public void SendFullUpdateToAll() public void SendFullUpdateToAll()
{ {
m_Entity.Scene.ForEachClient( m_Entity.Scene.ForEachClient(
delegate(IClientAPI controller) delegate(IClientAPI client)
{ m_Entity.SendFullUpdateToClient(controller); } { m_Entity.SendUpdateToClient(client, PrimUpdateFlags.FullUpdate); }
); );
} }

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 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) 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 ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{ {
} }

View File

@ -641,7 +641,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{ {
s_tree.Scale += copse.m_rate; s_tree.Scale += copse.m_rate;
s_tree.ParentGroup.HasGroupChanged = true; s_tree.ParentGroup.HasGroupChanged = true;
s_tree.ScheduleFullUpdate(); s_tree.ScheduleUpdate(PrimUpdateFlags.Scale);
} }
} }
else else
@ -773,7 +773,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
tree.Name = copse.ToString(); tree.Name = copse.ToString();
copse.m_trees.Add(tree.UUID); copse.m_trees.Add(tree.UUID);
tree.SendGroupFullUpdate(); tree.SendGroupUpdate(PrimUpdateFlags.FullUpdate);
} }
} }

View File

@ -1329,7 +1329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
tmp.Y = (float)scale.y; tmp.Y = (float)scale.y;
tmp.Z = (float)scale.z; tmp.Z = (float)scale.z;
part.Scale = tmp; part.Scale = tmp;
part.SendFullUpdateToAllClients(); part.SendUpdateToAllClients(PrimUpdateFlags.Scale);
} }
public LSL_Vector llGetScale() public LSL_Vector llGetScale()
@ -1343,7 +1343,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.ClickAction = (byte)action; m_host.ClickAction = (byte)action;
if (m_host.ParentGroup != null) m_host.ParentGroup.HasGroupChanged = true; if (m_host.ParentGroup != null) m_host.ParentGroup.HasGroupChanged = true;
m_host.ScheduleFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.PrimFlags);
return; return;
} }
@ -1595,7 +1595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
part.ParentGroup.HasGroupChanged = true; part.ParentGroup.HasGroupChanged = true;
part.ScheduleFullUpdate(); part.ScheduleUpdate(PrimUpdateFlags.ExtraData);
} }
/// <summary> /// <summary>
@ -1630,7 +1630,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
part.ParentGroup.HasGroupChanged = true; part.ParentGroup.HasGroupChanged = true;
part.ScheduleFullUpdate(); part.ScheduleUpdate(PrimUpdateFlags.ExtraData);
} }
public LSL_Vector llGetColor(int face) public LSL_Vector llGetColor(int face)
@ -1913,7 +1913,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.OffsetPosition = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z); part.OffsetPosition = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z);
SceneObjectGroup parent = part.ParentGroup; SceneObjectGroup parent = part.ParentGroup;
parent.HasGroupChanged = true; parent.HasGroupChanged = true;
parent.ScheduleGroupForTerseUpdate(); part.ScheduleUpdate(PrimUpdateFlags.Position);
} }
} }
} }
@ -2245,8 +2245,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundFlags = 1; // looping m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.Sound);
m_host.SendFullUpdateToAllClients(); m_host.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
public void llLoopSoundMaster(string sound, double volume) public void llLoopSoundMaster(string sound, double volume)
@ -2265,8 +2265,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
prim.SoundFlags = 1; // looping prim.SoundFlags = 1; // looping
prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
prim.ScheduleFullUpdate(); prim.ScheduleUpdate(PrimUpdateFlags.Sound);
prim.SendFullUpdateToAllClients(); prim.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
} }
if (m_host.Sound != UUID.Zero) if (m_host.Sound != UUID.Zero)
@ -2277,8 +2277,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundFlags = 1; // looping m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.Sound);
m_host.SendFullUpdateToAllClients(); m_host.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
public void llLoopSoundSlave(string sound, double volume) public void llLoopSoundSlave(string sound, double volume)
@ -2319,8 +2319,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.SoundGain = 0; part.SoundGain = 0;
part.SoundFlags = 0; part.SoundFlags = 0;
part.SoundRadius = 0; part.SoundRadius = 0;
part.ScheduleFullUpdate(); part.ScheduleUpdate(PrimUpdateFlags.Sound);
part.SendFullUpdateToAllClients(); part.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
m_host.ParentGroup.LoopSoundMasterPrim = null; m_host.ParentGroup.LoopSoundMasterPrim = null;
m_host.ParentGroup.LoopSoundSlavePrims.Clear(); m_host.ParentGroup.LoopSoundSlavePrims.Clear();
@ -2331,8 +2331,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundGain = 0; m_host.SoundGain = 0;
m_host.SoundFlags = 0; m_host.SoundFlags = 0;
m_host.SoundRadius = 0; m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.Sound);
m_host.SendFullUpdateToAllClients(); m_host.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
} }
else else
@ -2341,8 +2341,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.SoundGain = 0; m_host.SoundGain = 0;
m_host.SoundFlags = 0; m_host.SoundFlags = 0;
m_host.SoundRadius = 0; m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.Sound);
m_host.SendFullUpdateToAllClients(); m_host.SendUpdateToAllClients(PrimUpdateFlags.Sound);
} }
} }
@ -3240,8 +3240,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
m_host.ScheduleTerseUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.AngularVelocity);
m_host.SendTerseUpdateToAllClients(); m_host.SendUpdateToAllClients(PrimUpdateFlags.AngularVelocity);
m_host.ParentGroup.HasGroupChanged = true; m_host.ParentGroup.HasGroupChanged = true;
} }
@ -3507,7 +3507,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
childPrim = m_host.ParentGroup; childPrim = m_host.ParentGroup;
} }
// byte uf = childPrim.RootPart.UpdateFlag; // byte uf = childPrim.RootPart.UpdateFlag;
childPrim.RootPart.UpdateFlag = 0; childPrim.RootPart.ClearPendingUpdate();
parentPrim.LinkToGroup(childPrim); parentPrim.LinkToGroup(childPrim);
// if (uf != (Byte)0) // if (uf != (Byte)0)
// parent.RootPart.UpdateFlag = uf; // parent.RootPart.UpdateFlag = uf;
@ -3516,7 +3516,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.TriggerScriptChangedEvent(Changed.LINK); parentPrim.TriggerScriptChangedEvent(Changed.LINK);
parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected); parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
parentPrim.HasGroupChanged = true; parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate(); parentPrim.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
if (client != null) if (client != null)
parentPrim.GetProperties(client); parentPrim.GetProperties(client);
@ -3582,7 +3582,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.DelinkFromGroup(part.LocalId, true); parentPrim.DelinkFromGroup(part.LocalId, true);
} }
parentPrim.HasGroupChanged = true; parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate(); parentPrim.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
parentPrim.TriggerScriptChangedEvent(Changed.LINK); parentPrim.TriggerScriptChangedEvent(Changed.LINK);
if (parts.Count > 0) if (parts.Count > 0)
@ -3591,11 +3591,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parts.Remove(newRoot); parts.Remove(newRoot);
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
{ {
part.UpdateFlag = 0; part.ClearPendingUpdate();
newRoot.ParentGroup.LinkToGroup(part.ParentGroup); newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
} }
newRoot.ParentGroup.HasGroupChanged = true; newRoot.ParentGroup.HasGroupChanged = true;
newRoot.ParentGroup.ScheduleGroupForFullUpdate(); newRoot.ParentGroup.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
} }
else else
@ -3605,7 +3605,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.DelinkFromGroup(childPrim.LocalId, true); parentPrim.DelinkFromGroup(childPrim.LocalId, true);
parentPrim.HasGroupChanged = true; parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate(); parentPrim.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
parentPrim.TriggerScriptChangedEvent(Changed.LINK); parentPrim.TriggerScriptChangedEvent(Changed.LINK);
} }
} }
@ -3626,7 +3626,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parentPrim.TriggerScriptChangedEvent(Changed.LINK); parentPrim.TriggerScriptChangedEvent(Changed.LINK);
} }
parentPrim.HasGroupChanged = true; parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate(); parentPrim.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdate);
} }
public LSL_String llGetLinkKey(int linknum) public LSL_String llGetLinkKey(int linknum)
@ -3866,7 +3866,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Util.Clip((float)color.z, 0.0f, 1.0f)); Util.Clip((float)color.z, 0.0f, 1.0f));
m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
m_host.ParentGroup.HasGroupChanged = true; m_host.ParentGroup.HasGroupChanged = true;
m_host.ParentGroup.ScheduleGroupForFullUpdate(); m_host.ScheduleUpdate(PrimUpdateFlags.Text);
} }
public LSL_Float llWater(LSL_Vector offset) public LSL_Float llWater(LSL_Vector offset)
@ -5467,7 +5467,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
pTexAnim.Start = (float)start; pTexAnim.Start = (float)start;
part.AddTextureAnimation(pTexAnim); part.AddTextureAnimation(pTexAnim);
part.SendFullUpdateToAllClients(); part.SendUpdateToAllClients(PrimUpdateFlags.TextureAnim);
part.ParentGroup.HasGroupChanged = true; part.ParentGroup.HasGroupChanged = true;
} }
@ -6029,7 +6029,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.AddNewParticleSystem(prules); part.AddNewParticleSystem(prules);
part.ParentGroup.HasGroupChanged = true; part.ParentGroup.HasGroupChanged = true;
} }
part.SendFullUpdateToAllClients(); part.SendUpdateToAllClients(PrimUpdateFlags.Particles);
} }
public void llGroundRepel(double height, int water, double tau) public void llGroundRepel(double height, int water, double tau)

View File

@ -0,0 +1,283 @@
/*
* 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.Collections.Specialized;
using System.Net;
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Services.Connectors.SimianGrid
{
/// <summary>
/// Handles logins and teleports
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class RezAvatar : INonSharedRegionModule
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
private GridRegion m_gridRegion;
private ISimulationService m_simulationService;
#region INonSharedRegionModule
public Type ReplaceableInterface { get { return null; } }
public void RegionLoaded(Scene scene) { }
public void Close() { }
public RezAvatar() { }
public string Name { get { return "RezAvatar"; } }
public void AddRegion(Scene scene)
{
m_scene = scene;
m_gridRegion = new GridRegion
{
RegionID = scene.RegionInfo.RegionID,
RegionLocX = (int)scene.RegionInfo.RegionLocX,
RegionLocY = (int)scene.RegionInfo.RegionLocY,
RegionName = scene.RegionInfo.RegionName
};
if (Simian.IsSimianEnabled(scene.Config, "UserAccountServices", "SimianUserAccountServiceConnector"))
{
m_simulationService = scene.RequestModuleInterface<ISimulationService>();
if (m_simulationService != null)
m_simulationService = m_simulationService.GetInnerService();
string urlFriendlySceneName = WebUtil.UrlEncode(scene.RegionInfo.RegionName);
MainServer.Instance.AddStreamHandler(new HttpStreamHandler("application/xml+llsd", "GET", "/scenes/" + urlFriendlySceneName + "/public_region_seed_capability",
PublicRegionSeedCapabilityHandler));
MainServer.Instance.AddStreamHandler(new HttpStreamHandler(null, "POST", "/scenes/" + urlFriendlySceneName + "/rez_avatar/request",
RezAvatarRequestHandler));
}
}
public void RemoveRegion(Scene scene)
{
if (Simian.IsSimianEnabled(scene.Config, "UserAccountServices", this.Name))
{
string urlFriendlySceneName = WebUtil.UrlEncode(scene.RegionInfo.RegionName);
MainServer.Instance.RemoveStreamHandler("GET", "/scenes/" + urlFriendlySceneName + "/public_region_seed_capability");
MainServer.Instance.RemoveStreamHandler("GET", "/scenes/" + urlFriendlySceneName + "/rez_avatar/request");
}
m_scene = null;
}
#endregion INonSharedRegionModule
public RezAvatar(IConfigSource source)
{
}
public void Initialise(IConfigSource source)
{
}
private void PublicRegionSeedCapabilityHandler(OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
// Build a seed capability response that contains the rez_avatar/request capability (a hardcoded URL)
OSDMap responseMap = new OSDMap();
Uri httpAddress = new Uri("http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + "/");
string urlFriendlySceneName = WebUtil.UrlEncode(m_scene.RegionInfo.RegionName);
OSDMap capabilities = new OSDMap();
capabilities["rez_avatar/request"] = OSD.FromUri(new Uri(httpAddress, "/scenes/" + urlFriendlySceneName + "/rez_avatar/request"));
responseMap["capabilities"] = capabilities;
WebUtil.SendJSONResponse(httpResponse, responseMap);
}
private void RezAvatarRequestHandler(OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
OSDMap requestMap = null;
try { requestMap = OSDParser.Deserialize(httpRequest.InputStream) as OSDMap; }
catch { }
Vector3 lookAt = Vector3.UnitX;
RegionInfo regInfo = m_scene.RegionInfo;
// Unpack the rez_avatar/request into an AgentCircuitData structure
AgentCircuitData agentCircuit = BuildAgentCircuitFromRezAvatarRequest(requestMap);
OSDMap responseMap = new OSDMap();
if (agentCircuit != null && agentCircuit.AgentID != UUID.Zero)
{
if (agentCircuit.startpos == Vector3.Zero)
{
m_log.Info("rez_avatar/request did not contain a position, setting to default");
agentCircuit.startpos = new Vector3(128f, 128f, 25f);
}
// Attempt to create an agent from the AgentCircuitData info
string reason;
if (m_simulationService.CreateAgent(m_gridRegion, agentCircuit, agentCircuit.teleportFlags, out reason))
{
// Build the seed capability URL for this agent
Uri seedCapability = new Uri("http://" + regInfo.ExternalHostName + ":" + regInfo.HttpPort + "/CAPS/" + agentCircuit.CapsPath + "0000/");
m_log.Info("rez_avatar/request created agent " + agentCircuit.firstname + " " + agentCircuit.lastname +
" with circuit code " + agentCircuit.circuitcode + " and seed capability " + seedCapability);
IPAddress externalAddress = regInfo.ExternalEndPoint.Address;
uint regionX, regionY;
Utils.LongToUInts(regInfo.RegionHandle, out regionX, out regionY);
responseMap["connect"] = OSD.FromBoolean(true);
responseMap["agent_id"] = OSD.FromUUID(agentCircuit.AgentID);
responseMap["sim_host"] = OSD.FromString(externalAddress.ToString());
responseMap["sim_port"] = OSD.FromInteger(regInfo.ExternalEndPoint.Port);
responseMap["region_seed_capability"] = OSD.FromUri(seedCapability);
responseMap["position"] = OSD.FromVector3(agentCircuit.startpos);
responseMap["look_at"] = OSD.FromVector3(lookAt);
// Region information
responseMap["region_id"] = OSD.FromUUID(regInfo.RegionID);
responseMap["region_x"] = OSD.FromInteger(regionX);
responseMap["region_y"] = OSD.FromInteger(regionY);
}
else
{
m_log.Warn("Denied rez_avatar/request for " + agentCircuit.firstname + " " + agentCircuit.lastname + ": " + reason);
responseMap["message"] = OSD.FromString(reason);
}
}
else
{
responseMap["message"] = OSD.FromString("Invalid or incomplete request");
}
WebUtil.SendJSONResponse(httpResponse, responseMap);
}
private static AgentCircuitData BuildAgentCircuitFromRezAvatarRequest(OSDMap request)
{
AgentCircuitData agentCircuit = new AgentCircuitData();
agentCircuit.AgentID = request["agent_id"].AsUUID();
agentCircuit.BaseFolder = request["base_folder"].AsUUID();
agentCircuit.CapsPath = request["caps_path"].AsString();
agentCircuit.child = request["child_agent"].AsBoolean();
agentCircuit.circuitcode = request["circuit_code"].AsUInteger();
agentCircuit.firstname = request["first_name"].AsString();
agentCircuit.InventoryFolder = request["inventory_folder"].AsUUID();
agentCircuit.lastname = request["last_name"].AsString();
agentCircuit.SecureSessionID = request["secure_session_id"].AsUUID();
agentCircuit.ServiceSessionID = String.Empty;
agentCircuit.ServiceURLs = new Dictionary<string, object>(0);
agentCircuit.SessionID = request["session_id"].AsUUID();
agentCircuit.startpos = request["position"].AsVector3();
agentCircuit.teleportFlags = request["teleport_flags"].AsUInteger();
if (agentCircuit.teleportFlags == 0)
agentCircuit.teleportFlags = (uint)TeleportFlags.ViaLogin;
#region Children Seed Caps
if (request["children_seeds"].Type == OSDType.Array)
{
OSDArray childrenSeeds = (OSDArray)request["children_seeds"];
agentCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>(childrenSeeds.Count);
for (int i = 0; i < childrenSeeds.Count; i++)
{
if (childrenSeeds[i].Type == OSDType.Map)
{
OSDMap pair = (OSDMap)childrenSeeds[i];
ulong handle;
if (!UInt64.TryParse(pair["handle"].AsString(), out handle))
continue;
string seed = pair["seed"].AsString();
if (!agentCircuit.ChildrenCapSeeds.ContainsKey(handle))
agentCircuit.ChildrenCapSeeds.Add(handle, seed);
}
}
}
else
{
agentCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>(0);
}
#endregion Children Seed Caps
#region Appearance
agentCircuit.Appearance = new AvatarAppearance(agentCircuit.AgentID);
agentCircuit.Appearance.Serial = request["appearance_serial"].AsInteger();
if (request["wearables"].Type == OSDType.Array)
{
OSDArray wearables = (OSDArray)request["wearables"];
for (int i = 0; i < wearables.Count / 2; i++)
{
agentCircuit.Appearance.Wearables[i].ItemID = wearables[i * 2].AsUUID();
agentCircuit.Appearance.Wearables[i].AssetID = wearables[(i * 2) + 1].AsUUID();
}
}
if (request["attachments"].Type == OSDType.Array)
{
OSDArray attachArray = (OSDArray)request["attachments"];
List<AttachmentData> attachments = new List<AttachmentData>(attachArray.Count);
for (int i = 0; i < attachArray.Count; i++)
{
if (attachArray[i].Type == OSDType.Map)
attachments.Add(new AttachmentData((OSDMap)attachArray[i]));
}
agentCircuit.Appearance.SetAttachments(attachments.ToArray());
}
#endregion Appearance
return agentCircuit;
}
private static OSDMap BuildRezAvatarRequestFromAgentCircuit(AgentCircuitData agentCircuit)
{
return new OSDMap();
}
}
}

View File

@ -88,7 +88,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
{ {
if (Simian.IsSimianEnabled(source, "UserAccountServices", this.Name)) if (Simian.IsSimianEnabled(source, "UserAccountServices", "SimianUserAccountServiceConnector"))
{ {
IConfig gridConfig = source.Configs["UserAccountService"]; IConfig gridConfig = source.Configs["UserAccountService"];
if (gridConfig == null) if (gridConfig == null)

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 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) 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 ReprioritizeUpdates(UpdatePriorityHandler handler)
{
}
public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
{
}
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{ {
} }

View File

@ -369,18 +369,13 @@
;asset_limit = 27500 ;asset_limit = 27500
;state_limit = 37000 ;state_limit = 37000
; Configures how ObjectUpdates are aggregated. These numbers ; Configures how scene graph updates are sent to clients.
; do not literally mean how many updates will be put in each ; This controls the balance between responsiveness of interest
; packet that goes over the wire, as packets are ; list updates and total throughput. A higher value will ensure
; automatically split on a 1400 byte boundary. These control ; more full-sized packets and faster sending of data, but more
; the balance between responsiveness of interest list updates ; delay in updating client interest lists
; and total throughput. Higher numbers will ensure more full-
; sized packets and faster sending of data, but more delay in
; updating interest lists
; ;
;PrimTerseUpdatesPerPacket = 25 PrimUpdatesPerCallback = 100
;AvatarTerseUpdatesPerPacket = 10
;PrimFullUpdatesPerPacket = 100
; TextureSendLimit determines how many packets will be put on ; TextureSendLimit determines how many packets will be put on
; the outgoing queue each cycle. Like the settings above, this ; the outgoing queue each cycle. Like the settings above, this