aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
diff options
context:
space:
mode:
authorroot2019-03-11 23:41:26 +0000
committerroot2019-03-11 23:41:26 +0000
commitc7a02dc058018429fca8fb0c979785be34bebaf6 (patch)
treea364249657222c201c9880ec355dafbcb7f99d9a /OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
parentShould have been in the last commit (diff)
parenterrr use invariantculture compare not current (diff)
downloadopensim-SC-c7a02dc058018429fca8fb0c979785be34bebaf6.zip
opensim-SC-c7a02dc058018429fca8fb0c979785be34bebaf6.tar.gz
opensim-SC-c7a02dc058018429fca8fb0c979785be34bebaf6.tar.bz2
opensim-SC-c7a02dc058018429fca8fb0c979785be34bebaf6.tar.xz
Merge branch 'master' of brain.opensimulator.org:/var/git/opensim
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1158
1 files changed, 996 insertions, 162 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index b7d5a80..ac041f5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -1257,6 +1257,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1); 1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1);
1258 } 1258 }
1259 1259
1260 static private readonly byte[] TerrainPacketHeader = new byte[] {
1261 Helpers.MSG_RELIABLE, // zero code is not as spec
1262 0, 0, 0, 0, // sequence number
1263 0, // extra
1264 11, // ID (high frequency)
1265 };
1266
1267 private const int END_OF_PATCHES = 97;
1268 private const int STRIDE = 264;
1269
1260 public void SendLayerData(int[] map) 1270 public void SendLayerData(int[] map)
1261 { 1271 {
1262 if(map == null) 1272 if(map == null)
@@ -1264,9 +1274,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1264 1274
1265 try 1275 try
1266 { 1276 {
1267 List<LayerDataPacket> packets = OpenSimTerrainCompressor.CreateLayerDataPackets(m_scene.Heightmap.GetTerrainData(), map); 1277 TerrainData terrData = m_scene.Heightmap.GetTerrainData();
1268 foreach (LayerDataPacket pkt in packets) 1278 byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ?
1269 OutPacket(pkt, ThrottleOutPacketType.Land); 1279 (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land;
1280
1281 int numberPatchs = map.Length / 2;
1282
1283 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1284 byte[] data = buf.Data;
1285
1286 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1287
1288 data[7] = landPacketType;
1289 //data[8] and data[9] == datablock size to fill later
1290
1291 data[10] = 0; // BitPack needs this on reused packets
1292
1293 // start data
1294 BitPack bitpack = new BitPack(data, 10);
1295 bitpack.PackBits(STRIDE, 16);
1296 bitpack.PackBitsFromByte(16);
1297 bitpack.PackBitsFromByte(landPacketType);
1298
1299 int s;
1300 int datasize = 0;
1301 for (int i = 0; i < numberPatchs; i++)
1302 {
1303 s = 2 * i;
1304 OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
1305 if (bitpack.BytePos > 950 && i != numberPatchs - 1)
1306 {
1307 //finish this packet
1308 bitpack.PackBitsFromByte(END_OF_PATCHES);
1309
1310 // fix the datablock lenght
1311 datasize = bitpack.BytePos - 9;
1312 data[8] = (byte)datasize;
1313 data[9] = (byte)(datasize >> 8);
1314
1315 buf.DataLength = bitpack.BytePos + 1;
1316 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1317
1318 // start another
1319 buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1320 data = buf.Data;
1321
1322 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1323
1324 data[7] = landPacketType;
1325 //data[8] and data[9] == datablock size to fill later
1326
1327 data[10] = 0; // BitPack needs this
1328 // start data
1329 bitpack = new BitPack(data, 10);
1330
1331 bitpack.PackBits(STRIDE, 16);
1332 bitpack.PackBitsFromByte(16);
1333 bitpack.PackBitsFromByte(landPacketType);
1334 }
1335 }
1336
1337 bitpack.PackBitsFromByte(END_OF_PATCHES);
1338
1339 datasize = bitpack.BytePos - 9;
1340 data[8] = (byte)datasize;
1341 data[9] = (byte)(datasize >> 8);
1342
1343 buf.DataLength = bitpack.BytePos + 1;
1344 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1345
1270 } 1346 }
1271 catch (Exception e) 1347 catch (Exception e)
1272 { 1348 {
@@ -1677,8 +1753,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1677 1753
1678 public void SendKillObject(List<uint> localIDs) 1754 public void SendKillObject(List<uint> localIDs)
1679 { 1755 {
1680 // foreach (uint id in localIDs) 1756 // foreach (uint id in localIDs)
1681 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1757 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1682 1758
1683 // remove pending entities to reduce looping chances. 1759 // remove pending entities to reduce looping chances.
1684 lock (m_entityProps.SyncRoot) 1760 lock (m_entityProps.SyncRoot)
@@ -1702,10 +1778,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1702 1778
1703 if(++nsent >= 200) 1779 if(++nsent >= 200)
1704 { 1780 {
1705 kill.Header.Reliable = true;
1706 kill.Header.Zerocoded = true;
1707 OutPacket(kill, ThrottleOutPacketType.Task); 1781 OutPacket(kill, ThrottleOutPacketType.Task);
1708
1709 perpacket = localIDs.Count - i - 1; 1782 perpacket = localIDs.Count - i - 1;
1710 if(perpacket == 0) 1783 if(perpacket == 0)
1711 break; 1784 break;
@@ -1720,8 +1793,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1720 1793
1721 if(nsent != 0) 1794 if(nsent != 0)
1722 { 1795 {
1723 kill.Header.Reliable = true;
1724 kill.Header.Zerocoded = true;
1725 OutPacket(kill, ThrottleOutPacketType.Task); 1796 OutPacket(kill, ThrottleOutPacketType.Task);
1726 } 1797 }
1727 } 1798 }
@@ -3832,32 +3903,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3832 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3903 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3833 } 3904 }
3834 3905
3906/*
3835 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3907 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3836 { 3908 {
3837// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); 3909// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3838 3910
3839 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); 3911 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
3840 // TODO: don't create new blocks if recycling an old packet 3912 // TODO: don't create new blocks if recycling an old packet
3841 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
3842 ani.Sender = new AvatarAnimationPacket.SenderBlock(); 3913 ani.Sender = new AvatarAnimationPacket.SenderBlock();
3843 ani.Sender.ID = sourceAgentId; 3914 ani.Sender.ID = sourceAgentId;
3844 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; 3915 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
3845 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; 3916 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
3846 3917
3847 for (int i = 0; i < animations.Length; ++i) 3918 //self animations
3919 if (sourceAgentId == AgentId)
3848 { 3920 {
3849 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); 3921 List<int> withobjects = new List<int>(animations.Length);
3850 ani.AnimationList[i].AnimID = animations[i]; 3922 List<int> noobjects = new List<int>(animations.Length);
3851 ani.AnimationList[i].AnimSequenceID = seqs[i]; 3923 for(int i = 0; i < animations.Length; ++i)
3924 {
3925 if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3926 noobjects.Add(i);
3927 else
3928 withobjects.Add(i);
3929 }
3852 3930
3853 ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); 3931 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count];
3854 if (objectIDs[i].Equals(sourceAgentId)) 3932 int k = 0;
3855 ani.AnimationSourceList[i].ObjectID = UUID.Zero; 3933 foreach (int i in withobjects)
3856 else 3934 {
3857 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3935 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3936 ani.AnimationList[k].AnimID = animations[i];
3937 ani.AnimationList[k].AnimSequenceID = seqs[i];
3938 ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock();
3939 ani.AnimationSourceList[k].ObjectID = objectIDs[i];
3940 k++;
3941 }
3942 foreach (int i in noobjects)
3943 {
3944 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3945 ani.AnimationList[k].AnimID = animations[i];
3946 ani.AnimationList[k].AnimSequenceID = seqs[i];
3947 k++;
3948 }
3949 }
3950 else
3951 {
3952 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0];
3953 for (int i = 0; i < animations.Length; ++i)
3954 {
3955 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
3956 ani.AnimationList[i].AnimID = animations[i];
3957 ani.AnimationList[i].AnimSequenceID = seqs[i];
3958 }
3858 } 3959 }
3960
3859 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3961 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3860 } 3962 }
3963*/
3964
3965 static private readonly byte[] AvatarAnimationHeader = new byte[] {
3966 Helpers.MSG_RELIABLE,
3967 0, 0, 0, 0, // sequence number
3968 0, // extra
3969 20 // ID (high frequency)
3970 };
3971
3972 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3973 {
3974 // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3975
3976 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3977 byte[] data = buf.Data;
3978 //setup header
3979 Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7);
3980 //agent block
3981 sourceAgentId.ToBytes(data, 7);
3982
3983 // animations count
3984 data[23] = (byte)animations.Length;
3985
3986 int pos = 24;
3987
3988 //self animations
3989 if (sourceAgentId == AgentId)
3990 {
3991 List<int> withobjects = new List<int>(animations.Length);
3992 List<int> noobjects = new List<int>(animations.Length);
3993 for (int i = 0; i < animations.Length; ++i)
3994 {
3995 if (objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3996 noobjects.Add(i);
3997 else
3998 withobjects.Add(i);
3999 }
4000
4001 // first the ones with corresponding objects
4002 foreach (int i in withobjects)
4003 {
4004 animations[i].ToBytes(data, pos); pos += 16;
4005 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4006 }
4007 // then the rest
4008 foreach (int i in noobjects)
4009 {
4010 animations[i].ToBytes(data, pos); pos += 16;
4011 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4012 }
4013 // object ids block
4014 data[pos++] = (byte)withobjects.Count;
4015 foreach (int i in withobjects)
4016 {
4017 objectIDs[i].ToBytes(data, pos); pos += 16;
4018 }
4019 }
4020 else
4021 {
4022 for(int i = 0; i < animations.Length; ++i)
4023 {
4024 animations[i].ToBytes(data, pos); pos += 16;
4025 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4026 }
4027 data[pos++] = 0; // no object ids
4028 }
4029
4030 data[pos++] = 0; // no physical avatar events
4031
4032 buf.DataLength = pos;
4033 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority,
4034 null, false, false);
4035 }
3861 4036
3862 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) 4037 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId)
3863 { 4038 {
@@ -3889,36 +4064,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3889 /// </summary> 4064 /// </summary>
3890 public void SendEntityFullUpdateImmediate(ISceneEntity ent) 4065 public void SendEntityFullUpdateImmediate(ISceneEntity ent)
3891 { 4066 {
3892// m_log.DebugFormat( 4067 if (ent == null || (!(ent is ScenePresence) && !(ent is SceneObjectPart)))
3893// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}",
3894// avatar.Name, avatar.UUID, Name, AgentId);
3895
3896 if (ent == null)
3897 return; 4068 return;
3898 4069
3899 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4070 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3900 objupdate.Header.Zerocoded = true; 4071 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
3901 4072
3902 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4073 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
3903 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 4074 zc.Position = 7;
3904 4075
3905 if(ent is ScenePresence) 4076 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
3906 { 4077 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
3907 ScenePresence presence = ent as ScenePresence; 4078
3908 objupdate.RegionData.RegionHandle = presence.RegionHandle; 4079 zc.AddByte(1); // block count
3909 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 4080
3910 } 4081 ThrottleOutPacketType ptype = ThrottleOutPacketType.Task;
3911 else if(ent is SceneObjectPart) 4082 if (ent is ScenePresence)
3912 { 4083 {
3913 SceneObjectPart part = ent as SceneObjectPart; 4084 CreateAvatarUpdateBlock(ent as ScenePresence, zc);
3914 objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4085 ptype |= ThrottleOutPacketType.HighPriority;
3915 objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
3916 } 4086 }
4087 else
4088 CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc);
3917 4089
3918 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 4090 buf.DataLength = zc.Finish();
3919 4091 m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false);
3920 // We need to record the avatar local id since the root prim of an attachment points to this.
3921// m_attachmentsSent.Add(avatar.LocalId);
3922 } 4092 }
3923 4093
3924 public void SendEntityTerseUpdateImmediate(ISceneEntity ent) 4094 public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
@@ -4089,6 +4259,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4089 ResendPrimUpdate(update); 4259 ResendPrimUpdate(update);
4090 } 4260 }
4091 4261
4262 static private readonly byte[] objectUpdateHeader = new byte[] {
4263 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
4264 0, 0, 0, 0, // sequence number
4265 0, // extra
4266 12 // ID (high frequency)
4267 };
4268
4269 static private readonly byte[] terseUpdateHeader = new byte[] {
4270 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
4271 0, 0, 0, 0, // sequence number
4272 0, // extra
4273 15 // ID (high frequency)
4274 };
4275
4092 private void ProcessEntityUpdates(int maxUpdatesBytes) 4276 private void ProcessEntityUpdates(int maxUpdatesBytes)
4093 { 4277 {
4094 if (!IsActive) 4278 if (!IsActive)
@@ -4098,14 +4282,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4098 if (mysp == null) 4282 if (mysp == null)
4099 return; 4283 return;
4100 4284
4101 List<ObjectUpdatePacket.ObjectDataBlock> objectUpdateBlocks = null; 4285 // List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4102 List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4103 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseUpdateBlocks = null;
4104 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseAgentUpdateBlocks = null;
4105 List<EntityUpdate> objectUpdates = null; 4286 List<EntityUpdate> objectUpdates = null;
4106 List<EntityUpdate> compressedUpdates = null; 4287 // List<EntityUpdate> compressedUpdates = null;
4107 List<EntityUpdate> terseUpdates = null; 4288 List<EntityUpdate> terseUpdates = null;
4108 List<EntityUpdate> terseAgentUpdates = null;
4109 List<SceneObjectPart> ObjectAnimationUpdates = null; 4289 List<SceneObjectPart> ObjectAnimationUpdates = null;
4110 4290
4111 // Check to see if this is a flush 4291 // Check to see if this is a flush
@@ -4120,10 +4300,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4120 float cullingrange = 64.0f; 4300 float cullingrange = 64.0f;
4121 Vector3 mypos = Vector3.Zero; 4301 Vector3 mypos = Vector3.Zero;
4122 4302
4123 bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; 4303 //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
4304 bool orderedDequeue = false; // temporary off
4124 4305
4125 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); 4306 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
4126 4307
4308
4127 if (doCulling) 4309 if (doCulling)
4128 { 4310 {
4129 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; 4311 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
@@ -4179,7 +4361,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4179 } 4361 }
4180 4362
4181 if (grp.IsAttachment) 4363 if (grp.IsAttachment)
4182 { // Someone else's HUD, why are we getting these? 4364 {
4365 // animated attachments are nasty if not supported by viewer
4366 if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry)
4367 continue;
4368
4369 // Someone else's HUD, why are we getting these?
4183 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint) 4370 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint)
4184 continue; 4371 continue;
4185 4372
@@ -4273,7 +4460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4273 if(ObjectAnimationUpdates == null) 4460 if(ObjectAnimationUpdates == null)
4274 ObjectAnimationUpdates = new List<SceneObjectPart>(); 4461 ObjectAnimationUpdates = new List<SceneObjectPart>();
4275 ObjectAnimationUpdates.Add(sop); 4462 ObjectAnimationUpdates.Add(sop);
4276 maxUpdatesBytes -= 32 * sop.Animations.Count + 16; 4463 maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
4277 } 4464 }
4278 } 4465 }
4279 } 4466 }
@@ -4304,7 +4491,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4304 PrimUpdateFlags.Velocity | 4491 PrimUpdateFlags.Velocity |
4305 PrimUpdateFlags.Acceleration | 4492 PrimUpdateFlags.Acceleration |
4306 PrimUpdateFlags.AngularVelocity | 4493 PrimUpdateFlags.AngularVelocity |
4307 PrimUpdateFlags.CollisionPlane 4494 PrimUpdateFlags.CollisionPlane |
4495 PrimUpdateFlags.Textures
4308 ); 4496 );
4309 4497
4310 #endregion UpdateFlags to packet type conversion 4498 #endregion UpdateFlags to packet type conversion
@@ -4326,48 +4514,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4326 4514
4327 if ((updateFlags & canNotUseImprovedMask) == 0) 4515 if ((updateFlags & canNotUseImprovedMask) == 0)
4328 { 4516 {
4329 ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = 4517 if (terseUpdates == null)
4330 CreateImprovedTerseBlock(update.Entity);
4331
4332 if (update.Entity is ScenePresence)
4333 { 4518 {
4334 // ALL presence updates go into a special list 4519 terseUpdates = new List<EntityUpdate>();
4335 if (terseAgentUpdateBlocks == null) 4520 maxUpdatesBytes -= 18;
4336 {
4337 terseAgentUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4338 terseAgentUpdates = new List<EntityUpdate>();
4339 }
4340 terseAgentUpdateBlocks.Add(ablock);
4341 terseAgentUpdates.Add(update);
4342 } 4521 }
4522 terseUpdates.Add(update);
4523
4524 if (update.Entity is ScenePresence)
4525 maxUpdatesBytes -= 63; // no texture entry
4343 else 4526 else
4344 { 4527 {
4345 // Everything else goes here 4528 if ((updateFlags & PrimUpdateFlags.Textures) == 0)
4346 if (terseUpdateBlocks == null) 4529 maxUpdatesBytes -= 47;
4347 { 4530 else
4348 terseUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 4531 maxUpdatesBytes -= 150; // aprox
4349 terseUpdates = new List<EntityUpdate>();
4350 }
4351 terseUpdateBlocks.Add(ablock);
4352 terseUpdates.Add(update);
4353 } 4532 }
4354 maxUpdatesBytes -= ablock.Length;
4355 } 4533 }
4356 else 4534 else
4357 { 4535 {
4358 ObjectUpdatePacket.ObjectDataBlock ablock;
4359 if (update.Entity is ScenePresence) 4536 if (update.Entity is ScenePresence)
4360 ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); 4537 maxUpdatesBytes -= 150; // crude estimation
4361 else 4538 else
4362 ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); 4539 maxUpdatesBytes -= 300;
4363 if(objectUpdateBlocks == null) 4540
4541 if(objectUpdates == null)
4364 { 4542 {
4365 objectUpdateBlocks = new List<ObjectUpdatePacket.ObjectDataBlock>();
4366 objectUpdates = new List<EntityUpdate>(); 4543 objectUpdates = new List<EntityUpdate>();
4544 maxUpdatesBytes -= 18;
4367 } 4545 }
4368 objectUpdateBlocks.Add(ablock);
4369 objectUpdates.Add(update); 4546 objectUpdates.Add(update);
4370 maxUpdatesBytes -= ablock.Length;
4371 } 4547 }
4372 4548
4373 #endregion Block Construction 4549 #endregion Block Construction
@@ -4382,29 +4558,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4382 4558
4383 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4559 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4384 4560
4385 if (terseAgentUpdateBlocks != null) 4561 if(objectUpdates != null)
4386 { 4562 {
4387 ImprovedTerseObjectUpdatePacket packet 4563 int blocks = objectUpdates.Count;
4388 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4564 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4389 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4390 packet.RegionData.TimeDilation = timeDilation;
4391 packet.ObjectData = terseAgentUpdateBlocks.ToArray();
4392 terseAgentUpdateBlocks.Clear();
4393 4565
4394 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates, oPacket); }); 4566 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4395 } 4567 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
4396 4568
4397 if (objectUpdateBlocks != null) 4569 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
4398 { 4570 zc.Position = 7;
4399 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4571
4400 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4572 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
4401 packet.RegionData.TimeDilation = timeDilation; 4573 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
4402 packet.ObjectData = objectUpdateBlocks.ToArray(); 4574
4403 objectUpdateBlocks.Clear(); 4575 zc.AddByte(1); // tmp block count
4576
4577 int countposition = zc.Position - 1;
4578
4579 int lastpos = 0;
4580 int lastzc = 0;
4581
4582 int count = 0;
4583 foreach (EntityUpdate eu in objectUpdates)
4584 {
4585 lastpos = zc.Position;
4586 lastzc = zc.ZeroCount;
4587 if (eu.Entity is ScenePresence)
4588 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4589 else
4590 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4591 if (zc.Position < LLUDPServer.MAXPAYLOAD)
4592 {
4593 tau.Add(eu);
4594 ++count;
4595 --blocks;
4596 }
4597 else if (blocks > 0)
4598 {
4599 // we need more packets
4600 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4601 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
4404 4602
4405 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); }); 4603 buf.Data[countposition] = (byte)count;
4604 // get pending zeros at cut point
4605 if(lastzc > 0)
4606 {
4607 buf.Data[lastpos++] = 0;
4608 buf.Data[lastpos++] = (byte)lastzc;
4609 }
4610 buf.DataLength = lastpos;
4611
4612 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4613 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4614
4615 buf = newbuf;
4616 zc.Data = buf.Data;
4617 zc.ZeroCount = 0;
4618 zc.Position = countposition + 1;
4619 // im lazy now, just do last again
4620 if (eu.Entity is ScenePresence)
4621 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4622 else
4623 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4624
4625 tau = new List<EntityUpdate>(30);
4626 tau.Add(eu);
4627 count = 1;
4628 --blocks;
4629 }
4630 }
4631
4632 if (count > 0)
4633 {
4634 buf.Data[countposition] = (byte)count;
4635 buf.DataLength = zc.Finish();
4636 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4637 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4638 }
4406 } 4639 }
4407 4640
4641/*
4408 if (compressedUpdateBlocks != null) 4642 if (compressedUpdateBlocks != null)
4409 { 4643 {
4410 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); 4644 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
@@ -4415,20 +4649,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4415 4649
4416 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); 4650 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); });
4417 } 4651 }
4418 4652*/
4419 if (terseUpdateBlocks != null) 4653 if (terseUpdates != null)
4420 { 4654 {
4421 ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 4655 int blocks = terseUpdates.Count;
4422 PacketType.ImprovedTerseObjectUpdate); 4656 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4423 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4657
4424 packet.RegionData.TimeDilation = timeDilation; 4658 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4425 packet.ObjectData = terseUpdateBlocks.ToArray(); 4659
4426 terseUpdateBlocks.Clear(); 4660 //setup header and regioninfo block
4661 Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
4662 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
4663 Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
4664 int pos = 18;
4665 int lastpos = 0;
4427 4666
4428 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates, oPacket); }); 4667 int count = 0;
4668 foreach (EntityUpdate eu in terseUpdates)
4669 {
4670 lastpos = pos;
4671 CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0);
4672 if (pos < LLUDPServer.MAXPAYLOAD)
4673 {
4674 tau.Add(eu);
4675 ++count;
4676 --blocks;
4677 }
4678 else if (blocks > 0)
4679 {
4680 // we need more packets
4681 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4682 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
4683 // copy what we done in excess
4684 int extralen = pos - lastpos;
4685 if(extralen > 0)
4686 Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen);
4687
4688 pos = 18 + extralen;
4689
4690 buf.Data[17] = (byte)count;
4691 buf.DataLength = lastpos;
4692 // zero encode is not as spec
4693 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4694 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4695
4696 tau = new List<EntityUpdate>(30);
4697 tau.Add(eu);
4698 count = 1;
4699 --blocks;
4700 buf = newbuf;
4701 }
4702 }
4703
4704 if (count > 0)
4705 {
4706 buf.Data[17] = (byte)count;
4707 buf.DataLength = pos;
4708 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4709 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4710 }
4429 } 4711 }
4430 4712
4431 if(ObjectAnimationUpdates != null) 4713 if (ObjectAnimationUpdates != null)
4432 { 4714 {
4433 foreach (SceneObjectPart sop in ObjectAnimationUpdates) 4715 foreach (SceneObjectPart sop in ObjectAnimationUpdates)
4434 { 4716 {
@@ -4445,13 +4727,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4445 UUID[] ids = null; 4727 UUID[] ids = null;
4446 int[] seqs = null; 4728 int[] seqs = null;
4447 int count = sop.GetAnimations(out ids, out seqs); 4729 int count = sop.GetAnimations(out ids, out seqs);
4448 if(count < 0)
4449 continue;
4450 4730
4451 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); 4731 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
4452 ani.Sender = new ObjectAnimationPacket.SenderBlock(); 4732 ani.Sender = new ObjectAnimationPacket.SenderBlock();
4453 ani.Sender.ID = sop.UUID; 4733 ani.Sender.ID = sop.UUID;
4454 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; 4734 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
4455 4735
4456 for(int i = 0; i< count; i++) 4736 for(int i = 0; i< count; i++)
4457 { 4737 {
@@ -4642,9 +4922,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4642 // These are used to implement an adaptive backoff in the number 4922 // These are used to implement an adaptive backoff in the number
4643 // of updates converted to packets. Since we don't want packets 4923 // of updates converted to packets. Since we don't want packets
4644 // to sit in the queue with old data, only convert enough updates 4924 // to sit in the queue with old data, only convert enough updates
4645 // to packets that can be sent in 200ms. 4925 // to packets that can be sent in 30ms.
4646// private Int32 m_LastQueueFill = 0;
4647// private Int32 m_maxUpdates = 0;
4648 4926
4649 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4927 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4650 { 4928 {
@@ -5645,9 +5923,144 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5645 return block; 5923 return block;
5646 } 5924 }
5647 5925
5926 protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
5927 {
5928 #region ScenePresence/SOP Handling
5929
5930 bool avatar = (entity is ScenePresence);
5931 uint localID = entity.LocalId;
5932 uint attachPoint;
5933 Vector4 collisionPlane;
5934 Vector3 position, velocity, acceleration, angularVelocity;
5935 Quaternion rotation;
5936 byte datasize;
5937 byte[] te = null;
5938
5939 if (avatar)
5940 {
5941 ScenePresence presence = (ScenePresence)entity;
5942
5943 position = presence.OffsetPosition;
5944 velocity = presence.Velocity;
5945 acceleration = Vector3.Zero;
5946 rotation = presence.Rotation;
5947 // tpvs can only see rotations around Z in some cases
5948 if (!presence.Flying && !presence.IsSatOnObject)
5949 {
5950 rotation.X = 0f;
5951 rotation.Y = 0f;
5952 }
5953 rotation.Normalize();
5954 angularVelocity = presence.AngularVelocity;
5955
5956 // m_log.DebugFormat(
5957 // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5958
5959 attachPoint = presence.State;
5960 collisionPlane = presence.CollisionPlane;
5961
5962 datasize = 60;
5963 }
5964 else
5965 {
5966 SceneObjectPart part = (SceneObjectPart)entity;
5967
5968 attachPoint = part.ParentGroup.AttachmentPoint;
5969 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5970 // m_log.DebugFormat(
5971 // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5972 // attachPoint, part.Name, part.LocalId, Name);
5973
5974 collisionPlane = Vector4.Zero;
5975 position = part.RelativePosition;
5976 velocity = part.Velocity;
5977 acceleration = part.Acceleration;
5978 angularVelocity = part.AngularVelocity;
5979 rotation = part.RotationOffset;
5980
5981 datasize = 44;
5982 if(includeTexture)
5983 te = part.Shape.TextureEntry;
5984 }
5985
5986 #endregion ScenePresence/SOP Handling
5987 //object block size
5988 data[pos++] = datasize;
5989
5990 // LocalID
5991 Utils.UIntToBytes(localID, data, pos);
5992 pos += 4;
5993
5994 data[pos++] = (byte)attachPoint;
5995
5996 // Avatar/CollisionPlane
5997 if (avatar)
5998 {
5999 data[pos++] = 1;
6000
6001 if (collisionPlane == Vector4.Zero)
6002 collisionPlane = Vector4.UnitW;
6003 //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
6004 collisionPlane.ToBytes(data, pos);
6005 pos += 16;
6006 }
6007 else
6008 {
6009 data[pos++] = 0;
6010 }
6011
6012 // Position
6013 position.ToBytes(data, pos);
6014 pos += 12;
6015
6016 // Velocity
6017 ClampVectorForUint(ref velocity, 128f);
6018 Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2;
6019 Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2;
6020 Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2;
6021
6022 // Acceleration
6023 ClampVectorForUint(ref acceleration, 64f);
6024 Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2;
6025 Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2;
6026 Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2;
6027
6028 // Rotation
6029 Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2;
6030 Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2;
6031 Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2;
6032 Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2;
6033
6034 // Angular Velocity
6035 ClampVectorForUint(ref angularVelocity, 64f);
6036 Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2;
6037 Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2;
6038 Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2;
6039
6040 // texture entry block size
6041 if(te == null)
6042 {
6043 data[pos++] = 0;
6044 data[pos++] = 0;
6045 }
6046 else
6047 {
6048 int len = te.Length & 0x7fff;
6049 int totlen = len + 4;
6050 data[pos++] = (byte)totlen;
6051 data[pos++] = (byte)(totlen >> 8);
6052 data[pos++] = (byte)len; // wtf ???
6053 data[pos++] = (byte)(len >> 8);
6054 data[pos++] = 0;
6055 data[pos++] = 0;
6056 Buffer.BlockCopy(te, 0, data, pos, len);
6057 pos += len;
6058 }
6059 // total size 63 or 47 + (texture size + 4)
6060 }
6061
5648 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 6062 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5649 { 6063 {
5650 Vector3 offsetPosition = data.OffsetPosition;
5651 Quaternion rotation = data.Rotation; 6064 Quaternion rotation = data.Rotation;
5652 // tpvs can only see rotations around Z in some cases 6065 // tpvs can only see rotations around Z in some cases
5653 if(!data.Flying && !data.IsSatOnObject) 6066 if(!data.Flying && !data.IsSatOnObject)
@@ -5657,27 +6070,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5657 } 6070 }
5658 rotation.Normalize(); 6071 rotation.Normalize();
5659 6072
5660 uint parentID = data.ParentID;
5661
5662// m_log.DebugFormat( 6073// m_log.DebugFormat(
5663// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 6074// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5664 6075
5665 byte[] objectData = new byte[76]; 6076 byte[] objectData = new byte[76];
5666 6077
5667 Vector3 velocity = new Vector3(0, 0, 0); 6078 //Vector3 velocity = Vector3.Zero;
5668 Vector3 acceleration = new Vector3(0, 0, 0); 6079 Vector3 acceleration = Vector3.Zero;
6080 Vector3 angularvelocity = Vector3.Zero;
5669 6081
5670 data.CollisionPlane.ToBytes(objectData, 0); 6082 data.CollisionPlane.ToBytes(objectData, 0);
5671 offsetPosition.ToBytes(objectData, 16); 6083 data.OffsetPosition.ToBytes(objectData, 16);
5672 velocity.ToBytes(objectData, 28); 6084 data.Velocity.ToBytes(objectData, 28);
5673 acceleration.ToBytes(objectData, 40); 6085 acceleration.ToBytes(objectData, 40);
5674 rotation.ToBytes(objectData, 52); 6086 rotation.ToBytes(objectData, 52);
5675 data.AngularVelocity.ToBytes(objectData, 64); 6087 angularvelocity.ToBytes(objectData, 64);
5676 6088
5677 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 6089 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5678 6090
5679 update.Data = Utils.EmptyBytes; 6091 update.Data = Utils.EmptyBytes;
5680 update.ExtraParams = new byte[1]; 6092 update.ExtraParams = Utils.EmptyBytes;
5681 update.FullID = data.UUID; 6093 update.FullID = data.UUID;
5682 update.ID = data.LocalId; 6094 update.ID = data.LocalId;
5683 update.Material = (byte)Material.Flesh; 6095 update.Material = (byte)Material.Flesh;
@@ -5714,7 +6126,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5714 return update; 6126 return update;
5715 } 6127 }
5716 6128
5717// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) 6129 protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
6130 {
6131 Quaternion rotation = data.Rotation;
6132 // tpvs can only see rotations around Z in some cases
6133 if (!data.Flying && !data.IsSatOnObject)
6134 {
6135 rotation.X = 0f;
6136 rotation.Y = 0f;
6137 }
6138 rotation.Normalize();
6139
6140 //Vector3 velocity = Vector3.Zero;
6141 //Vector3 acceleration = Vector3.Zero;
6142 //Vector3 angularvelocity = Vector3.Zero;
6143
6144 Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
6145 dest[pos++] = 0; // state
6146 data.UUID.ToBytes(dest, pos); pos += 16;
6147 Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
6148 dest[pos++] = (byte)PCode.Avatar;
6149 dest[pos++] = (byte)Material.Flesh;
6150 dest[pos++] = 0; // clickaction
6151 data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
6152
6153 // objectdata block
6154 dest[pos++] = 76;
6155 data.CollisionPlane.ToBytes(dest, pos); pos += 16;
6156 data.OffsetPosition.ToBytes(dest, pos); pos += 12;
6157 data.Velocity.ToBytes(dest, pos); pos += 12;
6158
6159 //acceleration.ToBytes(dest, pos); pos += 12;
6160 Array.Clear(dest, pos, 12); pos += 12;
6161
6162 rotation.ToBytes(dest, pos); pos += 12;
6163
6164 //angularvelocity.ToBytes(dest, pos); pos += 12;
6165 Array.Clear(dest, pos, 12); pos += 12;
6166
6167 SceneObjectPart parentPart = data.ParentPart;
6168 if (parentPart != null)
6169 {
6170 Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
6171 pos += 4;
6172 }
6173 else
6174 {
6175// Utils.UIntToBytesSafepos(0, dest, pos);
6176// pos += 4;
6177 dest[pos++] = 0;
6178 dest[pos++] = 0;
6179 dest[pos++] = 0;
6180 dest[pos++] = 0;
6181 }
6182
6183 //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
6184 dest[pos++] = 0;
6185 dest[pos++] = 0;
6186 dest[pos++] = 0;
6187 dest[pos++] = 0;
6188
6189 //pbs
6190 dest[pos++] = 16;
6191 dest[pos++] = 1;
6192 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6193 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6194 dest[pos++] = 0;
6195 dest[pos++] = 0;
6196 dest[pos++] = 0;
6197 dest[pos++] = 0;
6198
6199 dest[pos++] = 100;
6200 dest[pos++] = 100;
6201
6202 // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
6203 const int pbszeros = 15 + 2 + 1;
6204 Array.Clear(dest, pos, pbszeros); pos += pbszeros;
6205
6206 //NameValue
6207 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6208 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6209 int len = nv.Length;
6210 dest[pos++] = (byte)len;
6211 dest[pos++] = (byte)(len >> 8);
6212 Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
6213
6214 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6215 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6216 // jointtype(1) joint pivot(12) joint offset(12)
6217 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6218 Array.Clear(dest, pos, lastzeros); pos += lastzeros;
6219 }
6220
6221 protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc)
6222 {
6223 Quaternion rotation = data.Rotation;
6224 // tpvs can only see rotations around Z in some cases
6225 if (!data.Flying && !data.IsSatOnObject)
6226 {
6227 rotation.X = 0f;
6228 rotation.Y = 0f;
6229 }
6230 rotation.Normalize();
6231
6232 zc.AddUInt(data.LocalId);
6233 zc.AddByte(0);
6234 zc.AddUUID(data.UUID);
6235 zc.AddZeros(4); // crc unused
6236 zc.AddByte((byte)PCode.Avatar);
6237 zc.AddByte((byte)Material.Flesh);
6238 zc.AddByte(0); // clickaction
6239 zc.AddVector3(data.Appearance.AvatarSize);
6240
6241 // objectdata block
6242 zc.AddByte(76); // fixed avatar block size
6243 zc.AddVector4(data.CollisionPlane);
6244 zc.AddVector3(data.OffsetPosition);
6245 zc.AddVector3(data.Velocity);
6246 //zc.AddVector3(acceleration);
6247 zc.AddZeros(12);
6248 zc.AddNormQuat(rotation);
6249 //zc.AddVector3(angularvelocity);
6250 zc.AddZeros(12);
6251
6252 SceneObjectPart parentPart = data.ParentPart;
6253 if (parentPart != null)
6254 zc.AddUInt(parentPart.ParentGroup.LocalId);
6255 else
6256 zc.AddZeros(4);
6257
6258 zc.AddZeros(4); //update flags
6259
6260 //pbs volume data 23
6261 //texture entry 2
6262 //texture anim (1)
6263 const int pbszeros = 23 + 2 + 1;
6264 zc.AddZeros(pbszeros);
6265
6266 //NameValue
6267 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6268 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6269 int len = nv.Length;
6270 zc.AddByte((byte)len);
6271 zc.AddByte((byte)(len >> 8));
6272 zc.AddBytes(nv, len);
6273
6274 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6275 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6276 // jointtype(1) joint pivot(12) joint offset(12)
6277 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6278 zc.AddZeros(lastzeros);
6279 }
6280
5718 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) 6281 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
5719 { 6282 {
5720 byte[] objectData = new byte[60]; 6283 byte[] objectData = new byte[60];
@@ -5737,32 +6300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5737 //update.JointPivot = Vector3.Zero; 6300 //update.JointPivot = Vector3.Zero;
5738 //update.JointType = 0; 6301 //update.JointType = 0;
5739 update.Material = part.Material; 6302 update.Material = part.Material;
5740/*
5741 if (data.ParentGroup.IsAttachment)
5742 {
5743 update.NameValue
5744 = Util.StringToBytes256(
5745 string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID));
5746
5747 update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16));
5748
5749// m_log.DebugFormat(
5750// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}",
5751// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name);
5752//
5753// m_log.DebugFormat(
5754// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}",
5755// update.State, data.Name, data.LocalId, Name);
5756 }
5757 else
5758 {
5759 update.NameValue = Utils.EmptyBytes;
5760
5761 // The root part state is the canonical state for all parts of the object. The other part states in the
5762 // case for attachments may contain conflicting values that can end up crashing the viewer.
5763 update.State = data.ParentGroup.RootPart.Shape.State;
5764 }
5765*/
5766 6303
5767 if (part.ParentGroup.IsAttachment) 6304 if (part.ParentGroup.IsAttachment)
5768 { 6305 {
@@ -5858,15 +6395,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5858 6395
5859 #endregion PrimFlags 6396 #endregion PrimFlags
5860 6397
5861 if (part.Sound != UUID.Zero || part.SoundFlags != 0) 6398 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6399 if (hassound)
5862 { 6400 {
5863 update.Sound = part.Sound; 6401 update.Sound = part.Sound;
5864 update.OwnerID = part.OwnerID;
5865 update.Gain = (float)part.SoundGain; 6402 update.Gain = (float)part.SoundGain;
5866 update.Radius = (float)part.SoundRadius; 6403 update.Radius = (float)part.SoundRadius;
5867 update.Flags = part.SoundFlags; 6404 update.Flags = part.SoundFlags;
5868 } 6405 }
5869 6406
6407 if(hassound || update.PSBlock.Length > 1)
6408 update.OwnerID = part.OwnerID;
6409
5870 switch ((PCode)part.Shape.PCode) 6410 switch ((PCode)part.Shape.PCode)
5871 { 6411 {
5872 case PCode.Grass: 6412 case PCode.Grass:
@@ -5882,6 +6422,308 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5882 return update; 6422 return update;
5883 } 6423 }
5884 6424
6425 protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
6426 {
6427 // prepare data
6428
6429 #region PrimFlags
6430 // prim/update flags
6431 PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
6432 // Don't send the CreateSelected flag to everyone
6433 primflags &= ~PrimFlags.CreateSelected;
6434 if (sp.UUID == part.OwnerID)
6435 {
6436 if (part.CreateSelected)
6437 {
6438 // Only send this flag once, then unset it
6439 primflags |= PrimFlags.CreateSelected;
6440 part.CreateSelected = false;
6441 }
6442 }
6443 #endregion PrimFlags
6444
6445 // data block
6446 byte[] data = null;
6447 byte state = part.Shape.State;
6448 PCode pcode = (PCode)part.Shape.PCode;
6449
6450 //vegetation is special so just do it inline
6451 if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
6452 {
6453 zc.AddUInt(part.LocalId);
6454 zc.AddByte(state); // state
6455 zc.AddUUID(part.UUID);
6456 zc.AddZeros(4); // crc unused
6457 zc.AddByte((byte)pcode);
6458 // material 1
6459 // clickaction 1
6460 zc.AddZeros(2);
6461 zc.AddVector3(part.Shape.Scale);
6462
6463 // objectdata block
6464 zc.AddByte(60); // fixed object block size
6465 zc.AddVector3(part.RelativePosition);
6466 if (pcode == PCode.Grass)
6467 zc.AddZeros(48);
6468 else
6469 {
6470 zc.AddZeros(24);
6471 Quaternion rot = part.RotationOffset;
6472 rot.Normalize();
6473 zc.AddNormQuat(rot);
6474 zc.AddZeros(12);
6475 }
6476
6477 zc.AddUInt(part.ParentID);
6478 zc.AddUInt((uint)primflags); //update flags
6479
6480 /*
6481 if (pcode == PCode.Grass)
6482 {
6483 //pbs volume data 23
6484 //texture entry 2
6485 //texture anim 1
6486 //name value 2
6487 // data 1
6488 // text 5
6489 // media url 1
6490 // particle system 1
6491 // Extraparams 1
6492 // sound id 16
6493 // ownwer 16
6494 // sound gain 4
6495 // sound flags 1
6496 // sound radius 4
6497 // jointtype 1
6498 // joint pivot 12
6499 // joint offset 12
6500 zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6501 return;
6502 }
6503 */
6504
6505 //pbs volume data 23
6506 //texture entry 2
6507 //texture anim 1
6508 //name value 2
6509 zc.AddZeros(23 + 2 + 1 + 2);
6510
6511 //data: the tree type
6512 zc.AddByte(1);
6513 zc.AddZeros(1);
6514 zc.AddByte(state);
6515
6516 // text 5
6517 // media url 1
6518 // particle system 1
6519 // Extraparams 1
6520 // sound id 16
6521 // ownwer 16
6522 // sound gain 4
6523 // sound flags 1
6524 // sound radius 4
6525 // jointtype 1
6526 // joint pivot 12
6527 // joint offset 12
6528 zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6529
6530 return;
6531 }
6532
6533 //NameValue and state
6534 byte[] nv = null;
6535
6536 if (part.ParentGroup.IsAttachment)
6537 {
6538 if (part.IsRoot)
6539 nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID);
6540
6541 int st = (int)part.ParentGroup.AttachmentPoint;
6542 state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
6543 }
6544
6545 // filter out mesh faces hack
6546 ushort profileBegin = part.Shape.ProfileBegin;
6547 ushort profileHollow = part.Shape.ProfileHollow;
6548 byte profileCurve = part.Shape.ProfileCurve;
6549 byte pathScaleY = part.Shape.PathScaleY;
6550
6551 if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
6552 {
6553 profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
6554 // fix old values that confused viewers
6555 if (profileBegin == 1)
6556 profileBegin = 9375;
6557 if (profileHollow == 1)
6558 profileHollow = 27500;
6559 // fix torus hole size Y that also confuse some viewers
6560 if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
6561 pathScaleY = 150;
6562 }
6563
6564 // do encode the things
6565 zc.AddUInt(part.LocalId);
6566 zc.AddByte(state); // state
6567 zc.AddUUID(part.UUID);
6568 zc.AddZeros(4); // crc unused
6569 zc.AddByte((byte)pcode);
6570 zc.AddByte(part.Material);
6571 zc.AddByte(part.ClickAction); // clickaction
6572 zc.AddVector3(part.Shape.Scale);
6573
6574 // objectdata block
6575 zc.AddByte(60); // fixed object block size
6576 zc.AddVector3(part.RelativePosition);
6577 zc.AddVector3(part.Velocity);
6578 zc.AddVector3(part.Acceleration);
6579 Quaternion rotation = part.RotationOffset;
6580 rotation.Normalize();
6581 zc.AddNormQuat(rotation);
6582 zc.AddVector3(part.AngularVelocity);
6583
6584 zc.AddUInt(part.ParentID);
6585 zc.AddUInt((uint)primflags); //update flags
6586
6587 //pbs
6588 zc.AddByte(part.Shape.PathCurve);
6589 zc.AddByte(profileCurve);
6590 zc.AddUInt16(part.Shape.PathBegin);
6591 zc.AddUInt16(part.Shape.PathEnd);
6592 zc.AddByte(part.Shape.PathScaleX);
6593 zc.AddByte(pathScaleY);
6594 zc.AddByte(part.Shape.PathShearX);
6595 zc.AddByte(part.Shape.PathShearY);
6596 zc.AddByte((byte)part.Shape.PathTwist);
6597 zc.AddByte((byte)part.Shape.PathTwistBegin);
6598 zc.AddByte((byte)part.Shape.PathRadiusOffset);
6599 zc.AddByte((byte)part.Shape.PathTaperX);
6600 zc.AddByte((byte)part.Shape.PathTaperY);
6601 zc.AddByte(part.Shape.PathRevolutions);
6602 zc.AddByte((byte)part.Shape.PathSkew);
6603 zc.AddUInt16(profileBegin);
6604 zc.AddUInt16(part.Shape.ProfileEnd);
6605 zc.AddUInt16(profileHollow);
6606
6607 // texture
6608 byte[] tentry = part.Shape.TextureEntry;
6609 if (tentry == null)
6610 zc.AddZeros(2);
6611 else
6612 {
6613 int len = tentry.Length;
6614 zc.AddByte((byte)len);
6615 zc.AddByte((byte)(len >> 8));
6616 zc.AddBytes(tentry, len);
6617 }
6618
6619 // texture animation
6620 byte[] tanim = part.TextureAnimation;
6621 if (tanim == null)
6622 zc.AddZeros(1);
6623 else
6624 {
6625 int len = tanim.Length;
6626 zc.AddByte((byte)len);
6627 zc.AddBytes(tanim, len);
6628 }
6629
6630 //NameValue
6631 if(nv == null)
6632 zc.AddZeros(2);
6633 else
6634 {
6635 int len = nv.Length;
6636 zc.AddByte((byte)len);
6637 zc.AddByte((byte)(len >> 8));
6638 zc.AddBytes(nv, len);
6639 }
6640
6641 // data
6642 if (data == null)
6643 zc.AddZeros(2);
6644 else
6645 {
6646 int len = data.Length;
6647 zc.AddByte((byte)len);
6648 zc.AddByte((byte)(len >> 8));
6649 zc.AddBytes(data, len);
6650 }
6651
6652 //text
6653 if (part.Text == null || part.Text.Length == 0)
6654 zc.AddZeros(5);
6655 else
6656 {
6657 byte[] tbuf = Util.StringToBytes(part.Text, 254);
6658 int len = tbuf.Length;
6659 zc.AddByte((byte)len);
6660 zc.AddBytes(tbuf, len);
6661
6662 //textcolor
6663 byte[] tc = part.GetTextColor().GetBytes(false);
6664 zc.AddBytes(tc, 4);
6665 }
6666
6667 //media url
6668 if (part.MediaUrl == null || part.MediaUrl.Length == 0)
6669 zc.AddZeros(1);
6670 else
6671 {
6672 byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255);
6673 int len = tbuf.Length;
6674 zc.AddByte((byte)len);
6675 zc.AddBytes(tbuf, len);
6676 }
6677
6678 bool hasps = false;
6679 //particle system
6680 byte[] ps = part.ParticleSystem;
6681 if (ps == null || ps.Length < 1)
6682 zc.AddZeros(1);
6683 else
6684 {
6685 int len = ps.Length;
6686 zc.AddByte((byte)len);
6687 zc.AddBytes(ps, len);
6688 hasps = true;
6689 }
6690
6691 //Extraparams
6692 byte[] ep = part.Shape.ExtraParams;
6693 if (ep == null || ep.Length < 2)
6694 zc.AddZeros(1);
6695 else
6696 {
6697 int len = ep.Length;
6698 zc.AddByte((byte)len);
6699 zc.AddBytes(ep, len);
6700 }
6701
6702 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6703 if (hassound)
6704 zc.AddUUID(part.Sound);
6705 else
6706 zc.AddZeros(16);
6707
6708 if (hassound || hasps)
6709 zc.AddUUID(part.OwnerID);
6710 else
6711 zc.AddZeros(16);
6712
6713 if (hassound)
6714 {
6715 zc.AddFloat((float)part.SoundGain);
6716 zc.AddByte(part.SoundFlags);
6717 zc.AddFloat((float)part.SoundRadius);
6718 }
6719 else
6720 zc.AddZeros(9);
6721
6722 // jointtype(1) joint pivot(12) joint offset(12)
6723 const int lastzeros = 1 + 12 + 12;
6724 zc.AddZeros(lastzeros);
6725 }
6726
5885 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) 6727 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
5886 { 6728 {
5887 // TODO: Implement this 6729 // TODO: Implement this
@@ -10047,7 +10889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10047 10889
10048 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); 10890 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
10049 10891
10050 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 10892 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, false);
10051 } 10893 }
10052 return true; 10894 return true;
10053 case "teleporthomeallusers": 10895 case "teleporthomeallusers":
@@ -10195,7 +11037,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10195 11037
10196 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); 11038 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey);
10197 11039
10198 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 11040 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, true);
10199 } 11041 }
10200 return true; 11042 return true;
10201 11043
@@ -12560,14 +13402,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12560 /// provide your own method.</param> 13402 /// provide your own method.</param>
12561 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) 13403 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
12562 { 13404 {
12563
12564/* this is causing packet loss for some reason
12565 if(!m_udpClient.IsConnected)
12566 {
12567 PacketPool.Instance.ReturnPacket(packet);
12568 return;
12569 }
12570*/
12571 if (m_outPacketsToDrop != null) 13405 if (m_outPacketsToDrop != null)
12572 { 13406 {
12573 if (m_outPacketsToDrop.Contains(packet.Type.ToString())) 13407 if (m_outPacketsToDrop.Contains(packet.Type.ToString()))