aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs251
-rwxr-xr-xOpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs70
2 files changed, 212 insertions, 109 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e039fbf..f8ff3c4 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -3891,29 +3891,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3891 if (ent == null) 3891 if (ent == null)
3892 return; 3892 return;
3893 3893
3894 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3894 if (ent is ScenePresence)
3895 objupdate.Header.Zerocoded = true;
3896
3897 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
3898 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3899
3900 if(ent is ScenePresence)
3901 { 3895 {
3902 ScenePresence presence = ent as ScenePresence; 3896 ScenePresence presence = ent as ScenePresence;
3903 objupdate.RegionData.RegionHandle = presence.RegionHandle; 3897
3904 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 3898 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3899
3900 //setup header and regioninfo block
3901 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
3902 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
3903 Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15);
3904
3905 buf.Data[17] = 1;
3906 int pos = 18;
3907 CreateAvatarUpdateBlock(presence, buf.Data, ref pos);
3908
3909 buf.DataLength = pos;
3910 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);
3905 } 3911 }
3912
3906 else if(ent is SceneObjectPart) 3913 else if(ent is SceneObjectPart)
3907 { 3914 {
3915 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3916 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
3917 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3918
3908 SceneObjectPart part = ent as SceneObjectPart; 3919 SceneObjectPart part = ent as SceneObjectPart;
3909 objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3920 objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3910 objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent); 3921 objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
3911 }
3912 3922
3913 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3923 OutPacket(objupdate, ThrottleOutPacketType.Task);
3924 }
3914 3925
3915 // We need to record the avatar local id since the root prim of an attachment points to this. 3926 // We need to record the avatar local id since the root prim of an attachment points to this.
3916// m_attachmentsSent.Add(avatar.LocalId); 3927 // m_attachmentsSent.Add(avatar.LocalId);
3917 } 3928 }
3918 3929
3919 public void SendEntityTerseUpdateImmediate(ISceneEntity ent) 3930 public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
@@ -4084,8 +4095,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4084 ResendPrimUpdate(update); 4095 ResendPrimUpdate(update);
4085 } 4096 }
4086 4097
4098 static private readonly byte[] objectUpdateHeader = new byte[] {
4099 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
4100 0, 0, 0, 0, // sequence number
4101 0, // extra
4102 12 // ID (high frequency)
4103 };
4104
4087 static private readonly byte[] terseUpdateHeader = new byte[] { 4105 static private readonly byte[] terseUpdateHeader = new byte[] {
4088 Helpers.MSG_RELIABLE, 4106 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
4089 0, 0, 0, 0, // sequence number 4107 0, 0, 0, 0, // sequence number
4090 0, // extra 4108 0, // extra
4091 15 // ID (high frequency) 4109 15 // ID (high frequency)
@@ -4105,7 +4123,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4105 List<EntityUpdate> objectUpdates = null; 4123 List<EntityUpdate> objectUpdates = null;
4106 // List<EntityUpdate> compressedUpdates = null; 4124 // List<EntityUpdate> compressedUpdates = null;
4107 List<EntityUpdate> terseUpdates = null; 4125 List<EntityUpdate> terseUpdates = null;
4108 List<EntityUpdate> terseAgentUpdates = null;
4109 List<SceneObjectPart> ObjectAnimationUpdates = null; 4126 List<SceneObjectPart> ObjectAnimationUpdates = null;
4110 4127
4111 // Check to see if this is a flush 4128 // Check to see if this is a flush
@@ -4275,7 +4292,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4275 if(ObjectAnimationUpdates == null) 4292 if(ObjectAnimationUpdates == null)
4276 ObjectAnimationUpdates = new List<SceneObjectPart>(); 4293 ObjectAnimationUpdates = new List<SceneObjectPart>();
4277 ObjectAnimationUpdates.Add(sop); 4294 ObjectAnimationUpdates.Add(sop);
4278 maxUpdatesBytes -= 32 * sop.Animations.Count + 16; 4295 maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
4279 } 4296 }
4280 } 4297 }
4281 } 4298 }
@@ -4329,37 +4346,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4329 4346
4330 if ((updateFlags & canNotUseImprovedMask) == 0) 4347 if ((updateFlags & canNotUseImprovedMask) == 0)
4331 { 4348 {
4349 if (terseUpdates == null)
4350 {
4351 terseUpdates = new List<EntityUpdate>();
4352 maxUpdatesBytes -= 18;
4353 }
4354 terseUpdates.Add(update);
4332 4355
4333 if (update.Entity is ScenePresence) 4356 if (update.Entity is ScenePresence)
4334 {
4335 // ALL presence updates go into a special list
4336 if (terseAgentUpdates == null)
4337 {
4338 terseAgentUpdates = new List<EntityUpdate>();
4339 maxUpdatesBytes -= 18;
4340 }
4341 terseAgentUpdates.Add(update);
4342 maxUpdatesBytes -= 63; // no texture entry 4357 maxUpdatesBytes -= 63; // no texture entry
4343 }
4344 else 4358 else
4345 { 4359 {
4346 // Everything else goes here 4360 if ((updateFlags & PrimUpdateFlags.Textures) == 0)
4347 if (terseUpdates == null) 4361 maxUpdatesBytes -= 47;
4348 { 4362 else
4349 terseUpdates = new List<EntityUpdate>(); 4363 maxUpdatesBytes -= 150; // aprox
4350 maxUpdatesBytes -= 18;
4351 }
4352 terseUpdates.Add(update);
4353 maxUpdatesBytes -= 47;
4354 if ((updateFlags & PrimUpdateFlags.Textures) != 0)
4355 maxUpdatesBytes -= 100; // aprox
4356 } 4364 }
4357 } 4365 }
4358 else 4366 else
4359 { 4367 {
4360 ObjectUpdatePacket.ObjectDataBlock ablock; 4368 ObjectUpdatePacket.ObjectDataBlock ablock;
4361 if (update.Entity is ScenePresence) 4369 if (update.Entity is ScenePresence)
4370 {
4362 ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); 4371 ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
4372 }
4363 else 4373 else
4364 ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); 4374 ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp);
4365 if(objectUpdateBlocks == null) 4375 if(objectUpdateBlocks == null)
@@ -4385,57 +4395,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4385 4395
4386 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4396 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4387 4397
4388 if (terseAgentUpdates != null)
4389 {
4390 const int maxNBlocks = (LLUDPServer.MTU - 18) / 63; // no texture entry
4391 int blocks = terseAgentUpdates.Count;
4392 int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks;
4393 List<EntityUpdate> tau = new List<EntityUpdate>(curNBlocks);
4394
4395 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4396
4397 //setup header and regioninfo block
4398 Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
4399 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
4400 Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
4401 buf.Data[17] = (byte)curNBlocks;
4402 int pos = 18;
4403
4404 int count = 0;
4405 foreach (EntityUpdate eu in terseAgentUpdates)
4406 {
4407 CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, false);
4408 tau.Add(eu);
4409 ++count;
4410 --blocks;
4411 if (count == curNBlocks && blocks > 0)
4412 {
4413 // we need more packets
4414 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4415 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
4416
4417 buf.DataLength = pos;
4418 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown,
4419 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
4420
4421 curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks;
4422 tau = new List<EntityUpdate>(curNBlocks);
4423 count = 0;
4424
4425 buf = newbuf;
4426 buf.Data[17] = (byte)curNBlocks;
4427 pos = 18;
4428 }
4429 }
4430
4431 if (count > 0)
4432 {
4433 buf.DataLength = pos;
4434 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown,
4435 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false);
4436 }
4437 }
4438
4439 if (objectUpdateBlocks != null) 4398 if (objectUpdateBlocks != null)
4440 { 4399 {
4441 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4400 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
@@ -4497,8 +4456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4497 4456
4498 buf.Data[17] = (byte)count; 4457 buf.Data[17] = (byte)count;
4499 buf.DataLength = lastpos; 4458 buf.DataLength = lastpos;
4459 // zero encode is not as spec
4500 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 4460 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4501 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); 4461 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4502 4462
4503 tau = new List<EntityUpdate>(30); 4463 tau = new List<EntityUpdate>(30);
4504 tau.Add(eu); 4464 tau.Add(eu);
@@ -4513,7 +4473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4513 buf.Data[17] = (byte)count; 4473 buf.Data[17] = (byte)count;
4514 buf.DataLength = pos; 4474 buf.DataLength = pos;
4515 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 4475 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4516 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); 4476 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4517 } 4477 }
4518 } 4478 }
4519 4479
@@ -4534,13 +4494,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 UUID[] ids = null; 4494 UUID[] ids = null;
4535 int[] seqs = null; 4495 int[] seqs = null;
4536 int count = sop.GetAnimations(out ids, out seqs); 4496 int count = sop.GetAnimations(out ids, out seqs);
4537 if(count < 0)
4538 continue;
4539 4497
4540 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); 4498 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
4541 ani.Sender = new ObjectAnimationPacket.SenderBlock(); 4499 ani.Sender = new ObjectAnimationPacket.SenderBlock();
4542 ani.Sender.ID = sop.UUID; 4500 ani.Sender.ID = sop.UUID;
4543 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; 4501 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
4544 4502
4545 for(int i = 0; i< count; i++) 4503 for(int i = 0; i< count; i++)
4546 { 4504 {
@@ -5732,7 +5690,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5732 return block; 5690 return block;
5733 } 5691 }
5734 5692
5735
5736 protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture) 5693 protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
5737 { 5694 {
5738 #region ScenePresence/SOP Handling 5695 #region ScenePresence/SOP Handling
@@ -5871,7 +5828,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5871 5828
5872 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5829 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5873 { 5830 {
5874 Vector3 offsetPosition = data.OffsetPosition;
5875 Quaternion rotation = data.Rotation; 5831 Quaternion rotation = data.Rotation;
5876 // tpvs can only see rotations around Z in some cases 5832 // tpvs can only see rotations around Z in some cases
5877 if(!data.Flying && !data.IsSatOnObject) 5833 if(!data.Flying && !data.IsSatOnObject)
@@ -5881,27 +5837,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5881 } 5837 }
5882 rotation.Normalize(); 5838 rotation.Normalize();
5883 5839
5884 uint parentID = data.ParentID;
5885
5886// m_log.DebugFormat( 5840// m_log.DebugFormat(
5887// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 5841// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5888 5842
5889 byte[] objectData = new byte[76]; 5843 byte[] objectData = new byte[76];
5890 5844
5891 Vector3 velocity = new Vector3(0, 0, 0); 5845 //Vector3 velocity = Vector3.Zero;
5892 Vector3 acceleration = new Vector3(0, 0, 0); 5846 Vector3 acceleration = Vector3.Zero;
5847 Vector3 angularvelocity = Vector3.Zero;
5893 5848
5894 data.CollisionPlane.ToBytes(objectData, 0); 5849 data.CollisionPlane.ToBytes(objectData, 0);
5895 offsetPosition.ToBytes(objectData, 16); 5850 data.OffsetPosition.ToBytes(objectData, 16);
5896 velocity.ToBytes(objectData, 28); 5851 data.Velocity.ToBytes(objectData, 28);
5897 acceleration.ToBytes(objectData, 40); 5852 acceleration.ToBytes(objectData, 40);
5898 rotation.ToBytes(objectData, 52); 5853 rotation.ToBytes(objectData, 52);
5899 data.AngularVelocity.ToBytes(objectData, 64); 5854 angularvelocity.ToBytes(objectData, 64);
5900 5855
5901 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5856 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5902 5857
5903 update.Data = Utils.EmptyBytes; 5858 update.Data = Utils.EmptyBytes;
5904 update.ExtraParams = new byte[1]; 5859 update.ExtraParams = Utils.EmptyBytes;
5905 update.FullID = data.UUID; 5860 update.FullID = data.UUID;
5906 update.ID = data.LocalId; 5861 update.ID = data.LocalId;
5907 update.Material = (byte)Material.Flesh; 5862 update.Material = (byte)Material.Flesh;
@@ -5938,7 +5893,99 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5938 return update; 5893 return update;
5939 } 5894 }
5940 5895
5941// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) 5896 protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
5897 {
5898 Quaternion rotation = data.Rotation;
5899 // tpvs can only see rotations around Z in some cases
5900 if (!data.Flying && !data.IsSatOnObject)
5901 {
5902 rotation.X = 0f;
5903 rotation.Y = 0f;
5904 }
5905 rotation.Normalize();
5906
5907 //Vector3 velocity = Vector3.Zero;
5908 //Vector3 acceleration = Vector3.Zero;
5909 //Vector3 angularvelocity = Vector3.Zero;
5910
5911 Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
5912 dest[pos++] = 0; // state
5913 data.UUID.ToBytes(dest, pos); pos += 16;
5914 Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
5915 dest[pos++] = (byte)PCode.Avatar;
5916 dest[pos++] = (byte)Material.Flesh;
5917 dest[pos++] = 0; // clickaction
5918 data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
5919
5920 // objectdata block
5921 dest[pos++] = 76;
5922 data.CollisionPlane.ToBytes(dest, pos); pos += 16;
5923 data.OffsetPosition.ToBytes(dest, pos); pos += 12;
5924 data.Velocity.ToBytes(dest, pos); pos += 12;
5925
5926 //acceleration.ToBytes(dest, pos); pos += 12;
5927 Array.Clear(dest, pos, 12); pos += 12;
5928
5929 rotation.ToBytes(dest, pos); pos += 12;
5930
5931 //angularvelocity.ToBytes(dest, pos); pos += 12;
5932 Array.Clear(dest, pos, 12); pos += 12;
5933
5934 SceneObjectPart parentPart = data.ParentPart;
5935 if (parentPart != null)
5936 {
5937 Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
5938 pos += 4;
5939 }
5940 else
5941 {
5942// Utils.UIntToBytesSafepos(0, dest, pos);
5943// pos += 4;
5944 dest[pos++] = 0;
5945 dest[pos++] = 0;
5946 dest[pos++] = 0;
5947 dest[pos++] = 0;
5948 }
5949
5950 //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
5951 dest[pos++] = 0;
5952 dest[pos++] = 0;
5953 dest[pos++] = 0;
5954 dest[pos++] = 0;
5955
5956 //pbs
5957 dest[pos++] = 16;
5958 dest[pos++] = 1;
5959 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
5960 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
5961 dest[pos++] = 0;
5962 dest[pos++] = 0;
5963 dest[pos++] = 0;
5964 dest[pos++] = 0;
5965
5966 dest[pos++] = 100;
5967 dest[pos++] = 100;
5968
5969 // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
5970 const int pbszeros = 15 + 2 + 1;
5971 Array.Clear(dest, pos, pbszeros); pos += pbszeros;
5972
5973 //NameValue
5974 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5975 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5976 int len = nv.Length;
5977 dest[pos++] = (byte)len;
5978 dest[pos++] = (byte)(len >> 8);
5979 Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
5980
5981 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
5982 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
5983 // jointtype(1) joint pivot(12) joint offset(12)
5984 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
5985 Array.Clear(dest, pos, lastzeros); pos += lastzeros;
5986 }
5987
5988 // protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
5942 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) 5989 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
5943 { 5990 {
5944 byte[] objectData = new byte[60]; 5991 byte[] objectData = new byte[60];
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 653f648..6fd782a 100755
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -274,10 +274,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
274 /// <summary>The measured resolution of Environment.TickCount</summary> 274 /// <summary>The measured resolution of Environment.TickCount</summary>
275 public readonly float TickCountResolution; 275 public readonly float TickCountResolution;
276 276
277 /// <summary>Number of prim updates to put on the queue each time the
278 /// OnQueueEmpty event is triggered for updates</summary>
279 public readonly int PrimUpdatesPerCallback;
280
281 /// <summary>Number of texture packets to put on the queue each time the 277 /// <summary>Number of texture packets to put on the queue each time the
282 /// OnQueueEmpty event is triggered for textures</summary> 278 /// OnQueueEmpty event is triggered for textures</summary>
283 public readonly int TextureSendLimit; 279 public readonly int TextureSendLimit;
@@ -440,7 +436,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
440 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 436 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
441 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 437 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
442 438
443 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
444 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 439 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
445 440
446 m_defaultRTO = config.GetInt("DefaultRTO", 0); 441 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -451,7 +446,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 } 446 }
452 else 447 else
453 { 448 {
454 PrimUpdatesPerCallback = 100;
455 TextureSendLimit = 20; 449 TextureSendLimit = 20;
456 m_ackTimeout = 1000 * 60; // 1 minute 450 m_ackTimeout = 1000 * 60; // 1 minute
457 m_pausedAckTimeout = 1000 * 300; // 5 minutes 451 m_pausedAckTimeout = 1000 * 300; // 5 minutes
@@ -934,11 +928,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP
934 #endregion Queue or Send 928 #endregion Queue or Send
935 } 929 }
936 930
931 public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input)
932 {
933 UDPPacketBuffer zb = GetNewUDPBuffer(null);
934 int srclen = input.DataLength;
935 byte[] src = input.Data;
936 byte[] dest = zb.Data;
937
938 int zerolen = 6;
939 byte zerocount = 0;
940
941 for (int i = zerolen; i < srclen; i++)
942 {
943 if (src[i] == 0x00)
944 {
945 zerocount++;
946 if (zerocount == 0)
947 {
948 dest[zerolen++] = 0x00;
949 dest[zerolen++] = 0xff;
950 zerocount++;
951 }
952 }
953 else
954 {
955 if (zerocount != 0)
956 {
957 dest[zerolen++] = 0x00;
958 dest[zerolen++] = zerocount;
959 zerocount = 0;
960 }
961
962 dest[zerolen++] = src[i];
963 }
964 }
965
966 if (zerocount != 0)
967 {
968 dest[zerolen++] = 0x00;
969 dest[zerolen++] = zerocount;
970 }
971
972 if(zerolen >= srclen)
973 {
974 FreeUDPBuffer(zb);
975
976 src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED);
977 return input;
978 }
979
980 Buffer.BlockCopy(src, 0, dest, 0, 6);
981
982 zb.RemoteEndPoint = input.RemoteEndPoint;
983 zb.DataLength = zerolen;
984
985 FreeUDPBuffer(input);
986
987 return zb;
988 }
989
937 public void SendUDPPacket( 990 public void SendUDPPacket(
938 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue) 991 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
939 { 992 {
940 bool highPriority = false; 993 bool highPriority = false;
941 994
995 if(zerocode)
996 buffer = ZeroEncode(buffer);
997
942 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) 998 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
943 { 999 {
944 category = (ThrottleOutPacketType)((int)category & 127); 1000 category = (ThrottleOutPacketType)((int)category & 127);