aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/LLSDxmlEncode.cs84
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs17
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs370
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs5
-rw-r--r--OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs13
5 files changed, 297 insertions, 192 deletions
diff --git a/OpenSim/Framework/LLSDxmlEncode.cs b/OpenSim/Framework/LLSDxmlEncode.cs
index 102955d..5074f05 100644
--- a/OpenSim/Framework/LLSDxmlEncode.cs
+++ b/OpenSim/Framework/LLSDxmlEncode.cs
@@ -176,96 +176,96 @@ namespace OpenSim.Framework
176 176
177 public static void AddElem(Vector2 e, StringBuilder sb) 177 public static void AddElem(Vector2 e, StringBuilder sb)
178 { 178 {
179 sb.Append("<map><key>x</key>"); 179 sb.Append("<array>");
180 180
181 if(e.X == 0) 181 if(e.X == 0)
182 sb.Append("<real /><key>y</key>"); 182 sb.Append("<real />");
183 else 183 else
184 { 184 {
185 sb.Append("<real>"); 185 sb.Append("<real>");
186 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 186 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
187 sb.Append("</real><key>y</key>"); 187 sb.Append("</real>");
188 } 188 }
189 189
190 if(e.Y == 0) 190 if(e.Y == 0)
191 sb.Append("<real /></map>"); 191 sb.Append("<real /></array>");
192 else 192 else
193 { 193 {
194 sb.Append("<real>"); 194 sb.Append("<real>");
195 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 195 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
196 sb.Append("</real></map>"); 196 sb.Append("</real></array>");
197 } 197 }
198 } 198 }
199 199
200 public static void AddElem(Vector3 e, StringBuilder sb) 200 public static void AddElem(Vector3 e, StringBuilder sb)
201 { 201 {
202 sb.Append("<map>key>x</key>"); 202 sb.Append("<array>");
203 203
204 if(e.X == 0) 204 if(e.X == 0)
205 sb.Append("<real /><key>y</key>"); 205 sb.Append("<real />");
206 else 206 else
207 { 207 {
208 sb.Append("<real>"); 208 sb.Append("<real>");
209 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 209 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
210 sb.Append("</real><key>y</key>"); 210 sb.Append("</real>");
211 } 211 }
212 212
213 if(e.Y == 0) 213 if(e.Y == 0)
214 sb.Append("<real /><key>z</key>"); 214 sb.Append("<real />");
215 else 215 else
216 { 216 {
217 sb.Append("<real>"); 217 sb.Append("<real>");
218 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 218 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
219 sb.Append("</real><key>z</key>"); 219 sb.Append("</real>");
220 } 220 }
221 221
222 if(e.Z == 0) 222 if(e.Z == 0)
223 sb.Append("<real /></map>"); 223 sb.Append("<real /></array>");
224 else 224 else
225 { 225 {
226 sb.Append("<real>"); 226 sb.Append("<real>");
227 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture)); 227 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture));
228 sb.Append("</real></map>"); 228 sb.Append("</real></array>");
229 } 229 }
230 } 230 }
231 231
232 public static void AddElem(Quaternion e, StringBuilder sb) 232 public static void AddElem(Quaternion e, StringBuilder sb)
233 { 233 {
234 sb.Append("<map><key>x</key>"); 234 sb.Append("<array><key>x</key>");
235 235
236 if(e.X == 0) 236 if(e.X == 0)
237 sb.Append("<real /><key>y</key>"); 237 sb.Append("<real />");
238 else 238 else
239 { 239 {
240 sb.Append("<real>"); 240 sb.Append("<real>");
241 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 241 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
242 sb.Append("</real><key>y</key>"); 242 sb.Append("</real>");
243 } 243 }
244 244
245 if(e.Y == 0) 245 if(e.Y == 0)
246 sb.Append("<real /><key>z</key>"); 246 sb.Append("<real />");
247 else 247 else
248 { 248 {
249 sb.Append("<real>"); 249 sb.Append("<real>");
250 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 250 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
251 sb.Append("</real><key>z</key>"); 251 sb.Append("</real>");
252 } 252 }
253 if(e.Z == 0) 253 if(e.Z == 0)
254 sb.Append("<real /><key>w</key>"); 254 sb.Append("<real />");
255 else 255 else
256 { 256 {
257 sb.Append("<real>"); 257 sb.Append("<real>");
258 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture)); 258 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture));
259 sb.Append("</real><key>w</key>"); 259 sb.Append("</real>");
260 } 260 }
261 261
262 if(e.W == 0) 262 if(e.W == 0)
263 sb.Append("<real /></map>"); 263 sb.Append("<real /></array>");
264 else 264 else
265 { 265 {
266 sb.Append("<real>"); 266 sb.Append("<real>");
267 sb.Append(e.W.ToString(CultureInfo.InvariantCulture)); 267 sb.Append(e.W.ToString(CultureInfo.InvariantCulture));
268 sb.Append("</real></map>"); 268 sb.Append("</real></array>");
269 } 269 }
270 } 270 }
271 271
@@ -491,24 +491,24 @@ namespace OpenSim.Framework
491 { 491 {
492 sb.Append("<key>"); 492 sb.Append("<key>");
493 sb.Append(name); 493 sb.Append(name);
494 sb.Append("</key><map><key>x</key>"); 494 sb.Append("</key><array>>");
495 495
496 if(e.X == 0) 496 if(e.X == 0)
497 sb.Append("<real /><key>y</key>"); 497 sb.Append("<real />");
498 else 498 else
499 { 499 {
500 sb.Append("<real>"); 500 sb.Append("<real>");
501 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 501 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
502 sb.Append("</real><key>y</key>"); 502 sb.Append("</real>");
503 } 503 }
504 504
505 if(e.Y == 0) 505 if(e.Y == 0)
506 sb.Append("<real /></map>"); 506 sb.Append("<real /></array>");
507 else 507 else
508 { 508 {
509 sb.Append("<real>"); 509 sb.Append("<real>");
510 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 510 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
511 sb.Append("</real></map>"); 511 sb.Append("</real></array>");
512 } 512 }
513 } 513 }
514 514
@@ -516,33 +516,33 @@ namespace OpenSim.Framework
516 { 516 {
517 sb.Append("<key>"); 517 sb.Append("<key>");
518 sb.Append(name); 518 sb.Append(name);
519 sb.Append("</key><map>key>x</key>"); 519 sb.Append("</key><array>");
520 520
521 if(e.X == 0) 521 if(e.X == 0)
522 sb.Append("<real /><key>y</key>"); 522 sb.Append("<real />");
523 else 523 else
524 { 524 {
525 sb.Append("<real>"); 525 sb.Append("<real>");
526 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 526 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
527 sb.Append("</real><key>y</key>"); 527 sb.Append("</real>");
528 } 528 }
529 529
530 if(e.Y == 0) 530 if(e.Y == 0)
531 sb.Append("<real /><key>z</key>"); 531 sb.Append("<real />");
532 else 532 else
533 { 533 {
534 sb.Append("<real>"); 534 sb.Append("<real>");
535 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 535 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
536 sb.Append("</real><key>z</key>"); 536 sb.Append("</real>");
537 } 537 }
538 538
539 if(e.Z == 0) 539 if(e.Z == 0)
540 sb.Append("<real /></map>"); 540 sb.Append("<real /></array>");
541 else 541 else
542 { 542 {
543 sb.Append("<real>"); 543 sb.Append("<real>");
544 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture)); 544 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture));
545 sb.Append("</real></map>"); 545 sb.Append("</real></array>");
546 } 546 }
547 } 547 }
548 548
@@ -550,41 +550,41 @@ namespace OpenSim.Framework
550 { 550 {
551 sb.Append("<key>"); 551 sb.Append("<key>");
552 sb.Append(name); 552 sb.Append(name);
553 sb.Append("</key><map><key>x</key>"); 553 sb.Append("</key><array>");
554 554
555 if(e.X == 0) 555 if(e.X == 0)
556 sb.Append("<real /><key>y</key>"); 556 sb.Append("<real />");
557 else 557 else
558 { 558 {
559 sb.Append("<real>"); 559 sb.Append("<real>");
560 sb.Append(e.X.ToString(CultureInfo.InvariantCulture)); 560 sb.Append(e.X.ToString(CultureInfo.InvariantCulture));
561 sb.Append("</real><key>y</key>"); 561 sb.Append("</real>");
562 } 562 }
563 563
564 if(e.Y == 0) 564 if(e.Y == 0)
565 sb.Append("<real /><key>z</key>"); 565 sb.Append("<real />");
566 else 566 else
567 { 567 {
568 sb.Append("<real>"); 568 sb.Append("<real>");
569 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture)); 569 sb.Append(e.Y.ToString(CultureInfo.InvariantCulture));
570 sb.Append("</real><key>z</key>"); 570 sb.Append("</real>");
571 } 571 }
572 if(e.Z == 0) 572 if(e.Z == 0)
573 sb.Append("<real /><key>w</key>"); 573 sb.Append("<real />");
574 else 574 else
575 { 575 {
576 sb.Append("<real>"); 576 sb.Append("<real>");
577 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture)); 577 sb.Append(e.Z.ToString(CultureInfo.InvariantCulture));
578 sb.Append("</real><key>w</key>"); 578 sb.Append("</real>");
579 } 579 }
580 580
581 if(e.W == 0) 581 if(e.W == 0)
582 sb.Append("<real /></map>"); 582 sb.Append("<real /></array>");
583 else 583 else
584 { 584 {
585 sb.Append("<real>"); 585 sb.Append("<real>");
586 sb.Append(e.W.ToString(CultureInfo.InvariantCulture)); 586 sb.Append(e.W.ToString(CultureInfo.InvariantCulture));
587 sb.Append("</real></map>"); 587 sb.Append("</real></array>");
588 } 588 }
589 } 589 }
590 590
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 4da4412..58860b0 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -499,6 +499,23 @@ namespace OpenSim.Region.ClientStack.Linden
499 Enqueue(item, avatarID); 499 Enqueue(item, avatarID);
500 } 500 }
501*/ 501*/
502 public StringBuilder StartEvent(string eventName)
503 {
504 StringBuilder sb = new StringBuilder(256);
505 LLSDxmlEncode.AddMap(sb);
506 LLSDxmlEncode.AddElem("message", eventName, sb);
507 LLSDxmlEncode.AddMap("body", sb);
508
509 return sb;
510 }
511
512 public string EndEvent(StringBuilder sb)
513 {
514 LLSDxmlEncode.AddEndMap(sb); // close body
515 LLSDxmlEncode.AddEndMap(sb); // close event
516 return sb.ToString();
517 }
518
502 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) 519 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
503 { 520 {
504 if (DebugLevel > 0) 521 if (DebugLevel > 0)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index cbb1075..fa619c7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using System.Runtime; 32using System.Runtime;
33using System.Text;
33using System.Threading; 34using System.Threading;
34 35
35using log4net; 36using log4net;
@@ -4847,19 +4848,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4847 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); 4848 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
4848 } 4849 }
4849 4850
4850 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> objectFamilyBlocks = new
4851 List<ObjectPropertiesFamilyPacket.ObjectDataBlock>();
4852 List<ObjectPropertiesPacket.ObjectDataBlock> objectPropertiesBlocks =
4853 new List<ObjectPropertiesPacket.ObjectDataBlock>();
4854 List<SceneObjectPart> needPhysics = new List<SceneObjectPart>();
4855
4856 private void ProcessEntityPropertyRequests(int maxUpdateBytes) 4851 private void ProcessEntityPropertyRequests(int maxUpdateBytes)
4857 { 4852 {
4858// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates = 4853 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> objectFamilyBlocks = null;
4859// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); 4854 List<ObjectPropertiesPacket.ObjectDataBlock> objectPropertiesBlocks = null;
4860 4855 List<SceneObjectPart> needPhysics = null;
4861// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
4862// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4863 4856
4864 bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; 4857 bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
4865 4858
@@ -4888,8 +4881,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4888 { 4881 {
4889 SceneObjectPart sop = (SceneObjectPart)update.Entity; 4882 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4890 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); 4883 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4884 if(objectFamilyBlocks == null)
4885 objectFamilyBlocks = new List<ObjectPropertiesFamilyPacket.ObjectDataBlock>();
4891 objectFamilyBlocks.Add(objPropDB); 4886 objectFamilyBlocks.Add(objPropDB);
4892// familyUpdates.Value.Add(update);
4893 maxUpdateBytes -= objPropDB.Length; 4887 maxUpdateBytes -= objPropDB.Length;
4894 } 4888 }
4895 } 4889 }
@@ -4899,26 +4893,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4899 if (update.Entity is SceneObjectPart) 4893 if (update.Entity is SceneObjectPart)
4900 { 4894 {
4901 SceneObjectPart sop = (SceneObjectPart)update.Entity; 4895 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4896 if(needPhysics == null)
4897 needPhysics = new List<SceneObjectPart>();
4902 needPhysics.Add(sop); 4898 needPhysics.Add(sop);
4903 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); 4899 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4900 if(objectPropertiesBlocks == null)
4901 objectPropertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
4904 objectPropertiesBlocks.Add(objPropDB); 4902 objectPropertiesBlocks.Add(objPropDB);
4905// propertyUpdates.Value.Add(update);
4906 maxUpdateBytes -= objPropDB.Length; 4903 maxUpdateBytes -= objPropDB.Length;
4907 } 4904 }
4908 } 4905 }
4909 } 4906 }
4910 4907
4911 if (objectPropertiesBlocks.Count > 0) 4908 if (objectPropertiesBlocks != null)
4912 { 4909 {
4913 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4910 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4914 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[objectPropertiesBlocks.Count]; 4911 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[objectPropertiesBlocks.Count];
4915 for (int i = 0; i < objectPropertiesBlocks.Count; i++) 4912 for (int i = 0; i < objectPropertiesBlocks.Count; i++)
4916 packet.ObjectData[i] = objectPropertiesBlocks[i]; 4913 packet.ObjectData[i] = objectPropertiesBlocks[i];
4917 4914
4918
4919 objectPropertiesBlocks.Clear();
4920 packet.Header.Zerocoded = true;
4921
4922 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4915 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4923 // of the object rather than the properties when the packet was created 4916 // of the object rather than the properties when the packet was created
4924 // HACK : Remove intelligent resending until it's fixed in core 4917 // HACK : Remove intelligent resending until it's fixed in core
@@ -4928,15 +4921,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4928 // ResendPropertyUpdates(propertyUpdates.Value, oPacket); 4921 // ResendPropertyUpdates(propertyUpdates.Value, oPacket);
4929 // }); 4922 // });
4930 OutPacket(packet, ThrottleOutPacketType.Task, true); 4923 OutPacket(packet, ThrottleOutPacketType.Task, true);
4931
4932 // pbcnt += blocks.Count;
4933 // ppcnt++;
4934 } 4924 }
4935 4925
4936 // Int32 fpcnt = 0; 4926 if (objectFamilyBlocks != null)
4937 // Int32 fbcnt = 0;
4938
4939 if (objectFamilyBlocks.Count > 0)
4940 { 4927 {
4941 // one packet per object block... uggh... 4928 // one packet per object block... uggh...
4942 for (int i = 0; i < objectFamilyBlocks.Count; i++) 4929 for (int i = 0; i < objectFamilyBlocks.Count; i++)
@@ -4945,7 +4932,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4945 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); 4932 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4946 4933
4947 packet.ObjectData = objectFamilyBlocks[i]; 4934 packet.ObjectData = objectFamilyBlocks[i];
4948 packet.Header.Zerocoded = true;
4949 4935
4950 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4936 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4951 // of the object rather than the properties when the packet was created 4937 // of the object rather than the properties when the packet was created
@@ -4958,41 +4944,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4958 // ResendPropertyUpdates(updates, oPacket); 4944 // ResendPropertyUpdates(updates, oPacket);
4959 // }); 4945 // });
4960 OutPacket(packet, ThrottleOutPacketType.Task, true); 4946 OutPacket(packet, ThrottleOutPacketType.Task, true);
4961
4962 // fpcnt++;
4963 // fbcnt++;
4964 } 4947 }
4965 objectFamilyBlocks.Clear();
4966 } 4948 }
4967 4949
4968 if(needPhysics.Count > 0) 4950 if(needPhysics != null)
4969 { 4951 {
4970 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 4952 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
4971 if(eq != null) 4953 if(eq != null)
4972 { 4954 {
4973 OSDArray array = new OSDArray(); 4955 StringBuilder sb = eq.StartEvent("ObjectPhysicsProperties");
4974 foreach(SceneObjectPart sop in needPhysics) 4956 LLSDxmlEncode.AddArray("ObjectData", sb);
4957 foreach (SceneObjectPart sop in needPhysics)
4975 { 4958 {
4976 OSDMap physinfo = new OSDMap(6); 4959 LLSDxmlEncode.AddMap(sb);
4977 physinfo["LocalID"] = sop.LocalId; 4960 LLSDxmlEncode.AddElem("LocalID",(int)sop.LocalId, sb);
4978 physinfo["Density"] = sop.Density; 4961 LLSDxmlEncode.AddElem("Density", sop.Density, sb);
4979 physinfo["Friction"] = sop.Friction; 4962 LLSDxmlEncode.AddElem("Friction", sop.Friction, sb);
4980 physinfo["GravityMultiplier"] = sop.GravityModifier; 4963 LLSDxmlEncode.AddElem("GravityMultiplier", sop.GravityModifier, sb);
4981 physinfo["Restitution"] = sop.Restitution; 4964 LLSDxmlEncode.AddElem("Restitution", sop.Restitution, sb);
4982 physinfo["PhysicsShapeType"] = (int)sop.PhysicsShapeType; 4965 LLSDxmlEncode.AddElem("PhysicsShapeType", (int)sop.PhysicsShapeType, sb);
4983 array.Add(physinfo); 4966 LLSDxmlEncode.AddEndMap(sb);
4984 } 4967 }
4985 4968 LLSDxmlEncode.AddEndArray(sb);
4986 OSDMap llsdBody = new OSDMap(1); 4969 OSDllsdxml ev = new OSDllsdxml(eq.EndEvent(sb));
4987 llsdBody.Add("ObjectData", array); 4970 eq.Enqueue(ev, AgentId);
4988 4971 }
4989 eq.Enqueue(BuildEvent("ObjectPhysicsProperties", llsdBody),AgentId);
4990 }
4991 needPhysics.Clear();
4992 } 4972 }
4993
4994 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
4995 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt);
4996 } 4973 }
4997 4974
4998 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags) 4975 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags)
@@ -5309,115 +5286,212 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5309 int sequence_id, bool snap_selection, int request_result, ILandObject lo, 5286 int sequence_id, bool snap_selection, int request_result, ILandObject lo,
5310 float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) 5287 float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
5311 { 5288 {
5312// m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name); 5289 // m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name);
5290
5291 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
5292 if (eq == null)
5293 {
5294 m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data.");
5295 return;
5296 }
5313 5297
5314 LandData landData = lo.LandData; 5298 LandData landData = lo.LandData;
5299 IPrimCounts pc = lo.PrimCounts;
5315 5300
5316 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage(); 5301 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage();
5317 5302
5318 updateMessage.AABBMax = landData.AABBMax; 5303 StringBuilder sb = eq.StartEvent("ParcelProperties");
5319 updateMessage.AABBMin = landData.AABBMin; 5304
5320 updateMessage.Area = landData.Area; 5305 LLSDxmlEncode.AddArray("ParcelData", sb);
5321 updateMessage.AuctionID = landData.AuctionID; 5306 LLSDxmlEncode.AddMap(sb);
5322 updateMessage.AuthBuyerID = landData.AuthBuyerID; 5307
5323 updateMessage.Bitmap = landData.Bitmap; 5308 LLSDxmlEncode.AddElem("LocalID", landData.LocalID, sb);
5324 updateMessage.Desc = landData.Description; 5309 LLSDxmlEncode.AddElem("AABBMax", landData.AABBMax, sb);
5325 updateMessage.Category = landData.Category; 5310 LLSDxmlEncode.AddElem("AABBMin", landData.AABBMin, sb);
5326 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate); 5311 LLSDxmlEncode.AddElem("Area", landData.Area, sb);
5327 updateMessage.ClaimPrice = landData.ClaimPrice; 5312 LLSDxmlEncode.AddElem("AuctionID", (int)landData.AuctionID, sb);
5328 updateMessage.GroupID = landData.GroupID; 5313 LLSDxmlEncode.AddElem("AuthBuyerID", landData.AuthBuyerID, sb);
5329 updateMessage.IsGroupOwned = landData.IsGroupOwned; 5314 LLSDxmlEncode.AddElem("Bitmap", landData.Bitmap, sb);
5330 updateMessage.LandingType = (LandingType) landData.LandingType; 5315 LLSDxmlEncode.AddElem("Category", (int)landData.Category, sb);
5331 updateMessage.LocalID = landData.LocalID; 5316 LLSDxmlEncode.AddElem("ClaimDate", Util.ToDateTime(landData.ClaimDate), sb);
5332 5317 LLSDxmlEncode.AddElem("ClaimPrice", landData.ClaimPrice, sb);
5318 LLSDxmlEncode.AddElem("Desc", landData.Description, sb);
5319 LLSDxmlEncode.AddElem("ParcelFlags", landData.Flags, sb);
5320 LLSDxmlEncode.AddElem("GroupID", landData.GroupID, sb);
5321 LLSDxmlEncode.AddElem("GroupPrims", pc.Group, sb);
5322 LLSDxmlEncode.AddElem("IsGroupOwned", landData.IsGroupOwned, sb);
5323 LLSDxmlEncode.AddElem("LandingType", (int)landData.LandingType, sb);
5333 if (landData.Area > 0) 5324 if (landData.Area > 0)
5334 { 5325 LLSDxmlEncode.AddElem("MaxPrims", parcelObjectCapacity, sb);
5335 updateMessage.MaxPrims = parcelObjectCapacity;
5336 }
5337 else 5326 else
5338 { 5327 LLSDxmlEncode.AddElem("MaxPrims", (int)0, sb);
5339 updateMessage.MaxPrims = 0; 5328 LLSDxmlEncode.AddElem("MediaID", landData.MediaID, sb);
5340 } 5329 LLSDxmlEncode.AddElem("MediaURL", landData.MediaURL, sb);
5341 5330 LLSDxmlEncode.AddElem("MediaAutoScale", landData.MediaAutoScale != 0, sb);
5342 updateMessage.MediaAutoScale = Convert.ToBoolean(landData.MediaAutoScale); 5331 LLSDxmlEncode.AddElem("MusicURL", landData.MusicURL, sb);
5343 updateMessage.MediaID = landData.MediaID; 5332 LLSDxmlEncode.AddElem("Name", landData.Name, sb);
5344 updateMessage.MediaURL = landData.MediaURL; 5333 LLSDxmlEncode.AddElem("OtherCleanTime", landData.OtherCleanTime, sb);
5345 updateMessage.MusicURL = landData.MusicURL; 5334 LLSDxmlEncode.AddElem("OtherCount", (int)0 , sb); //TODO
5346 updateMessage.Name = landData.Name; 5335 LLSDxmlEncode.AddElem("OtherPrims", pc.Others, sb);
5347 updateMessage.OtherCleanTime = landData.OtherCleanTime; 5336 LLSDxmlEncode.AddElem("OwnerID", landData.OwnerID, sb);
5348 updateMessage.OtherCount = 0; //TODO: Unimplemented 5337 LLSDxmlEncode.AddElem("OwnerPrims", pc.Owner, sb);
5349 updateMessage.OwnerID = landData.OwnerID; 5338 LLSDxmlEncode.AddElem("ParcelPrimBonus", simObjectBonusFactor, sb);
5350 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags; 5339 LLSDxmlEncode.AddElem("PassHours", landData.PassHours, sb);
5351 updateMessage.ParcelPrimBonus = simObjectBonusFactor; 5340 LLSDxmlEncode.AddElem("PassPrice", landData.PassPrice, sb);
5352 updateMessage.PassHours = landData.PassHours; 5341 LLSDxmlEncode.AddElem("PublicCount", (int)0, sb); //TODO
5353 updateMessage.PassPrice = landData.PassPrice; 5342 LLSDxmlEncode.AddElem("Privacy", false, sb); //TODO ??
5354 updateMessage.PublicCount = 0; //TODO: Unimplemented 5343 LLSDxmlEncode.AddElem("RegionDenyAnonymous", (regionFlags & (uint)RegionFlags.DenyAnonymous) != 0, sb);
5355 5344 //LLSDxmlEncode.AddElem("RegionDenyIdentified", (regionFlags & (uint)RegionFlags.DenyIdentified) != 0, sb);
5356 updateMessage.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0; 5345 LLSDxmlEncode.AddElem("RegionDenyIdentified", false, sb);
5357 updateMessage.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0; 5346 //LLSDxmlEncode.AddElem("RegionDenyTransacted", (regionFlags & (uint)RegionFlags.DenyTransacted) != 0, sb);
5358 5347 LLSDxmlEncode.AddElem("RegionDenyTransacted", false, sb);
5359 //updateMessage.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0; 5348 LLSDxmlEncode.AddElem("RegionPushOverride", (regionFlags & (uint)RegionFlags.RestrictPushObject) != 0, sb);
5360 //updateMessage.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0; 5349 LLSDxmlEncode.AddElem("RentPrice", (int) 0, sb);;
5361 5350 LLSDxmlEncode.AddElem("RequestResult", request_result, sb);
5362 updateMessage.RentPrice = 0; 5351 LLSDxmlEncode.AddElem("SalePrice", landData.SalePrice, sb);
5363 updateMessage.RequestResult = (ParcelResult) request_result; 5352 LLSDxmlEncode.AddElem("SelectedPrims", pc.Selected, sb);
5364 updateMessage.SalePrice = landData.SalePrice; 5353 LLSDxmlEncode.AddElem("SelfCount", (int)0, sb); //TODO
5365 updateMessage.SelfCount = 0; //TODO: Unimplemented 5354 LLSDxmlEncode.AddElem("SequenceID", sequence_id, sb);
5366 updateMessage.SequenceID = sequence_id;
5367
5368 if (landData.SimwideArea > 0) 5355 if (landData.SimwideArea > 0)
5369 { 5356 LLSDxmlEncode.AddElem("SimWideMaxPrims", lo.GetSimulatorMaxPrimCount(), sb);
5370 updateMessage.SimWideMaxPrims = lo.GetSimulatorMaxPrimCount();
5371 }
5372 else 5357 else
5373 { 5358 LLSDxmlEncode.AddElem("SimWideMaxPrims", (int)0, sb);
5374 updateMessage.SimWideMaxPrims = 0; 5359 LLSDxmlEncode.AddElem("SimWideTotalPrims", pc.Simulator, sb);
5375 } 5360 LLSDxmlEncode.AddElem("SnapSelection", snap_selection, sb);
5376 5361 LLSDxmlEncode.AddElem("SnapshotID", landData.SnapshotID, sb);
5377 updateMessage.SnapSelection = snap_selection; 5362 LLSDxmlEncode.AddElem("Status", (int)landData.Status, sb);
5378 updateMessage.SnapshotID = landData.SnapshotID; 5363 LLSDxmlEncode.AddElem("TotalPrims", pc.Total, sb);
5379 updateMessage.Status = (ParcelStatus) landData.Status; 5364 LLSDxmlEncode.AddElem("UserLocation", landData.UserLocation, sb);
5380 updateMessage.UserLocation = landData.UserLocation; 5365 LLSDxmlEncode.AddElem("UserLookAt", landData.UserLookAt, sb);
5381 updateMessage.UserLookAt = landData.UserLookAt; 5366 LLSDxmlEncode.AddElem("SeeAVs", landData.SeeAVs, sb);
5367 LLSDxmlEncode.AddElem("AnyAVSounds", landData.AnyAVSounds, sb);
5368 LLSDxmlEncode.AddElem("GroupAVSounds", landData.GroupAVSounds, sb);
5369
5370 LLSDxmlEncode.AddEndMap(sb);
5371 LLSDxmlEncode.AddEndArray(sb);
5372
5373 LLSDxmlEncode.AddArray("MediaData", sb);
5374 LLSDxmlEncode.AddMap(sb);
5375
5376 LLSDxmlEncode.AddElem("MediaDesc", landData.MediaDescription, sb);
5377 LLSDxmlEncode.AddElem("MediaHeight", landData.MediaHeight, sb);
5378 LLSDxmlEncode.AddElem("MediaWidth", landData.MediaWidth, sb);
5379 LLSDxmlEncode.AddElem("MediaLoop", landData.MediaLoop, sb);
5380 LLSDxmlEncode.AddElem("MediaType", landData.MediaType, sb);
5381 LLSDxmlEncode.AddElem("ObscureMedia", landData.ObscureMedia, sb);
5382 LLSDxmlEncode.AddElem("ObscureMusic", landData.ObscureMusic, sb);
5383
5384 LLSDxmlEncode.AddEndMap(sb);
5385 LLSDxmlEncode.AddEndArray(sb);
5386
5387 LLSDxmlEncode.AddArray("AgeVerificationBlock", sb);
5388 LLSDxmlEncode.AddMap(sb);
5389
5390 //LLSDxmlEncode.AddElem("RegionDenyAgeUnverified", (regionFlags & (uint)RegionFlags.DenyAgeUnverified) != 0, sb);
5391 LLSDxmlEncode.AddElem("RegionDenyAgeUnverified", false, sb);
5392
5393 LLSDxmlEncode.AddEndMap(sb);
5394 LLSDxmlEncode.AddEndArray(sb);
5395
5396 OSDllsdxml ev = new OSDllsdxml(eq.EndEvent(sb));
5397 eq.Enqueue(ev, AgentId);
5382 5398
5383 updateMessage.MediaType = landData.MediaType; 5399 /*
5384 updateMessage.MediaDesc = landData.MediaDescription; 5400 updateMessage.AABBMax = landData.AABBMax;
5385 updateMessage.MediaWidth = landData.MediaWidth; 5401 updateMessage.AABBMin = landData.AABBMin;
5386 updateMessage.MediaHeight = landData.MediaHeight; 5402 updateMessage.Area = landData.Area;
5387 updateMessage.MediaLoop = landData.MediaLoop; 5403 updateMessage.AuctionID = landData.AuctionID;
5388 updateMessage.ObscureMusic = landData.ObscureMusic; 5404 updateMessage.AuthBuyerID = landData.AuthBuyerID;
5389 updateMessage.ObscureMedia = landData.ObscureMedia; 5405 updateMessage.Bitmap = landData.Bitmap;
5406 updateMessage.Desc = landData.Description;
5407 updateMessage.Category = landData.Category;
5408 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate);
5409 updateMessage.ClaimPrice = landData.ClaimPrice;
5410 updateMessage.GroupID = landData.GroupID;
5411 updateMessage.IsGroupOwned = landData.IsGroupOwned;
5412 updateMessage.LandingType = (LandingType) landData.LandingType;
5413 updateMessage.LocalID = landData.LocalID;
5414
5415 if (landData.Area > 0)
5416 {
5417 updateMessage.MaxPrims = parcelObjectCapacity;
5418 }
5419 else
5420 {
5421 updateMessage.MaxPrims = 0;
5422 }
5390 5423
5391 updateMessage.SeeAVs = landData.SeeAVs; 5424 updateMessage.MediaAutoScale = Convert.ToBoolean(landData.MediaAutoScale);
5392 updateMessage.AnyAVSounds = landData.AnyAVSounds; 5425 updateMessage.MediaID = landData.MediaID;
5393 updateMessage.GroupAVSounds = landData.GroupAVSounds; 5426 updateMessage.MediaURL = landData.MediaURL;
5427 updateMessage.MusicURL = landData.MusicURL;
5428 updateMessage.Name = landData.Name;
5429 updateMessage.OtherCleanTime = landData.OtherCleanTime;
5430 updateMessage.OtherCount = 0; //TODO: Unimplemented
5431 updateMessage.OwnerID = landData.OwnerID;
5432 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags;
5433 updateMessage.ParcelPrimBonus = simObjectBonusFactor;
5434 updateMessage.PassHours = landData.PassHours;
5435 updateMessage.PassPrice = landData.PassPrice;
5436 updateMessage.PublicCount = 0; //TODO: Unimplemented
5437
5438 updateMessage.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0;
5439 updateMessage.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0;
5440
5441 //updateMessage.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0;
5442 //updateMessage.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0;
5443
5444 updateMessage.RentPrice = 0;
5445 updateMessage.RequestResult = (ParcelResult) request_result;
5446 updateMessage.SalePrice = landData.SalePrice;
5447 updateMessage.SelfCount = 0; //TODO: Unimplemented
5448 updateMessage.SequenceID = sequence_id;
5449
5450 if (landData.SimwideArea > 0)
5451 {
5452 updateMessage.SimWideMaxPrims = lo.GetSimulatorMaxPrimCount();
5453 }
5454 else
5455 {
5456 updateMessage.SimWideMaxPrims = 0;
5457 }
5394 5458
5395 IPrimCounts pc = lo.PrimCounts; 5459 updateMessage.SnapSelection = snap_selection;
5396 updateMessage.OwnerPrims = pc.Owner; 5460 updateMessage.SnapshotID = landData.SnapshotID;
5397 updateMessage.GroupPrims = pc.Group; 5461 updateMessage.Status = (ParcelStatus) landData.Status;
5398 updateMessage.OtherPrims = pc.Others; 5462 updateMessage.UserLocation = landData.UserLocation;
5399 updateMessage.SelectedPrims = pc.Selected; 5463 updateMessage.UserLookAt = landData.UserLookAt;
5400 updateMessage.TotalPrims = pc.Total; 5464
5401 updateMessage.SimWideTotalPrims = pc.Simulator; 5465 updateMessage.MediaType = landData.MediaType;
5402 5466 updateMessage.MediaDesc = landData.MediaDescription;
5403 //m_log.DebugFormat("[YYY]: SimWideMaxPrims={0} OwnerPrims={1} TotalPrims={2} SimWideTotalPrims={3} MaxPrims={4}", 5467 updateMessage.MediaWidth = landData.MediaWidth;
5404 // updateMessage.SimWideMaxPrims, updateMessage.OwnerPrims, updateMessage.TotalPrims, updateMessage.SimWideTotalPrims, updateMessage.MaxPrims); 5468 updateMessage.MediaHeight = landData.MediaHeight;
5405 try 5469 updateMessage.MediaLoop = landData.MediaLoop;
5406 { 5470 updateMessage.ObscureMusic = landData.ObscureMusic;
5407 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 5471 updateMessage.ObscureMedia = landData.ObscureMedia;
5408 if (eq != null) 5472
5409 { 5473 updateMessage.SeeAVs = landData.SeeAVs;
5410 eq.ParcelProperties(updateMessage, this.AgentId); 5474 updateMessage.AnyAVSounds = landData.AnyAVSounds;
5411 } 5475 updateMessage.GroupAVSounds = landData.GroupAVSounds;
5412 else 5476
5413 { 5477 updateMessage.OwnerPrims = pc.Owner;
5414 m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data."); 5478 updateMessage.GroupPrims = pc.Group;
5415 } 5479 updateMessage.OtherPrims = pc.Others;
5416 } 5480 updateMessage.SelectedPrims = pc.Selected;
5417 catch (Exception ex) 5481 updateMessage.TotalPrims = pc.Total;
5418 { 5482 updateMessage.SimWideTotalPrims = pc.Simulator;
5419 m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString()); 5483
5420 } 5484 //m_log.DebugFormat("[YYY]: SimWideMaxPrims={0} OwnerPrims={1} TotalPrims={2} SimWideTotalPrims={3} MaxPrims={4}",
5485 // updateMessage.SimWideMaxPrims, updateMessage.OwnerPrims, updateMessage.TotalPrims, updateMessage.SimWideTotalPrims, updateMessage.MaxPrims);
5486 try
5487 {
5488 eq.ParcelProperties(updateMessage, this.AgentId);
5489 }
5490 catch (Exception ex)
5491 {
5492 m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString());
5493 }
5494 */
5421 } 5495 }
5422 5496
5423 public void SendLandAccessListData(List<LandAccessEntry> accessList, uint accessFlag, int localLandID) 5497 public void SendLandAccessListData(List<LandAccessEntry> accessList, uint accessFlag, int localLandID)
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index e0c5563..8e69d4b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System.Text;
28using System.Net; 29using System.Net;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
@@ -58,11 +59,13 @@ namespace OpenSim.Region.Framework.Interfaces
58 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, 59 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent,
59 bool canVoiceChat, bool isModerator, bool textMute, bool isEnterorLeave); 60 bool canVoiceChat, bool isModerator, bool textMute, bool isEnterorLeave);
60 void ChatterBoxForceClose(UUID toAgent, UUID sessionID, string reason); 61 void ChatterBoxForceClose(UUID toAgent, UUID sessionID, string reason);
61 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 62 //void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
62 void GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data); 63 void GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data);
63 void ScriptRunningEvent(UUID objectID, UUID itemID, bool running, UUID avatarID); 64 void ScriptRunningEvent(UUID objectID, UUID itemID, bool running, UUID avatarID);
64 OSD BuildEvent(string eventName, OSD eventBody); 65 OSD BuildEvent(string eventName, OSD eventBody);
65 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID); 66 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
66 67
68 StringBuilder StartEvent(string eventName);
69 string EndEvent(StringBuilder sb);
67 } 70 }
68} 71}
diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
index 9880c91..b17425a 100644
--- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
+++ b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
@@ -30,6 +30,7 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Net; 31using System.Net;
32using System.Reflection; 32using System.Reflection;
33using System.Text;
33using System.Threading; 34using System.Threading;
34using log4net; 35using log4net;
35using Nini.Config; 36using Nini.Config;
@@ -183,5 +184,15 @@ namespace OpenSim.Tests.Common
183 { 184 {
184 AddEvent(avatarID, "partPhysicsProperties", localID, physhapetype, density, friction, bounce, gravmod); 185 AddEvent(avatarID, "partPhysicsProperties", localID, physhapetype, density, friction, bounce, gravmod);
185 } 186 }
186 } 187
188 public StringBuilder StartEvent(string eventName)
189 {
190 return null;
191 }
192
193 public string EndEvent(StringBuilder sb)
194 {
195 return "";
196 }
197}
187} \ No newline at end of file 198} \ No newline at end of file