aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs239
1 files changed, 168 insertions, 71 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 662e5ad..526783e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 public event DeRezObject OnDeRezObject; 80 public event DeRezObject OnDeRezObject;
81 public event RezRestoreToWorld OnRezRestoreToWorld; 81 public event RezRestoreToWorld OnRezRestoreToWorld;
82 public event ModifyTerrain OnModifyTerrain; 82 public event ModifyTerrain OnModifyTerrain;
83 public event Action<IClientAPI> OnRegionHandShakeReply; 83 public event Action<IClientAPI, uint> OnRegionHandShakeReply;
84 public event GenericCall1 OnRequestWearables; 84 public event GenericCall1 OnRequestWearables;
85 public event SetAppearance OnSetAppearance; 85 public event SetAppearance OnSetAppearance;
86 public event AvatarNowWearing OnAvatarNowWearing; 86 public event AvatarNowWearing OnAvatarNowWearing;
@@ -392,6 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
392 392
393 protected IAssetService m_assetService; 393 protected IAssetService m_assetService;
394 394
395 protected bool m_supportViewerCache = false;
395 #endregion Class Members 396 #endregion Class Members
396 397
397 #region Properties 398 #region Properties
@@ -552,6 +553,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
552 string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString()); 553 string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString());
553 m_asyncPacketProcess = new JobEngine(name, name, 10000); 554 m_asyncPacketProcess = new JobEngine(name, name, 10000);
554 IsActive = true; 555 IsActive = true;
556
557 m_supportViewerCache = m_udpServer.SupportViewerObjectsCache;
555 } 558 }
556 559
557 #region Client Methods 560 #region Client Methods
@@ -4777,6 +4780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4777 13 // ID (high frequency) 4780 13 // ID (high frequency)
4778 }; 4781 };
4779 4782
4783 static private readonly byte[] ObjectUpdateCachedHeader = new byte[] {
4784 Helpers.MSG_RELIABLE,
4785 0, 0, 0, 0, // sequence number
4786 0, // extra
4787 14 // ID (high frequency)
4788 };
4789
4780 private void ProcessEntityUpdates(int maxUpdatesBytes) 4790 private void ProcessEntityUpdates(int maxUpdatesBytes)
4781 { 4791 {
4782 if (!IsActive) 4792 if (!IsActive)
@@ -4786,8 +4796,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4786 if (mysp == null) 4796 if (mysp == null)
4787 return; 4797 return;
4788 4798
4799
4789 List<EntityUpdate> objectUpdates = null; 4800 List<EntityUpdate> objectUpdates = null;
4790 //List<EntityUpdate> compressedUpdates = null; 4801 List<EntityUpdate> objectUpdateProbes = null;
4802 List<EntityUpdate> compressedUpdates = null;
4791 List<EntityUpdate> terseUpdates = null; 4803 List<EntityUpdate> terseUpdates = null;
4792 List<SceneObjectPart> ObjectAnimationUpdates = null; 4804 List<SceneObjectPart> ObjectAnimationUpdates = null;
4793 4805
@@ -4799,6 +4811,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4799 4811
4800 EntityUpdate update; 4812 EntityUpdate update;
4801 4813
4814 bool viewerCache = m_supportViewerCache && (m_viewerHandShakeFlags & 1) != 0 && mysp.IsChildAgent; // only on child agents
4802 bool doCulling = m_scene.ObjectsCullingByDistance; 4815 bool doCulling = m_scene.ObjectsCullingByDistance;
4803 float cullingrange = 64.0f; 4816 float cullingrange = 64.0f;
4804 Vector3 mypos = Vector3.Zero; 4817 Vector3 mypos = Vector3.Zero;
@@ -4807,7 +4820,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4807 bool orderedDequeue = false; // temporary off 4820 bool orderedDequeue = false; // temporary off
4808 4821
4809 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); 4822 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
4810 4823 bool useCompressUpdate = false;
4811 4824
4812 if (doCulling) 4825 if (doCulling)
4813 { 4826 {
@@ -4834,15 +4847,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4834 } 4847 }
4835 } 4848 }
4836 4849
4837 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 4850 PrimUpdateFlags updateFlags = update.Flags;
4838 4851
4839 if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) 4852 if (updateFlags.HasFlag(PrimUpdateFlags.Kill))
4840 { 4853 {
4841 m_killRecord.Add(update.Entity.LocalId); 4854 m_killRecord.Add(update.Entity.LocalId);
4842 maxUpdatesBytes -= 30; 4855 maxUpdatesBytes -= 30;
4843 continue; 4856 continue;
4844 } 4857 }
4845 4858
4859 useCompressUpdate = false;
4860
4846 if (update.Entity is SceneObjectPart) 4861 if (update.Entity is SceneObjectPart)
4847 { 4862 {
4848 SceneObjectPart part = (SceneObjectPart)update.Entity; 4863 SceneObjectPart part = (SceneObjectPart)update.Entity;
@@ -4928,10 +4943,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4928 if (dpos > maxview * maxview) 4943 if (dpos > maxview * maxview)
4929 continue; 4944 continue;
4930 4945
4931 GroupsNeedFullUpdate.Add(grp); 4946 if (!viewerCache || !updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe))
4932 continue; 4947 {
4948 GroupsNeedFullUpdate.Add(grp);
4949 continue;
4950 }
4951 }
4952 }
4953
4954 if (updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe))
4955 {
4956 if (objectUpdateProbes == null)
4957 {
4958 objectUpdateProbes = new List<EntityUpdate>();
4959 maxUpdatesBytes -= 18;
4960 }
4961 objectUpdateProbes.Add(update);
4962 maxUpdatesBytes -= 12;
4963 continue;
4964 }
4965
4966 if (m_SupportObjectAnimations && updateFlags.HasFlag(PrimUpdateFlags.Animations))
4967 {
4968 if (part.Animations != null)
4969 {
4970 if (ObjectAnimationUpdates == null)
4971 ObjectAnimationUpdates = new List<SceneObjectPart>();
4972 ObjectAnimationUpdates.Add(part);
4973 maxUpdatesBytes -= 20 * part.Animations.Count + 24;
4933 } 4974 }
4934 } 4975 }
4976 if(viewerCache)
4977 useCompressUpdate = grp.IsViewerCachable;
4935 } 4978 }
4936 else if (update.Entity is ScenePresence) 4979 else if (update.Entity is ScenePresence)
4937 { 4980 {
@@ -4951,27 +4994,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4951 4994
4952 #region UpdateFlags to packet type conversion 4995 #region UpdateFlags to packet type conversion
4953 4996
4954 // bool canUseCompressed = true;
4955
4956 if (update.Entity is SceneObjectPart)
4957 {
4958 if (m_SupportObjectAnimations && updateFlags.HasFlag(PrimUpdateFlags.Animations))
4959 {
4960 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4961 if ( sop.Animations != null)
4962 {
4963 if(ObjectAnimationUpdates == null)
4964 ObjectAnimationUpdates = new List<SceneObjectPart>();
4965 ObjectAnimationUpdates.Add(sop);
4966 maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
4967 }
4968 }
4969 }
4970 else
4971 {
4972 // canUseCompressed = false;
4973 }
4974
4975 updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled 4997 updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled
4976 if(updateFlags == PrimUpdateFlags.None) 4998 if(updateFlags == PrimUpdateFlags.None)
4977 continue; 4999 continue;
@@ -5025,34 +5047,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5025 } 5047 }
5026 else 5048 else
5027 { 5049 {
5028 SceneObjectPart part = (SceneObjectPart)update.Entity; 5050 if (useCompressUpdate)
5029 SceneObjectGroup grp = part.ParentGroup;
5030 // minimal compress conditions, not enough ?
5031 //if (grp.UsesPhysics || part.Velocity.LengthSquared() > 1e-8f || part.Acceleration.LengthSquared() > 1e-6f)
5032 { 5051 {
5033 maxUpdatesBytes -= 150; // crude estimation 5052 maxUpdatesBytes -= 150; // crude estimation
5034 5053
5035 if (objectUpdates == null) 5054 if (compressedUpdates == null)
5036 { 5055 {
5037 objectUpdates = new List<EntityUpdate>(); 5056 compressedUpdates = new List<EntityUpdate>();
5038 maxUpdatesBytes -= 18; 5057 maxUpdatesBytes -= 18;
5039 } 5058 }
5040 objectUpdates.Add(update); 5059 compressedUpdates.Add(update);
5041 } 5060 }
5042 //compress still disabled
5043 /*
5044 else 5061 else
5045 { 5062 {
5046 maxUpdatesBytes -= 150; // crude estimation 5063 maxUpdatesBytes -= 150; // crude estimation
5047 5064
5048 if (compressedUpdates == null) 5065 if (objectUpdates == null)
5049 { 5066 {
5050 compressedUpdates = new List<EntityUpdate>(); 5067 objectUpdates = new List<EntityUpdate>();
5051 maxUpdatesBytes -= 18; 5068 maxUpdatesBytes -= 18;
5052 } 5069 }
5053 compressedUpdates.Add(update); 5070 objectUpdates.Add(update);
5054 } 5071 }
5055 */
5056 } 5072 }
5057 } 5073 }
5058 5074
@@ -5147,7 +5163,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5147 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5163 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5148 } 5164 }
5149 } 5165 }
5150 /* 5166
5151 if(compressedUpdates != null) 5167 if(compressedUpdates != null)
5152 { 5168 {
5153 List<EntityUpdate> tau = new List<EntityUpdate>(30); 5169 List<EntityUpdate> tau = new List<EntityUpdate>(30);
@@ -5168,8 +5184,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5168 int count = 0; 5184 int count = 0;
5169 foreach (EntityUpdate eu in compressedUpdates) 5185 foreach (EntityUpdate eu in compressedUpdates)
5170 { 5186 {
5187 SceneObjectPart sop = (SceneObjectPart)eu.Entity;
5188 if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted)
5189 continue;
5171 lastpos = pos; 5190 lastpos = pos;
5172 CreateCompressedUpdateBlock((SceneObjectPart)eu.Entity, mysp, data, ref pos); 5191 CreateCompressedUpdateBlock(sop, mysp, data, ref pos);
5173 if (pos < LLUDPServer.MAXPAYLOAD) 5192 if (pos < LLUDPServer.MAXPAYLOAD)
5174 { 5193 {
5175 tau.Add(eu); 5194 tau.Add(eu);
@@ -5207,7 +5226,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5207 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5226 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5208 } 5227 }
5209 } 5228 }
5210 */ 5229
5230 if (objectUpdateProbes != null)
5231 {
5232 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
5233 byte[] data = buf.Data;
5234
5235 Buffer.BlockCopy(ObjectUpdateCachedHeader, 0, data, 0, 7);
5236
5237 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15
5238 Utils.UInt16ToBytes(timeDilation, data, 15); // 17
5239
5240 int countposition = 17; // blocks count position
5241 int pos = 18;
5242
5243 int count = 0;
5244 foreach (EntityUpdate eu in objectUpdateProbes)
5245 {
5246 SceneObjectPart sop = (SceneObjectPart)eu.Entity;
5247 if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted)
5248 continue;
5249 uint primflags = m_scene.Permissions.GenerateClientFlags(sop, mysp);
5250 if (mysp.UUID != sop.OwnerID)
5251 primflags &= ~(uint)PrimFlags.CreateSelected;
5252 else
5253 {
5254 if (sop.CreateSelected)
5255 primflags |= (uint)PrimFlags.CreateSelected;
5256 else
5257 primflags &= ~(uint)PrimFlags.CreateSelected;
5258 }
5259
5260 Utils.UIntToBytes(sop.LocalId, data, pos); pos += 4;
5261 Utils.UIntToBytes((uint)sop.ParentGroup.PseudoCRC, data, pos); pos += 4; //WRONG
5262 Utils.UIntToBytes(primflags, data, pos); pos += 4;
5263
5264 if (pos < (LLUDPServer.MAXPAYLOAD - 12))
5265 ++count;
5266 else
5267 {
5268 // we need more packets
5269 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
5270 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
5271
5272 buf.Data[countposition] = (byte)count;
5273 buf.DataLength = pos;
5274 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false);
5275
5276 buf = newbuf;
5277 data = buf.Data;
5278 pos = 18;
5279 count = 0;
5280 }
5281 }
5282
5283 if (count > 0)
5284 {
5285 buf.Data[countposition] = (byte)count;
5286 buf.DataLength = pos;
5287 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false);
5288 }
5289 }
5290
5211 if (terseUpdates != null) 5291 if (terseUpdates != null)
5212 { 5292 {
5213 int blocks = terseUpdates.Count; 5293 int blocks = terseUpdates.Count;
@@ -5329,8 +5409,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5329 { 5409 {
5330 lock (GroupsInView) 5410 lock (GroupsInView)
5331 GroupsInView.Add(grp); 5411 GroupsInView.Add(grp);
5412 PrimUpdateFlags flags = PrimUpdateFlags.CancelKill;
5413 if(viewerCache && grp.IsViewerCachable)
5414 flags |= PrimUpdateFlags.UpdateProbe;
5332 foreach (SceneObjectPart p in grp.Parts) 5415 foreach (SceneObjectPart p in grp.Parts)
5333 SendEntityUpdate(p, PrimUpdateFlags.CancelKill); 5416 SendEntityUpdate(p, flags);
5334 } 5417 }
5335 } 5418 }
5336 5419
@@ -5461,10 +5544,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5461 5544
5462 if(GroupsNeedFullUpdate.Count > 0) 5545 if(GroupsNeedFullUpdate.Count > 0)
5463 { 5546 {
5464 foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) 5547 bool viewerCache = m_supportViewerCache && (m_viewerHandShakeFlags & 1) != 0 && mysp.IsChildAgent;
5548 foreach (SceneObjectGroup grp in GroupsNeedFullUpdate)
5465 { 5549 {
5466 foreach(SceneObjectPart p in grp.Parts) 5550 PrimUpdateFlags flags = PrimUpdateFlags.CancelKill;
5467 SendEntityUpdate(p, PrimUpdateFlags.CancelKill); 5551 if (viewerCache && grp.IsViewerCachable)
5552 flags |= PrimUpdateFlags.UpdateProbe;
5553 foreach (SceneObjectPart p in grp.Parts)
5554 SendEntityUpdate(p, flags);
5468 } 5555 }
5469 } 5556 }
5470 5557
@@ -7173,7 +7260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7173 dest[pos++] = state; 7260 dest[pos++] = state;
7174 7261
7175 ///**** temp hack 7262 ///**** temp hack
7176 Utils.UIntToBytesSafepos((uint)rnd.Next(), dest, pos); pos += 4; //CRC needs fix or things will get crazy for now avoid caching 7263 Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4;
7177 dest[pos++] = part.Material; 7264 dest[pos++] = part.Material;
7178 dest[pos++] = part.ClickAction; 7265 dest[pos++] = part.ClickAction;
7179 part.Shape.Scale.ToBytes(dest, pos); pos += 12; 7266 part.Shape.Scale.ToBytes(dest, pos); pos += 12;
@@ -8407,13 +8494,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8407 return true; 8494 return true;
8408 } 8495 }
8409 8496
8497 public uint m_viewerHandShakeFlags = 0;
8498
8410 private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack) 8499 private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack)
8411 { 8500 {
8412 Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply; 8501 Action<IClientAPI, uint> handlerRegionHandShakeReply = OnRegionHandShakeReply;
8413 if (handlerRegionHandShakeReply != null) 8502 if (handlerRegionHandShakeReply == null)
8414 { 8503 return true; // silence the warning
8415 handlerRegionHandShakeReply(this); 8504
8416 } 8505 RegionHandshakeReplyPacket rsrpkt = (RegionHandshakeReplyPacket)Pack;
8506 if(rsrpkt.AgentData.AgentID != m_agentId || rsrpkt.AgentData.SessionID != m_sessionId)
8507 return false;
8508
8509 // regionHandSHake is a protocol message, but it is also seems to be the only way to update terrain textures
8510 // in last case this should be ignored.
8511 OnRegionHandShakeReply = null;
8512 if(m_supportViewerCache)
8513 m_viewerHandShakeFlags = rsrpkt.RegionInfo.Flags;
8514 else
8515 m_viewerHandShakeFlags = 0;
8516
8517 handlerRegionHandShakeReply(this, m_viewerHandShakeFlags);
8417 8518
8418 return true; 8519 return true;
8419 } 8520 }
@@ -8657,19 +8758,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8657 return true; 8758 return true;
8658 } 8759 }
8659 8760
8660 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 8761 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
8661 { 8762 {
8662 m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement"); 8763 //m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
8663 8764
8664 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 8765 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
8665 if (handlerCompleteMovementToRegion != null) 8766 if (handlerCompleteMovementToRegion == null)
8666 { 8767 return false;
8667 handlerCompleteMovementToRegion(sender, true); 8768
8668 } 8769 CompleteAgentMovementPacket cmp = (CompleteAgentMovementPacket)Pack;
8669 else 8770 if(cmp.AgentData.AgentID != m_agentId || cmp.AgentData.SessionID != m_sessionId || cmp.AgentData.CircuitCode != m_circuitCode)
8670 m_log.Debug("HandleCompleteAgentMovement NULL handler"); 8771 return false;
8671 8772
8672 handlerCompleteMovementToRegion = null; 8773 handlerCompleteMovementToRegion(sender, true);
8673 8774
8674 return true; 8775 return true;
8675 } 8776 }
@@ -9141,6 +9242,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9141 9242
9142 private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack) 9243 private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack)
9143 { 9244 {
9245 ObjectRequest handlerObjectRequest = OnObjectRequest;
9246 if (handlerObjectRequest == null)
9247 return false;
9248
9144 RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; 9249 RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack;
9145 9250
9146 #region Packet Session and User Check 9251 #region Packet Session and User Check
@@ -9149,16 +9254,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9149 return true; 9254 return true;
9150 #endregion 9255 #endregion
9151 9256
9152 ObjectRequest handlerObjectRequest = null;
9153
9154 for (int i = 0; i < incomingRequest.ObjectData.Length; i++) 9257 for (int i = 0; i < incomingRequest.ObjectData.Length; i++)
9155 {
9156 handlerObjectRequest = OnObjectRequest;
9157 if (handlerObjectRequest != null)
9158 {
9159 handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); 9258 handlerObjectRequest(incomingRequest.ObjectData[i].ID, this);
9160 }
9161 }
9162 return true; 9259 return true;
9163 } 9260 }
9164 9261