diff options
author | Melanie Thielker | 2009-05-01 16:29:15 +0000 |
---|---|---|
committer | Melanie Thielker | 2009-05-01 16:29:15 +0000 |
commit | 55a69f3f2d43c2475ace7761177751886b910be8 (patch) | |
tree | 702208f6abb4c794543674e45a6294c63b7075ab /OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |
parent | Update svn properties. (diff) | |
download | opensim-SC_OLD-55a69f3f2d43c2475ace7761177751886b910be8.zip opensim-SC_OLD-55a69f3f2d43c2475ace7761177751886b910be8.tar.gz opensim-SC_OLD-55a69f3f2d43c2475ace7761177751886b910be8.tar.bz2 opensim-SC_OLD-55a69f3f2d43c2475ace7761177751886b910be8.tar.xz |
Improve prim sending by combining multiple prim updates into a single packet
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 273 |
1 files changed, 200 insertions, 73 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 29ff86b..05ebcac 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -69,10 +69,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
69 | private int m_cachedTextureSerial; | 69 | private int m_cachedTextureSerial; |
70 | private Timer m_clientPingTimer; | 70 | private Timer m_clientPingTimer; |
71 | 71 | ||
72 | private Timer m_terseUpdateTimer; | 72 | private Timer m_avatarTerseUpdateTimer; |
73 | private Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_terseUpdates = new Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | 73 | private Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new Dictionary<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); |
74 | private ushort m_terseTimeDilationLast = 0; | 74 | private ushort m_terseTimeDilationLast = 0; |
75 | 75 | ||
76 | private Timer m_primTerseUpdateTimer; | ||
77 | private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | ||
78 | private Timer m_primFullUpdateTimer; | ||
79 | private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = | ||
80 | new List<ObjectUpdatePacket.ObjectDataBlock>(); | ||
81 | |||
76 | private bool m_clientBlocked; | 82 | private bool m_clientBlocked; |
77 | 83 | ||
78 | private int m_probesWithNoIngressPackets; | 84 | private int m_probesWithNoIngressPackets; |
@@ -121,8 +127,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
121 | protected string m_activeGroupName = String.Empty; | 127 | protected string m_activeGroupName = String.Empty; |
122 | protected ulong m_activeGroupPowers; | 128 | protected ulong m_activeGroupPowers; |
123 | protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); | 129 | protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); |
124 | protected int m_terseUpdateRate = 50; | 130 | protected int m_avatarTerseUpdateRate = 50; |
125 | protected int m_terseUpdatesPerPacket = 5; | 131 | protected int m_avatarTerseUpdatesPerPacket = 5; |
132 | |||
133 | // LL uses these limits, apparently. Compressed terse would be | ||
134 | // 23, but we don't have that yet | ||
135 | // | ||
136 | protected int m_primTerseUpdatesPerPacket = 10; | ||
137 | protected int m_primFullUpdatesPerPacket = 14; | ||
138 | |||
139 | protected int m_primTerseUpdateRate = 10; | ||
140 | protected int m_primFullUpdateRate = 14; | ||
126 | 141 | ||
127 | // LLClientView Only | 142 | // LLClientView Only |
128 | public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); | 143 | public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); |
@@ -528,7 +543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
528 | 543 | ||
529 | // Shut down timers | 544 | // Shut down timers |
530 | m_clientPingTimer.Stop(); | 545 | m_clientPingTimer.Stop(); |
531 | m_terseUpdateTimer.Stop(); | 546 | m_avatarTerseUpdateTimer.Stop(); |
547 | m_primTerseUpdateTimer.Stop(); | ||
548 | m_primFullUpdateTimer.Stop(); | ||
532 | 549 | ||
533 | // This is just to give the client a reasonable chance of | 550 | // This is just to give the client a reasonable chance of |
534 | // flushing out all it's packets. There should probably | 551 | // flushing out all it's packets. There should probably |
@@ -609,7 +626,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
609 | { | 626 | { |
610 | // Shut down timers | 627 | // Shut down timers |
611 | m_clientPingTimer.Stop(); | 628 | m_clientPingTimer.Stop(); |
612 | m_terseUpdateTimer.Stop(); | 629 | m_avatarTerseUpdateTimer.Stop(); |
630 | m_primTerseUpdateTimer.Stop(); | ||
631 | m_primFullUpdateTimer.Stop(); | ||
613 | } | 632 | } |
614 | 633 | ||
615 | public void Restart() | 634 | public void Restart() |
@@ -621,9 +640,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
621 | m_clientPingTimer.Elapsed += CheckClientConnectivity; | 640 | m_clientPingTimer.Elapsed += CheckClientConnectivity; |
622 | m_clientPingTimer.Enabled = true; | 641 | m_clientPingTimer.Enabled = true; |
623 | 642 | ||
624 | m_terseUpdateTimer = new Timer(m_terseUpdateRate); | 643 | m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); |
625 | m_terseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); | 644 | m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); |
626 | m_terseUpdateTimer.AutoReset = false; | 645 | m_avatarTerseUpdateTimer.AutoReset = false; |
646 | |||
647 | m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); | ||
648 | m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); | ||
649 | m_primTerseUpdateTimer.AutoReset = false; | ||
650 | |||
651 | m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); | ||
652 | m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); | ||
653 | m_primFullUpdateTimer.AutoReset = false; | ||
627 | } | 654 | } |
628 | 655 | ||
629 | public void Terminate() | 656 | public void Terminate() |
@@ -845,10 +872,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
845 | m_clientPingTimer.Elapsed += CheckClientConnectivity; | 872 | m_clientPingTimer.Elapsed += CheckClientConnectivity; |
846 | m_clientPingTimer.Enabled = true; | 873 | m_clientPingTimer.Enabled = true; |
847 | 874 | ||
848 | m_terseUpdateTimer = new Timer(m_terseUpdateRate); | 875 | m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); |
849 | m_terseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); | 876 | m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); |
850 | m_terseUpdateTimer.AutoReset = false; | 877 | m_avatarTerseUpdateTimer.AutoReset = false; |
878 | |||
879 | m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); | ||
880 | m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); | ||
881 | m_primTerseUpdateTimer.AutoReset = false; | ||
851 | 882 | ||
883 | m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); | ||
884 | m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); | ||
885 | m_primFullUpdateTimer.AutoReset = false; | ||
852 | m_scene.AddNewClient(this); | 886 | m_scene.AddNewClient(this); |
853 | 887 | ||
854 | RefreshGroupMembership(); | 888 | RefreshGroupMembership(); |
@@ -2724,20 +2758,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2724 | CreateAvatarImprovedBlock(localID, position, velocity, rotation); | 2758 | CreateAvatarImprovedBlock(localID, position, velocity, rotation); |
2725 | 2759 | ||
2726 | bool sendpacketnow = false; | 2760 | bool sendpacketnow = false; |
2727 | lock (m_terseUpdates) | 2761 | lock (m_avatarTerseUpdates) |
2728 | { | 2762 | { |
2729 | // Only one update per avatar per packet. No need to send old ones so just overwrite them. | 2763 | // Only one update per avatar per packet. No need to send old ones so just overwrite them. |
2730 | m_terseUpdates[localID] = terseBlock; | 2764 | m_avatarTerseUpdates[localID] = terseBlock; |
2731 | m_terseTimeDilationLast = timeDilation; | 2765 | m_terseTimeDilationLast = timeDilation; |
2732 | 2766 | ||
2733 | // If packet is full or own movement packet, send it. | 2767 | // If packet is full or own movement packet, send it. |
2734 | if (agentid == m_agentId || m_terseUpdates.Count >= m_terseUpdatesPerPacket) | 2768 | if (agentid == m_agentId || m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) |
2735 | { | 2769 | { |
2736 | m_terseUpdateTimer.Stop(); | 2770 | m_avatarTerseUpdateTimer.Stop(); |
2737 | sendpacketnow = true; | 2771 | sendpacketnow = true; |
2738 | } | 2772 | } |
2739 | else if (m_terseUpdates.Count == 1) | 2773 | else if (m_avatarTerseUpdates.Count == 1) |
2740 | m_terseUpdateTimer.Start(); | 2774 | m_avatarTerseUpdateTimer.Start(); |
2741 | } | 2775 | } |
2742 | // Call ProcessAvatarTerseUpdates outside the lock | 2776 | // Call ProcessAvatarTerseUpdates outside the lock |
2743 | if (sendpacketnow) | 2777 | if (sendpacketnow) |
@@ -2746,14 +2780,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2746 | 2780 | ||
2747 | private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) | 2781 | private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) |
2748 | { | 2782 | { |
2749 | lock (m_terseUpdates) | 2783 | lock (m_avatarTerseUpdates) |
2750 | { | 2784 | { |
2751 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | 2785 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); |
2752 | terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; | 2786 | terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; |
2753 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[m_terseUpdates.Count]; | 2787 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[m_avatarTerseUpdates.Count]; |
2754 | 2788 | ||
2755 | int i = 0; | 2789 | int i = 0; |
2756 | foreach (KeyValuePair<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> dbe in m_terseUpdates) | 2790 | foreach (KeyValuePair<uint, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> dbe in m_avatarTerseUpdates) |
2757 | { | 2791 | { |
2758 | terse.ObjectData[i] = dbe.Value; | 2792 | terse.ObjectData[i] = dbe.Value; |
2759 | i++; | 2793 | i++; |
@@ -2764,7 +2798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2764 | terse.Header.Zerocoded = true; | 2798 | terse.Header.Zerocoded = true; |
2765 | OutPacket(terse, ThrottleOutPacketType.Task); | 2799 | OutPacket(terse, ThrottleOutPacketType.Task); |
2766 | 2800 | ||
2767 | m_terseUpdates.Clear(); | 2801 | m_avatarTerseUpdates.Clear(); |
2768 | } | 2802 | } |
2769 | } | 2803 | } |
2770 | 2804 | ||
@@ -2859,81 +2893,124 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2859 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | 2893 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) |
2860 | rotation = Quaternion.Identity; | 2894 | rotation = Quaternion.Identity; |
2861 | 2895 | ||
2862 | ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); | 2896 | ObjectUpdatePacket.ObjectDataBlock objectData = |
2897 | new ObjectUpdatePacket.ObjectDataBlock(); | ||
2863 | 2898 | ||
2899 | objectData = CreatePrimUpdateBlock(primShape, flags); | ||
2864 | 2900 | ||
2901 | objectData.ID = localID; | ||
2902 | objectData.FullID = objectID; | ||
2903 | objectData.OwnerID = ownerID; | ||
2865 | 2904 | ||
2866 | // TODO: don't create new blocks if recycling an old packet | 2905 | objectData.Text = LLUtil.StringToPacketBytes(text); |
2867 | outPacket.RegionData.RegionHandle = regionHandle; | 2906 | objectData.TextColor[0] = color[0]; |
2868 | outPacket.RegionData.TimeDilation = timeDilation; | 2907 | objectData.TextColor[1] = color[1]; |
2869 | outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | 2908 | objectData.TextColor[2] = color[2]; |
2870 | 2909 | objectData.TextColor[3] = color[3]; | |
2871 | outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags); | 2910 | objectData.ParentID = parentID; |
2872 | 2911 | objectData.PSBlock = particleSystem; | |
2873 | outPacket.ObjectData[0].ID = localID; | 2912 | objectData.ClickAction = clickAction; |
2874 | outPacket.ObjectData[0].FullID = objectID; | 2913 | objectData.Material = material; |
2875 | outPacket.ObjectData[0].OwnerID = ownerID; | 2914 | objectData.Flags = 0; |
2876 | |||
2877 | outPacket.ObjectData[0].Text = LLUtil.StringToPacketBytes(text); | ||
2878 | outPacket.ObjectData[0].TextColor[0] = color[0]; | ||
2879 | outPacket.ObjectData[0].TextColor[1] = color[1]; | ||
2880 | outPacket.ObjectData[0].TextColor[2] = color[2]; | ||
2881 | outPacket.ObjectData[0].TextColor[3] = color[3]; | ||
2882 | outPacket.ObjectData[0].ParentID = parentID; | ||
2883 | outPacket.ObjectData[0].PSBlock = particleSystem; | ||
2884 | outPacket.ObjectData[0].ClickAction = clickAction; | ||
2885 | outPacket.ObjectData[0].Material = material; | ||
2886 | outPacket.ObjectData[0].Flags = 0; | ||
2887 | 2915 | ||
2888 | if (attachment) | 2916 | if (attachment) |
2889 | { | 2917 | { |
2890 | // Necessary??? | 2918 | // Necessary??? |
2891 | outPacket.ObjectData[0].JointAxisOrAnchor = new Vector3(0, 0, 2); | 2919 | objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); |
2892 | outPacket.ObjectData[0].JointPivot = new Vector3(0, 0, 0); | 2920 | objectData.JointPivot = new Vector3(0, 0, 0); |
2893 | 2921 | ||
2894 | // Item from inventory??? | 2922 | // Item from inventory??? |
2895 | outPacket.ObjectData[0].NameValue = | 2923 | objectData.NameValue = |
2896 | Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); | 2924 | Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); |
2897 | outPacket.ObjectData[0].State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); | 2925 | objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); |
2898 | } | 2926 | } |
2899 | 2927 | ||
2900 | // Xantor 20080528: Send sound info as well | 2928 | // Xantor 20080528: Send sound info as well |
2901 | // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again | 2929 | // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again |
2902 | outPacket.ObjectData[0].Sound = SoundId; | 2930 | objectData.Sound = SoundId; |
2903 | if (SoundId == UUID.Zero) | 2931 | if (SoundId == UUID.Zero) |
2904 | { | 2932 | { |
2905 | outPacket.ObjectData[0].OwnerID = UUID.Zero; | 2933 | objectData.OwnerID = UUID.Zero; |
2906 | outPacket.ObjectData[0].Gain = 0.0f; | 2934 | objectData.Gain = 0.0f; |
2907 | outPacket.ObjectData[0].Radius = 0.0f; | 2935 | objectData.Radius = 0.0f; |
2908 | outPacket.ObjectData[0].Flags = 0; | 2936 | objectData.Flags = 0; |
2909 | } | 2937 | } |
2910 | else | 2938 | else |
2911 | { | 2939 | { |
2912 | outPacket.ObjectData[0].OwnerID = ownerID; | 2940 | objectData.OwnerID = ownerID; |
2913 | outPacket.ObjectData[0].Gain = (float)SoundGain; | 2941 | objectData.Gain = (float)SoundGain; |
2914 | outPacket.ObjectData[0].Radius = (float)SoundRadius; | 2942 | objectData.Radius = (float)SoundRadius; |
2915 | outPacket.ObjectData[0].Flags = SoundFlags; | 2943 | objectData.Flags = SoundFlags; |
2916 | } | 2944 | } |
2917 | 2945 | ||
2918 | byte[] pb = pos.GetBytes(); | 2946 | byte[] pb = pos.GetBytes(); |
2919 | Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); | 2947 | Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); |
2920 | 2948 | ||
2921 | byte[] vel = velocity.GetBytes(); | 2949 | byte[] vel = velocity.GetBytes(); |
2922 | Array.Copy(vel, 0, outPacket.ObjectData[0].ObjectData, pb.Length, vel.Length); | 2950 | Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); |
2923 | 2951 | ||
2924 | byte[] rot = rotation.GetBytes(); | 2952 | byte[] rot = rotation.GetBytes(); |
2925 | Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length); | 2953 | Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); |
2926 | 2954 | ||
2927 | byte[] rvel = rotational_velocity.GetBytes(); | 2955 | byte[] rvel = rotational_velocity.GetBytes(); |
2928 | Array.Copy(rvel, 0, outPacket.ObjectData[0].ObjectData, 36 + rot.Length, rvel.Length); | 2956 | Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); |
2929 | 2957 | ||
2930 | if (textureanim.Length > 0) | 2958 | if (textureanim.Length > 0) |
2931 | { | 2959 | { |
2932 | outPacket.ObjectData[0].TextureAnim = textureanim; | 2960 | objectData.TextureAnim = textureanim; |
2933 | } | 2961 | } |
2934 | outPacket.Header.Zerocoded = true; | ||
2935 | 2962 | ||
2936 | OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); | 2963 | lock (m_primFullUpdates) |
2964 | { | ||
2965 | if (m_primFullUpdates.Count == 0) | ||
2966 | m_primFullUpdateTimer.Start(); | ||
2967 | |||
2968 | m_primFullUpdates.Add(objectData); | ||
2969 | |||
2970 | if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) | ||
2971 | ProcessPrimFullUpdates(this, null); | ||
2972 | } | ||
2973 | } | ||
2974 | |||
2975 | void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) | ||
2976 | { | ||
2977 | lock (m_primFullUpdates) | ||
2978 | { | ||
2979 | if (m_primFullUpdates.Count == 0) | ||
2980 | { | ||
2981 | m_primFullUpdateTimer.Stop(); | ||
2982 | |||
2983 | return; | ||
2984 | } | ||
2985 | |||
2986 | ObjectUpdatePacket outPacket = | ||
2987 | (ObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
2988 | PacketType.ObjectUpdate); | ||
2989 | |||
2990 | outPacket.RegionData.RegionHandle = | ||
2991 | Scene.RegionInfo.RegionHandle; | ||
2992 | outPacket.RegionData.TimeDilation = | ||
2993 | (ushort)(Scene.TimeDilation * ushort.MaxValue); | ||
2994 | |||
2995 | int count = m_primFullUpdates.Count; | ||
2996 | if (count > m_primFullUpdatesPerPacket) | ||
2997 | count = m_primFullUpdatesPerPacket; | ||
2998 | |||
2999 | outPacket.ObjectData = | ||
3000 | new ObjectUpdatePacket.ObjectDataBlock[count]; | ||
3001 | |||
3002 | for (int index = 0 ; index < count ; index++) | ||
3003 | { | ||
3004 | outPacket.ObjectData[index] = m_primFullUpdates[0]; | ||
3005 | m_primFullUpdates.RemoveAt(0); | ||
3006 | } | ||
3007 | |||
3008 | outPacket.Header.Zerocoded = true; | ||
3009 | OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); | ||
3010 | |||
3011 | if (m_primFullUpdates.Count == 0) | ||
3012 | m_primFullUpdateTimer.Stop(); | ||
3013 | } | ||
2937 | } | 3014 | } |
2938 | 3015 | ||
2939 | /// <summary> | 3016 | /// <summary> |
@@ -2947,15 +3024,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2947 | 3024 | ||
2948 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) | 3025 | if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) |
2949 | rotation = Quaternion.Identity; | 3026 | rotation = Quaternion.Identity; |
2950 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | 3027 | |
2951 | // TODO: don't create new blocks if recycling an old packet | 3028 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = |
2952 | terse.RegionData.RegionHandle = regionHandle; | 3029 | CreatePrimImprovedBlock(localID, position, rotation, |
2953 | terse.RegionData.TimeDilation = timeDilation; | 3030 | velocity, rotationalvelocity, state); |
2954 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | 3031 | |
2955 | terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow... | 3032 | lock (m_primTerseUpdates) |
2956 | terse.Header.Reliable = false; | 3033 | { |
2957 | terse.Header.Zerocoded = true; | 3034 | if (m_primTerseUpdates.Count == 0) |
2958 | OutPacket(terse, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); | 3035 | m_primTerseUpdateTimer.Start(); |
3036 | |||
3037 | m_primTerseUpdates.Add(objectData); | ||
3038 | |||
3039 | if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) | ||
3040 | ProcessPrimTerseUpdates(this, null); | ||
3041 | } | ||
3042 | } | ||
3043 | |||
3044 | void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) | ||
3045 | { | ||
3046 | lock (m_primTerseUpdates) | ||
3047 | { | ||
3048 | if (m_primTerseUpdates.Count == 0) | ||
3049 | { | ||
3050 | m_primTerseUpdateTimer.Stop(); | ||
3051 | |||
3052 | return; | ||
3053 | } | ||
3054 | |||
3055 | ImprovedTerseObjectUpdatePacket outPacket = | ||
3056 | (ImprovedTerseObjectUpdatePacket) | ||
3057 | PacketPool.Instance.GetPacket( | ||
3058 | PacketType.ImprovedTerseObjectUpdate); | ||
3059 | |||
3060 | outPacket.RegionData.RegionHandle = | ||
3061 | Scene.RegionInfo.RegionHandle; | ||
3062 | outPacket.RegionData.TimeDilation = | ||
3063 | (ushort)(Scene.TimeDilation * ushort.MaxValue); | ||
3064 | |||
3065 | int count = m_primTerseUpdates.Count; | ||
3066 | if (count > m_primTerseUpdatesPerPacket) | ||
3067 | count = m_primTerseUpdatesPerPacket; | ||
3068 | |||
3069 | outPacket.ObjectData = | ||
3070 | new ImprovedTerseObjectUpdatePacket. | ||
3071 | ObjectDataBlock[count]; | ||
3072 | |||
3073 | for (int index = 0 ; index < count ; index++) | ||
3074 | { | ||
3075 | outPacket.ObjectData[index] = m_primTerseUpdates[0]; | ||
3076 | m_primTerseUpdates.RemoveAt(0); | ||
3077 | } | ||
3078 | |||
3079 | outPacket.Header.Reliable = false; | ||
3080 | outPacket.Header.Zerocoded = true; | ||
3081 | OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); | ||
3082 | |||
3083 | if (m_primTerseUpdates.Count == 0) | ||
3084 | m_primTerseUpdateTimer.Stop(); | ||
3085 | } | ||
2959 | } | 3086 | } |
2960 | 3087 | ||
2961 | public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) | 3088 | public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) |