Improve prim sending by combining multiple prim updates into a single packet
parent
5ede445bdf
commit
55a69f3f2d
|
@ -62,6 +62,8 @@ namespace OpenSim.Framework
|
||||||
RegionStatus RegionStatus { get; set; }
|
RegionStatus RegionStatus { get; set; }
|
||||||
|
|
||||||
ClientManager ClientManager { get; }
|
ClientManager ClientManager { get; }
|
||||||
|
float TimeDilation { get; }
|
||||||
|
|
||||||
event restart OnRestart;
|
event restart OnRestart;
|
||||||
|
|
||||||
void AddNewClient(IClientAPI client);
|
void AddNewClient(IClientAPI client);
|
||||||
|
|
|
@ -69,10 +69,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private int m_cachedTextureSerial;
|
private int m_cachedTextureSerial;
|
||||||
private Timer m_clientPingTimer;
|
private Timer m_clientPingTimer;
|
||||||
|
|
||||||
private Timer m_terseUpdateTimer;
|
private Timer m_avatarTerseUpdateTimer;
|
||||||
private Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_terseUpdates = new Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
|
private Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
|
||||||
private ushort m_terseTimeDilationLast = 0;
|
private ushort m_terseTimeDilationLast = 0;
|
||||||
|
|
||||||
|
private Timer m_primTerseUpdateTimer;
|
||||||
|
private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
|
||||||
|
private Timer m_primFullUpdateTimer;
|
||||||
|
private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
|
||||||
|
new List<ObjectUpdatePacket.ObjectDataBlock>();
|
||||||
|
|
||||||
private bool m_clientBlocked;
|
private bool m_clientBlocked;
|
||||||
|
|
||||||
private int m_probesWithNoIngressPackets;
|
private int m_probesWithNoIngressPackets;
|
||||||
|
@ -121,8 +127,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
protected string m_activeGroupName = String.Empty;
|
protected string m_activeGroupName = String.Empty;
|
||||||
protected ulong m_activeGroupPowers;
|
protected ulong m_activeGroupPowers;
|
||||||
protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
|
protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
|
||||||
protected int m_terseUpdateRate = 50;
|
protected int m_avatarTerseUpdateRate = 50;
|
||||||
protected int m_terseUpdatesPerPacket = 5;
|
protected int m_avatarTerseUpdatesPerPacket = 5;
|
||||||
|
|
||||||
|
// LL uses these limits, apparently. Compressed terse would be
|
||||||
|
// 23, but we don't have that yet
|
||||||
|
//
|
||||||
|
protected int m_primTerseUpdatesPerPacket = 10;
|
||||||
|
protected int m_primFullUpdatesPerPacket = 14;
|
||||||
|
|
||||||
|
protected int m_primTerseUpdateRate = 10;
|
||||||
|
protected int m_primFullUpdateRate = 14;
|
||||||
|
|
||||||
// LLClientView Only
|
// LLClientView Only
|
||||||
public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
|
public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
|
||||||
|
@ -528,7 +543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Shut down timers
|
// Shut down timers
|
||||||
m_clientPingTimer.Stop();
|
m_clientPingTimer.Stop();
|
||||||
m_terseUpdateTimer.Stop();
|
m_avatarTerseUpdateTimer.Stop();
|
||||||
|
m_primTerseUpdateTimer.Stop();
|
||||||
|
m_primFullUpdateTimer.Stop();
|
||||||
|
|
||||||
// This is just to give the client a reasonable chance of
|
// This is just to give the client a reasonable chance of
|
||||||
// flushing out all it's packets. There should probably
|
// flushing out all it's packets. There should probably
|
||||||
|
@ -609,7 +626,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
// Shut down timers
|
// Shut down timers
|
||||||
m_clientPingTimer.Stop();
|
m_clientPingTimer.Stop();
|
||||||
m_terseUpdateTimer.Stop();
|
m_avatarTerseUpdateTimer.Stop();
|
||||||
|
m_primTerseUpdateTimer.Stop();
|
||||||
|
m_primFullUpdateTimer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Restart()
|
public void Restart()
|
||||||
|
@ -621,9 +640,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_clientPingTimer.Elapsed += CheckClientConnectivity;
|
m_clientPingTimer.Elapsed += CheckClientConnectivity;
|
||||||
m_clientPingTimer.Enabled = true;
|
m_clientPingTimer.Enabled = true;
|
||||||
|
|
||||||
m_terseUpdateTimer = new Timer(m_terseUpdateRate);
|
m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
|
||||||
m_terseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
|
m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
|
||||||
m_terseUpdateTimer.AutoReset = false;
|
m_avatarTerseUpdateTimer.AutoReset = false;
|
||||||
|
|
||||||
|
m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
|
||||||
|
m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
|
||||||
|
m_primTerseUpdateTimer.AutoReset = false;
|
||||||
|
|
||||||
|
m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
|
||||||
|
m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
|
||||||
|
m_primFullUpdateTimer.AutoReset = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Terminate()
|
public void Terminate()
|
||||||
|
@ -845,10 +872,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_clientPingTimer.Elapsed += CheckClientConnectivity;
|
m_clientPingTimer.Elapsed += CheckClientConnectivity;
|
||||||
m_clientPingTimer.Enabled = true;
|
m_clientPingTimer.Enabled = true;
|
||||||
|
|
||||||
m_terseUpdateTimer = new Timer(m_terseUpdateRate);
|
m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
|
||||||
m_terseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
|
m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
|
||||||
m_terseUpdateTimer.AutoReset = false;
|
m_avatarTerseUpdateTimer.AutoReset = false;
|
||||||
|
|
||||||
|
m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
|
||||||
|
m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
|
||||||
|
m_primTerseUpdateTimer.AutoReset = false;
|
||||||
|
|
||||||
|
m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
|
||||||
|
m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
|
||||||
|
m_primFullUpdateTimer.AutoReset = false;
|
||||||
m_scene.AddNewClient(this);
|
m_scene.AddNewClient(this);
|
||||||
|
|
||||||
RefreshGroupMembership();
|
RefreshGroupMembership();
|
||||||
|
@ -2724,20 +2758,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
CreateAvatarImprovedBlock(localID, position, velocity, rotation);
|
CreateAvatarImprovedBlock(localID, position, velocity, rotation);
|
||||||
|
|
||||||
bool sendpacketnow = false;
|
bool sendpacketnow = false;
|
||||||
lock (m_terseUpdates)
|
lock (m_avatarTerseUpdates)
|
||||||
{
|
{
|
||||||
// Only one update per avatar per packet. No need to send old ones so just overwrite them.
|
// Only one update per avatar per packet. No need to send old ones so just overwrite them.
|
||||||
m_terseUpdates[localID] = terseBlock;
|
m_avatarTerseUpdates[localID] = terseBlock;
|
||||||
m_terseTimeDilationLast = timeDilation;
|
m_terseTimeDilationLast = timeDilation;
|
||||||
|
|
||||||
// If packet is full or own movement packet, send it.
|
// If packet is full or own movement packet, send it.
|
||||||
if (agentid == m_agentId || m_terseUpdates.Count >= m_terseUpdatesPerPacket)
|
if (agentid == m_agentId || m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket)
|
||||||
{
|
{
|
||||||
m_terseUpdateTimer.Stop();
|
m_avatarTerseUpdateTimer.Stop();
|
||||||
sendpacketnow = true;
|
sendpacketnow = true;
|
||||||
}
|
}
|
||||||
else if (m_terseUpdates.Count == 1)
|
else if (m_avatarTerseUpdates.Count == 1)
|
||||||
m_terseUpdateTimer.Start();
|
m_avatarTerseUpdateTimer.Start();
|
||||||
}
|
}
|
||||||
// Call ProcessAvatarTerseUpdates outside the lock
|
// Call ProcessAvatarTerseUpdates outside the lock
|
||||||
if (sendpacketnow)
|
if (sendpacketnow)
|
||||||
|
@ -2746,14 +2780,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e)
|
private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
lock (m_terseUpdates)
|
lock (m_avatarTerseUpdates)
|
||||||
{
|
{
|
||||||
ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
|
ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
|
||||||
terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
|
terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
|
||||||
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[m_terseUpdates.Count];
|
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[m_avatarTerseUpdates.Count];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (KeyValuePair<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> dbe in m_terseUpdates)
|
foreach (KeyValuePair<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> dbe in m_avatarTerseUpdates)
|
||||||
{
|
{
|
||||||
terse.ObjectData[i] = dbe.Value;
|
terse.ObjectData[i] = dbe.Value;
|
||||||
i++;
|
i++;
|
||||||
|
@ -2764,7 +2798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
terse.Header.Zerocoded = true;
|
terse.Header.Zerocoded = true;
|
||||||
OutPacket(terse, ThrottleOutPacketType.Task);
|
OutPacket(terse, ThrottleOutPacketType.Task);
|
||||||
|
|
||||||
m_terseUpdates.Clear();
|
m_avatarTerseUpdates.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2859,81 +2893,124 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
|
if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
|
||||||
rotation = Quaternion.Identity;
|
rotation = Quaternion.Identity;
|
||||||
|
|
||||||
ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
|
ObjectUpdatePacket.ObjectDataBlock objectData =
|
||||||
|
new ObjectUpdatePacket.ObjectDataBlock();
|
||||||
|
|
||||||
|
objectData = CreatePrimUpdateBlock(primShape, flags);
|
||||||
|
|
||||||
|
objectData.ID = localID;
|
||||||
|
objectData.FullID = objectID;
|
||||||
|
objectData.OwnerID = ownerID;
|
||||||
|
|
||||||
// TODO: don't create new blocks if recycling an old packet
|
objectData.Text = LLUtil.StringToPacketBytes(text);
|
||||||
outPacket.RegionData.RegionHandle = regionHandle;
|
objectData.TextColor[0] = color[0];
|
||||||
outPacket.RegionData.TimeDilation = timeDilation;
|
objectData.TextColor[1] = color[1];
|
||||||
outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
|
objectData.TextColor[2] = color[2];
|
||||||
|
objectData.TextColor[3] = color[3];
|
||||||
outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags);
|
objectData.ParentID = parentID;
|
||||||
|
objectData.PSBlock = particleSystem;
|
||||||
outPacket.ObjectData[0].ID = localID;
|
objectData.ClickAction = clickAction;
|
||||||
outPacket.ObjectData[0].FullID = objectID;
|
objectData.Material = material;
|
||||||
outPacket.ObjectData[0].OwnerID = ownerID;
|
objectData.Flags = 0;
|
||||||
|
|
||||||
outPacket.ObjectData[0].Text = LLUtil.StringToPacketBytes(text);
|
|
||||||
outPacket.ObjectData[0].TextColor[0] = color[0];
|
|
||||||
outPacket.ObjectData[0].TextColor[1] = color[1];
|
|
||||||
outPacket.ObjectData[0].TextColor[2] = color[2];
|
|
||||||
outPacket.ObjectData[0].TextColor[3] = color[3];
|
|
||||||
outPacket.ObjectData[0].ParentID = parentID;
|
|
||||||
outPacket.ObjectData[0].PSBlock = particleSystem;
|
|
||||||
outPacket.ObjectData[0].ClickAction = clickAction;
|
|
||||||
outPacket.ObjectData[0].Material = material;
|
|
||||||
outPacket.ObjectData[0].Flags = 0;
|
|
||||||
|
|
||||||
if (attachment)
|
if (attachment)
|
||||||
{
|
{
|
||||||
// Necessary???
|
// Necessary???
|
||||||
outPacket.ObjectData[0].JointAxisOrAnchor = new Vector3(0, 0, 2);
|
objectData.JointAxisOrAnchor = new Vector3(0, 0, 2);
|
||||||
outPacket.ObjectData[0].JointPivot = new Vector3(0, 0, 0);
|
objectData.JointPivot = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
// Item from inventory???
|
// Item from inventory???
|
||||||
outPacket.ObjectData[0].NameValue =
|
objectData.NameValue =
|
||||||
Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid);
|
Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid);
|
||||||
outPacket.ObjectData[0].State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
|
objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Xantor 20080528: Send sound info as well
|
// Xantor 20080528: Send sound info as well
|
||||||
// Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again
|
// Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again
|
||||||
outPacket.ObjectData[0].Sound = SoundId;
|
objectData.Sound = SoundId;
|
||||||
if (SoundId == UUID.Zero)
|
if (SoundId == UUID.Zero)
|
||||||
{
|
{
|
||||||
outPacket.ObjectData[0].OwnerID = UUID.Zero;
|
objectData.OwnerID = UUID.Zero;
|
||||||
outPacket.ObjectData[0].Gain = 0.0f;
|
objectData.Gain = 0.0f;
|
||||||
outPacket.ObjectData[0].Radius = 0.0f;
|
objectData.Radius = 0.0f;
|
||||||
outPacket.ObjectData[0].Flags = 0;
|
objectData.Flags = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outPacket.ObjectData[0].OwnerID = ownerID;
|
objectData.OwnerID = ownerID;
|
||||||
outPacket.ObjectData[0].Gain = (float)SoundGain;
|
objectData.Gain = (float)SoundGain;
|
||||||
outPacket.ObjectData[0].Radius = (float)SoundRadius;
|
objectData.Radius = (float)SoundRadius;
|
||||||
outPacket.ObjectData[0].Flags = SoundFlags;
|
objectData.Flags = SoundFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] pb = pos.GetBytes();
|
byte[] pb = pos.GetBytes();
|
||||||
Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length);
|
Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length);
|
||||||
|
|
||||||
byte[] vel = velocity.GetBytes();
|
byte[] vel = velocity.GetBytes();
|
||||||
Array.Copy(vel, 0, outPacket.ObjectData[0].ObjectData, pb.Length, vel.Length);
|
Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
|
||||||
|
|
||||||
byte[] rot = rotation.GetBytes();
|
byte[] rot = rotation.GetBytes();
|
||||||
Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length);
|
Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length);
|
||||||
|
|
||||||
byte[] rvel = rotational_velocity.GetBytes();
|
byte[] rvel = rotational_velocity.GetBytes();
|
||||||
Array.Copy(rvel, 0, outPacket.ObjectData[0].ObjectData, 36 + rot.Length, rvel.Length);
|
Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
|
||||||
|
|
||||||
if (textureanim.Length > 0)
|
if (textureanim.Length > 0)
|
||||||
{
|
{
|
||||||
outPacket.ObjectData[0].TextureAnim = textureanim;
|
objectData.TextureAnim = textureanim;
|
||||||
}
|
}
|
||||||
outPacket.Header.Zerocoded = true;
|
|
||||||
|
|
||||||
|
lock (m_primFullUpdates)
|
||||||
|
{
|
||||||
|
if (m_primFullUpdates.Count == 0)
|
||||||
|
m_primFullUpdateTimer.Start();
|
||||||
|
|
||||||
|
m_primFullUpdates.Add(objectData);
|
||||||
|
|
||||||
|
if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket)
|
||||||
|
ProcessPrimFullUpdates(this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
lock (m_primFullUpdates)
|
||||||
|
{
|
||||||
|
if (m_primFullUpdates.Count == 0)
|
||||||
|
{
|
||||||
|
m_primFullUpdateTimer.Stop();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectUpdatePacket outPacket =
|
||||||
|
(ObjectUpdatePacket)PacketPool.Instance.GetPacket(
|
||||||
|
PacketType.ObjectUpdate);
|
||||||
|
|
||||||
|
outPacket.RegionData.RegionHandle =
|
||||||
|
Scene.RegionInfo.RegionHandle;
|
||||||
|
outPacket.RegionData.TimeDilation =
|
||||||
|
(ushort)(Scene.TimeDilation * ushort.MaxValue);
|
||||||
|
|
||||||
|
int count = m_primFullUpdates.Count;
|
||||||
|
if (count > m_primFullUpdatesPerPacket)
|
||||||
|
count = m_primFullUpdatesPerPacket;
|
||||||
|
|
||||||
|
outPacket.ObjectData =
|
||||||
|
new ObjectUpdatePacket.ObjectDataBlock[count];
|
||||||
|
|
||||||
|
for (int index = 0 ; index < count ; index++)
|
||||||
|
{
|
||||||
|
outPacket.ObjectData[index] = m_primFullUpdates[0];
|
||||||
|
m_primFullUpdates.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
outPacket.Header.Zerocoded = true;
|
||||||
OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
|
OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
|
||||||
|
|
||||||
|
if (m_primFullUpdates.Count == 0)
|
||||||
|
m_primFullUpdateTimer.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2947,15 +3024,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
|
if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
|
||||||
rotation = Quaternion.Identity;
|
rotation = Quaternion.Identity;
|
||||||
ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
|
|
||||||
// TODO: don't create new blocks if recycling an old packet
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData =
|
||||||
terse.RegionData.RegionHandle = regionHandle;
|
CreatePrimImprovedBlock(localID, position, rotation,
|
||||||
terse.RegionData.TimeDilation = timeDilation;
|
velocity, rotationalvelocity, state);
|
||||||
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
|
|
||||||
terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow...
|
lock (m_primTerseUpdates)
|
||||||
terse.Header.Reliable = false;
|
{
|
||||||
terse.Header.Zerocoded = true;
|
if (m_primTerseUpdates.Count == 0)
|
||||||
OutPacket(terse, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
|
m_primTerseUpdateTimer.Start();
|
||||||
|
|
||||||
|
m_primTerseUpdates.Add(objectData);
|
||||||
|
|
||||||
|
if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket)
|
||||||
|
ProcessPrimTerseUpdates(this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
lock (m_primTerseUpdates)
|
||||||
|
{
|
||||||
|
if (m_primTerseUpdates.Count == 0)
|
||||||
|
{
|
||||||
|
m_primTerseUpdateTimer.Stop();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImprovedTerseObjectUpdatePacket outPacket =
|
||||||
|
(ImprovedTerseObjectUpdatePacket)
|
||||||
|
PacketPool.Instance.GetPacket(
|
||||||
|
PacketType.ImprovedTerseObjectUpdate);
|
||||||
|
|
||||||
|
outPacket.RegionData.RegionHandle =
|
||||||
|
Scene.RegionInfo.RegionHandle;
|
||||||
|
outPacket.RegionData.TimeDilation =
|
||||||
|
(ushort)(Scene.TimeDilation * ushort.MaxValue);
|
||||||
|
|
||||||
|
int count = m_primTerseUpdates.Count;
|
||||||
|
if (count > m_primTerseUpdatesPerPacket)
|
||||||
|
count = m_primTerseUpdatesPerPacket;
|
||||||
|
|
||||||
|
outPacket.ObjectData =
|
||||||
|
new ImprovedTerseObjectUpdatePacket.
|
||||||
|
ObjectDataBlock[count];
|
||||||
|
|
||||||
|
for (int index = 0 ; index < count ; index++)
|
||||||
|
{
|
||||||
|
outPacket.ObjectData[index] = m_primTerseUpdates[0];
|
||||||
|
m_primTerseUpdates.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
outPacket.Header.Reliable = false;
|
||||||
|
outPacket.Header.Zerocoded = true;
|
||||||
|
OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
|
||||||
|
|
||||||
|
if (m_primTerseUpdates.Count == 0)
|
||||||
|
m_primTerseUpdateTimer.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
|
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
|
||||||
|
|
|
@ -97,6 +97,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
get { return m_clientManager; }
|
get { return m_clientManager; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float TimeDilation
|
||||||
|
{
|
||||||
|
get { return 1.0f; }
|
||||||
|
}
|
||||||
|
|
||||||
protected ulong m_regionHandle;
|
protected ulong m_regionHandle;
|
||||||
protected string m_regionName;
|
protected string m_regionName;
|
||||||
protected RegionInfo m_regInfo;
|
protected RegionInfo m_regInfo;
|
||||||
|
|
|
@ -745,7 +745,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_pendingObjects != null && m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 60)
|
while (m_pendingObjects != null && m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 120)
|
||||||
{
|
{
|
||||||
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
||||||
|
|
||||||
|
@ -834,7 +834,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
updateCount++;
|
updateCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateCount > 60)
|
if (updateCount > 300)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue