llupd direct encode object updates for agents; let terse updates be zeroencoded. This is not as spec but does work
parent
b5ad1b7dcc
commit
0944a96517
|
@ -3891,26 +3891,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (ent == null)
|
if (ent == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
|
|
||||||
objupdate.Header.Zerocoded = true;
|
|
||||||
|
|
||||||
objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
|
||||||
objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
|
|
||||||
|
|
||||||
if (ent is ScenePresence)
|
if (ent is ScenePresence)
|
||||||
{
|
{
|
||||||
ScenePresence presence = ent as ScenePresence;
|
ScenePresence presence = ent as ScenePresence;
|
||||||
objupdate.RegionData.RegionHandle = presence.RegionHandle;
|
|
||||||
objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
|
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
|
||||||
|
|
||||||
|
//setup header and regioninfo block
|
||||||
|
Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
|
||||||
|
Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
|
||||||
|
Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15);
|
||||||
|
|
||||||
|
buf.Data[17] = 1;
|
||||||
|
int pos = 18;
|
||||||
|
CreateAvatarUpdateBlock(presence, buf.Data, ref pos);
|
||||||
|
|
||||||
|
buf.DataLength = pos;
|
||||||
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(ent is SceneObjectPart)
|
else if(ent is SceneObjectPart)
|
||||||
{
|
{
|
||||||
|
ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
|
||||||
|
objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
||||||
|
objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
|
||||||
|
|
||||||
SceneObjectPart part = ent as SceneObjectPart;
|
SceneObjectPart part = ent as SceneObjectPart;
|
||||||
objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||||
objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
|
objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
|
||||||
}
|
|
||||||
|
|
||||||
OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
|
OutPacket(objupdate, ThrottleOutPacketType.Task);
|
||||||
|
}
|
||||||
|
|
||||||
// We need to record the avatar local id since the root prim of an attachment points to this.
|
// We need to record the avatar local id since the root prim of an attachment points to this.
|
||||||
// m_attachmentsSent.Add(avatar.LocalId);
|
// m_attachmentsSent.Add(avatar.LocalId);
|
||||||
|
@ -4084,8 +4095,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
ResendPrimUpdate(update);
|
ResendPrimUpdate(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static private readonly byte[] objectUpdateHeader = new byte[] {
|
||||||
|
Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
|
||||||
|
0, 0, 0, 0, // sequence number
|
||||||
|
0, // extra
|
||||||
|
12 // ID (high frequency)
|
||||||
|
};
|
||||||
|
|
||||||
static private readonly byte[] terseUpdateHeader = new byte[] {
|
static private readonly byte[] terseUpdateHeader = new byte[] {
|
||||||
Helpers.MSG_RELIABLE,
|
Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
|
||||||
0, 0, 0, 0, // sequence number
|
0, 0, 0, 0, // sequence number
|
||||||
0, // extra
|
0, // extra
|
||||||
15 // ID (high frequency)
|
15 // ID (high frequency)
|
||||||
|
@ -4105,7 +4123,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
List<EntityUpdate> objectUpdates = null;
|
List<EntityUpdate> objectUpdates = null;
|
||||||
// List<EntityUpdate> compressedUpdates = null;
|
// List<EntityUpdate> compressedUpdates = null;
|
||||||
List<EntityUpdate> terseUpdates = null;
|
List<EntityUpdate> terseUpdates = null;
|
||||||
List<EntityUpdate> terseAgentUpdates = null;
|
|
||||||
List<SceneObjectPart> ObjectAnimationUpdates = null;
|
List<SceneObjectPart> ObjectAnimationUpdates = null;
|
||||||
|
|
||||||
// Check to see if this is a flush
|
// Check to see if this is a flush
|
||||||
|
@ -4275,7 +4292,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if(ObjectAnimationUpdates == null)
|
if(ObjectAnimationUpdates == null)
|
||||||
ObjectAnimationUpdates = new List<SceneObjectPart>();
|
ObjectAnimationUpdates = new List<SceneObjectPart>();
|
||||||
ObjectAnimationUpdates.Add(sop);
|
ObjectAnimationUpdates.Add(sop);
|
||||||
maxUpdatesBytes -= 32 * sop.Animations.Count + 16;
|
maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4329,37 +4346,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if ((updateFlags & canNotUseImprovedMask) == 0)
|
if ((updateFlags & canNotUseImprovedMask) == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (update.Entity is ScenePresence)
|
|
||||||
{
|
|
||||||
// ALL presence updates go into a special list
|
|
||||||
if (terseAgentUpdates == null)
|
|
||||||
{
|
|
||||||
terseAgentUpdates = new List<EntityUpdate>();
|
|
||||||
maxUpdatesBytes -= 18;
|
|
||||||
}
|
|
||||||
terseAgentUpdates.Add(update);
|
|
||||||
maxUpdatesBytes -= 63; // no texture entry
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Everything else goes here
|
|
||||||
if (terseUpdates == null)
|
if (terseUpdates == null)
|
||||||
{
|
{
|
||||||
terseUpdates = new List<EntityUpdate>();
|
terseUpdates = new List<EntityUpdate>();
|
||||||
maxUpdatesBytes -= 18;
|
maxUpdatesBytes -= 18;
|
||||||
}
|
}
|
||||||
terseUpdates.Add(update);
|
terseUpdates.Add(update);
|
||||||
|
|
||||||
|
if (update.Entity is ScenePresence)
|
||||||
|
maxUpdatesBytes -= 63; // no texture entry
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((updateFlags & PrimUpdateFlags.Textures) == 0)
|
||||||
maxUpdatesBytes -= 47;
|
maxUpdatesBytes -= 47;
|
||||||
if ((updateFlags & PrimUpdateFlags.Textures) != 0)
|
else
|
||||||
maxUpdatesBytes -= 100; // aprox
|
maxUpdatesBytes -= 150; // aprox
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ObjectUpdatePacket.ObjectDataBlock ablock;
|
ObjectUpdatePacket.ObjectDataBlock ablock;
|
||||||
if (update.Entity is ScenePresence)
|
if (update.Entity is ScenePresence)
|
||||||
|
{
|
||||||
ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
|
ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp);
|
ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp);
|
||||||
if(objectUpdateBlocks == null)
|
if(objectUpdateBlocks == null)
|
||||||
|
@ -4385,57 +4395,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
||||||
|
|
||||||
if (terseAgentUpdates != null)
|
|
||||||
{
|
|
||||||
const int maxNBlocks = (LLUDPServer.MTU - 18) / 63; // no texture entry
|
|
||||||
int blocks = terseAgentUpdates.Count;
|
|
||||||
int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks;
|
|
||||||
List<EntityUpdate> tau = new List<EntityUpdate>(curNBlocks);
|
|
||||||
|
|
||||||
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
|
|
||||||
|
|
||||||
//setup header and regioninfo block
|
|
||||||
Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
|
|
||||||
Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
|
|
||||||
Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
|
|
||||||
buf.Data[17] = (byte)curNBlocks;
|
|
||||||
int pos = 18;
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
foreach (EntityUpdate eu in terseAgentUpdates)
|
|
||||||
{
|
|
||||||
CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, false);
|
|
||||||
tau.Add(eu);
|
|
||||||
++count;
|
|
||||||
--blocks;
|
|
||||||
if (count == curNBlocks && blocks > 0)
|
|
||||||
{
|
|
||||||
// we need more packets
|
|
||||||
UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
|
|
||||||
Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
|
|
||||||
|
|
||||||
buf.DataLength = pos;
|
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown,
|
|
||||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
|
|
||||||
|
|
||||||
curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks;
|
|
||||||
tau = new List<EntityUpdate>(curNBlocks);
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
buf = newbuf;
|
|
||||||
buf.Data[17] = (byte)curNBlocks;
|
|
||||||
pos = 18;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
buf.DataLength = pos;
|
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown,
|
|
||||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objectUpdateBlocks != null)
|
if (objectUpdateBlocks != null)
|
||||||
{
|
{
|
||||||
ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
|
ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
|
||||||
|
@ -4497,8 +4456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
buf.Data[17] = (byte)count;
|
buf.Data[17] = (byte)count;
|
||||||
buf.DataLength = lastpos;
|
buf.DataLength = lastpos;
|
||||||
|
// zero encode is not as spec
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
|
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
|
||||||
|
|
||||||
tau = new List<EntityUpdate>(30);
|
tau = new List<EntityUpdate>(30);
|
||||||
tau.Add(eu);
|
tau.Add(eu);
|
||||||
|
@ -4513,7 +4473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
buf.Data[17] = (byte)count;
|
buf.Data[17] = (byte)count;
|
||||||
buf.DataLength = pos;
|
buf.DataLength = pos;
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
|
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4534,13 +4494,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
UUID[] ids = null;
|
UUID[] ids = null;
|
||||||
int[] seqs = null;
|
int[] seqs = null;
|
||||||
int count = sop.GetAnimations(out ids, out seqs);
|
int count = sop.GetAnimations(out ids, out seqs);
|
||||||
if(count < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
|
ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
|
||||||
ani.Sender = new ObjectAnimationPacket.SenderBlock();
|
ani.Sender = new ObjectAnimationPacket.SenderBlock();
|
||||||
ani.Sender.ID = sop.UUID;
|
ani.Sender.ID = sop.UUID;
|
||||||
ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count];
|
ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
|
||||||
|
|
||||||
for(int i = 0; i< count; i++)
|
for(int i = 0; i< count; i++)
|
||||||
{
|
{
|
||||||
|
@ -5732,7 +5690,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
|
protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
|
||||||
{
|
{
|
||||||
#region ScenePresence/SOP Handling
|
#region ScenePresence/SOP Handling
|
||||||
|
@ -5871,7 +5828,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
|
protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
|
||||||
{
|
{
|
||||||
Vector3 offsetPosition = data.OffsetPosition;
|
|
||||||
Quaternion rotation = data.Rotation;
|
Quaternion rotation = data.Rotation;
|
||||||
// tpvs can only see rotations around Z in some cases
|
// tpvs can only see rotations around Z in some cases
|
||||||
if(!data.Flying && !data.IsSatOnObject)
|
if(!data.Flying && !data.IsSatOnObject)
|
||||||
|
@ -5881,27 +5837,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
rotation.Normalize();
|
rotation.Normalize();
|
||||||
|
|
||||||
uint parentID = data.ParentID;
|
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
|
// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
|
||||||
|
|
||||||
byte[] objectData = new byte[76];
|
byte[] objectData = new byte[76];
|
||||||
|
|
||||||
Vector3 velocity = new Vector3(0, 0, 0);
|
//Vector3 velocity = Vector3.Zero;
|
||||||
Vector3 acceleration = new Vector3(0, 0, 0);
|
Vector3 acceleration = Vector3.Zero;
|
||||||
|
Vector3 angularvelocity = Vector3.Zero;
|
||||||
|
|
||||||
data.CollisionPlane.ToBytes(objectData, 0);
|
data.CollisionPlane.ToBytes(objectData, 0);
|
||||||
offsetPosition.ToBytes(objectData, 16);
|
data.OffsetPosition.ToBytes(objectData, 16);
|
||||||
velocity.ToBytes(objectData, 28);
|
data.Velocity.ToBytes(objectData, 28);
|
||||||
acceleration.ToBytes(objectData, 40);
|
acceleration.ToBytes(objectData, 40);
|
||||||
rotation.ToBytes(objectData, 52);
|
rotation.ToBytes(objectData, 52);
|
||||||
data.AngularVelocity.ToBytes(objectData, 64);
|
angularvelocity.ToBytes(objectData, 64);
|
||||||
|
|
||||||
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
|
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
|
||||||
|
|
||||||
update.Data = Utils.EmptyBytes;
|
update.Data = Utils.EmptyBytes;
|
||||||
update.ExtraParams = new byte[1];
|
update.ExtraParams = Utils.EmptyBytes;
|
||||||
update.FullID = data.UUID;
|
update.FullID = data.UUID;
|
||||||
update.ID = data.LocalId;
|
update.ID = data.LocalId;
|
||||||
update.Material = (byte)Material.Flesh;
|
update.Material = (byte)Material.Flesh;
|
||||||
|
@ -5938,6 +5893,98 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
|
||||||
|
{
|
||||||
|
Quaternion rotation = data.Rotation;
|
||||||
|
// tpvs can only see rotations around Z in some cases
|
||||||
|
if (!data.Flying && !data.IsSatOnObject)
|
||||||
|
{
|
||||||
|
rotation.X = 0f;
|
||||||
|
rotation.Y = 0f;
|
||||||
|
}
|
||||||
|
rotation.Normalize();
|
||||||
|
|
||||||
|
//Vector3 velocity = Vector3.Zero;
|
||||||
|
//Vector3 acceleration = Vector3.Zero;
|
||||||
|
//Vector3 angularvelocity = Vector3.Zero;
|
||||||
|
|
||||||
|
Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
|
||||||
|
dest[pos++] = 0; // state
|
||||||
|
data.UUID.ToBytes(dest, pos); pos += 16;
|
||||||
|
Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
|
||||||
|
dest[pos++] = (byte)PCode.Avatar;
|
||||||
|
dest[pos++] = (byte)Material.Flesh;
|
||||||
|
dest[pos++] = 0; // clickaction
|
||||||
|
data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
|
||||||
|
|
||||||
|
// objectdata block
|
||||||
|
dest[pos++] = 76;
|
||||||
|
data.CollisionPlane.ToBytes(dest, pos); pos += 16;
|
||||||
|
data.OffsetPosition.ToBytes(dest, pos); pos += 12;
|
||||||
|
data.Velocity.ToBytes(dest, pos); pos += 12;
|
||||||
|
|
||||||
|
//acceleration.ToBytes(dest, pos); pos += 12;
|
||||||
|
Array.Clear(dest, pos, 12); pos += 12;
|
||||||
|
|
||||||
|
rotation.ToBytes(dest, pos); pos += 12;
|
||||||
|
|
||||||
|
//angularvelocity.ToBytes(dest, pos); pos += 12;
|
||||||
|
Array.Clear(dest, pos, 12); pos += 12;
|
||||||
|
|
||||||
|
SceneObjectPart parentPart = data.ParentPart;
|
||||||
|
if (parentPart != null)
|
||||||
|
{
|
||||||
|
Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Utils.UIntToBytesSafepos(0, dest, pos);
|
||||||
|
// pos += 4;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
|
||||||
|
//pbs
|
||||||
|
dest[pos++] = 16;
|
||||||
|
dest[pos++] = 1;
|
||||||
|
//Utils.UInt16ToBytes(0, dest, pos); pos += 2;
|
||||||
|
//Utils.UInt16ToBytes(0, dest, pos); pos += 2;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
dest[pos++] = 0;
|
||||||
|
|
||||||
|
dest[pos++] = 100;
|
||||||
|
dest[pos++] = 100;
|
||||||
|
|
||||||
|
// rest of pbs is 0 (15), texture entry (2) and texture anim (1)
|
||||||
|
const int pbszeros = 15 + 2 + 1;
|
||||||
|
Array.Clear(dest, pos, pbszeros); pos += pbszeros;
|
||||||
|
|
||||||
|
//NameValue
|
||||||
|
byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
|
||||||
|
data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
|
||||||
|
int len = nv.Length;
|
||||||
|
dest[pos++] = (byte)len;
|
||||||
|
dest[pos++] = (byte)(len >> 8);
|
||||||
|
Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
|
||||||
|
|
||||||
|
// data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
|
||||||
|
// sound id(16), sound owner(16) gain (4), flags (1), radius (4)
|
||||||
|
// jointtype(1) joint pivot(12) joint offset(12)
|
||||||
|
const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
|
||||||
|
Array.Clear(dest, pos, lastzeros); pos += lastzeros;
|
||||||
|
}
|
||||||
|
|
||||||
// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
|
// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
|
||||||
protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
|
protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -274,10 +274,6 @@ 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 prim updates to put on the queue each time the
|
|
||||||
/// OnQueueEmpty event is triggered for updates</summary>
|
|
||||||
public readonly int PrimUpdatesPerCallback;
|
|
||||||
|
|
||||||
/// <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;
|
||||||
|
@ -440,7 +436,6 @@ 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);
|
||||||
|
|
||||||
PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
|
|
||||||
TextureSendLimit = config.GetInt("TextureSendLimit", 20);
|
TextureSendLimit = config.GetInt("TextureSendLimit", 20);
|
||||||
|
|
||||||
m_defaultRTO = config.GetInt("DefaultRTO", 0);
|
m_defaultRTO = config.GetInt("DefaultRTO", 0);
|
||||||
|
@ -451,7 +446,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PrimUpdatesPerCallback = 100;
|
|
||||||
TextureSendLimit = 20;
|
TextureSendLimit = 20;
|
||||||
m_ackTimeout = 1000 * 60; // 1 minute
|
m_ackTimeout = 1000 * 60; // 1 minute
|
||||||
m_pausedAckTimeout = 1000 * 300; // 5 minutes
|
m_pausedAckTimeout = 1000 * 300; // 5 minutes
|
||||||
|
@ -934,11 +928,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
#endregion Queue or Send
|
#endregion Queue or Send
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input)
|
||||||
|
{
|
||||||
|
UDPPacketBuffer zb = GetNewUDPBuffer(null);
|
||||||
|
int srclen = input.DataLength;
|
||||||
|
byte[] src = input.Data;
|
||||||
|
byte[] dest = zb.Data;
|
||||||
|
|
||||||
|
int zerolen = 6;
|
||||||
|
byte zerocount = 0;
|
||||||
|
|
||||||
|
for (int i = zerolen; i < srclen; i++)
|
||||||
|
{
|
||||||
|
if (src[i] == 0x00)
|
||||||
|
{
|
||||||
|
zerocount++;
|
||||||
|
if (zerocount == 0)
|
||||||
|
{
|
||||||
|
dest[zerolen++] = 0x00;
|
||||||
|
dest[zerolen++] = 0xff;
|
||||||
|
zerocount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (zerocount != 0)
|
||||||
|
{
|
||||||
|
dest[zerolen++] = 0x00;
|
||||||
|
dest[zerolen++] = zerocount;
|
||||||
|
zerocount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest[zerolen++] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zerocount != 0)
|
||||||
|
{
|
||||||
|
dest[zerolen++] = 0x00;
|
||||||
|
dest[zerolen++] = zerocount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(zerolen >= srclen)
|
||||||
|
{
|
||||||
|
FreeUDPBuffer(zb);
|
||||||
|
|
||||||
|
src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer.BlockCopy(src, 0, dest, 0, 6);
|
||||||
|
|
||||||
|
zb.RemoteEndPoint = input.RemoteEndPoint;
|
||||||
|
zb.DataLength = zerolen;
|
||||||
|
|
||||||
|
FreeUDPBuffer(input);
|
||||||
|
|
||||||
|
return zb;
|
||||||
|
}
|
||||||
|
|
||||||
public void SendUDPPacket(
|
public void SendUDPPacket(
|
||||||
LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue)
|
LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
|
||||||
{
|
{
|
||||||
bool highPriority = false;
|
bool highPriority = false;
|
||||||
|
|
||||||
|
if(zerocode)
|
||||||
|
buffer = ZeroEncode(buffer);
|
||||||
|
|
||||||
if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
|
if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
|
||||||
{
|
{
|
||||||
category = (ThrottleOutPacketType)((int)category & 127);
|
category = (ThrottleOutPacketType)((int)category & 127);
|
||||||
|
|
|
@ -747,17 +747,6 @@
|
||||||
;texture_default = 18500
|
;texture_default = 18500
|
||||||
;asset_default = 10500
|
;asset_default = 10500
|
||||||
|
|
||||||
; Configures how ObjectUpdates are aggregated. These numbers
|
|
||||||
; do not literally mean how many updates will be put in each
|
|
||||||
; packet that goes over the wire, as packets are
|
|
||||||
; automatically split on a 1400 byte boundary. These control
|
|
||||||
; the balance between responsiveness of interest list updates
|
|
||||||
; and total throughput. Higher numbers will ensure more full-
|
|
||||||
; sized packets and faster sending of data, but more delay in
|
|
||||||
; updating interest lists
|
|
||||||
;
|
|
||||||
;PrimUpdatesPerCallback = 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
|
||||||
; is a balance between responsiveness to priority updates and
|
; is a balance between responsiveness to priority updates and
|
||||||
|
@ -767,16 +756,6 @@
|
||||||
;
|
;
|
||||||
;TextureSendLimit = 20
|
;TextureSendLimit = 20
|
||||||
|
|
||||||
; CannibalizeTextureRate allows bandwidth to be moved from the
|
|
||||||
; UDP texture throttle to the task throttle. Since most viewers
|
|
||||||
; use HTTP textures, this provides a means of using what is largely
|
|
||||||
; unused bandwidth in the total throttle. The value is the proportion
|
|
||||||
; of the texture rate to move to the task queue. It must be between
|
|
||||||
; 0.0 (none of the bandwidth is cannibalized) and 0.9 (90% of the
|
|
||||||
; bandwidth is grabbed)
|
|
||||||
;
|
|
||||||
; CannibalizeTextureRate = 0.5
|
|
||||||
|
|
||||||
; Quash and remove any light properties from attachments not on the
|
; Quash and remove any light properties from attachments not on the
|
||||||
; hands. This allows flashlights and lanterns to function, but kills
|
; hands. This allows flashlights and lanterns to function, but kills
|
||||||
; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps
|
; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps
|
||||||
|
|
Loading…
Reference in New Issue