diff options
author | root | 2019-03-11 23:41:26 +0000 |
---|---|---|
committer | root | 2019-03-11 23:41:26 +0000 |
commit | c7a02dc058018429fca8fb0c979785be34bebaf6 (patch) | |
tree | a364249657222c201c9880ec355dafbcb7f99d9a /OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |
parent | Should have been in the last commit (diff) | |
parent | errr use invariantculture compare not current (diff) | |
download | opensim-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.cs | 1158 |
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())) |