aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim.RegionServer/SimClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim.RegionServer/SimClient.cs')
-rw-r--r--OpenSim.RegionServer/SimClient.cs456
1 files changed, 35 insertions, 421 deletions
diff --git a/OpenSim.RegionServer/SimClient.cs b/OpenSim.RegionServer/SimClient.cs
index f5cfaad..81da10e 100644
--- a/OpenSim.RegionServer/SimClient.cs
+++ b/OpenSim.RegionServer/SimClient.cs
@@ -80,7 +80,7 @@ namespace OpenSim
80 private AssetCache m_assetCache; 80 private AssetCache m_assetCache;
81 private IGridServer m_gridServer; 81 private IGridServer m_gridServer;
82 private IUserServer m_userServer = null; 82 private IUserServer m_userServer = null;
83 private OpenSimNetworkHandler m_application; 83 private OpenSimNetworkHandler m_networkServer;
84 private InventoryCache m_inventoryCache; 84 private InventoryCache m_inventoryCache;
85 public bool m_sandboxMode; 85 public bool m_sandboxMode;
86 private int cachedtextureserial = 0; 86 private int cachedtextureserial = 0;
@@ -104,12 +104,12 @@ namespace OpenSim
104 m_clientThreads = clientThreads; 104 m_clientThreads = clientThreads;
105 m_assetCache = assetCache; 105 m_assetCache = assetCache;
106 m_gridServer = gridServer; 106 m_gridServer = gridServer;
107 m_application = application; 107 m_networkServer = application;
108 m_inventoryCache = inventoryCache; 108 m_inventoryCache = inventoryCache;
109 m_sandboxMode = sandboxMode; 109 m_sandboxMode = sandboxMode;
110 m_child = child; 110 m_child = child;
111 m_regionData = regionDat; 111 m_regionData = regionDat;
112 112
113 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW,"OpenSimClient.cs - Started up new client thread to handle incoming request"); 113 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW,"OpenSimClient.cs - Started up new client thread to handle incoming request");
114 cirpack = initialcirpack; 114 cirpack = initialcirpack;
115 userEP = remoteEP; 115 userEP = remoteEP;
@@ -185,7 +185,7 @@ namespace OpenSim
185 m_world.RemoveViewerAgent(this); 185 m_world.RemoveViewerAgent(this);
186 186
187 m_clientThreads.Remove(this.CircuitCode); 187 m_clientThreads.Remove(this.CircuitCode);
188 m_application.RemoveClientCircuit(this.CircuitCode); 188 m_networkServer.RemoveClientCircuit(this.CircuitCode);
189 this.ClientThread.Abort(); 189 this.ClientThread.Abort();
190 } 190 }
191 191
@@ -266,399 +266,6 @@ namespace OpenSim
266 }*/ 266 }*/
267 } 267 }
268 268
269 protected virtual void ProcessInPacket(Packet Pack)
270 {
271 ack_pack(Pack);
272 if (debug)
273 {
274 if (Pack.Type != PacketType.AgentUpdate)
275 {
276 Console.WriteLine(Pack.Type.ToString());
277 }
278 }
279
280 if (this.ProcessPacketMethod(Pack))
281 {
282 //there is a handler registered that handled this packet type
283 return;
284 }
285 else
286 {
287 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
288
289 switch (Pack.Type)
290 {
291 case PacketType.CompleteAgentMovement:
292 if (this.m_child) this.UpgradeClient();
293 ClientAvatar.CompleteMovement(m_world);
294 ClientAvatar.SendInitialPosition();
295 this.EnableNeighbours();
296 break;
297 case PacketType.RegionHandshakeReply:
298 m_world.SendLayerData(this);
299 break;
300 case PacketType.AgentWearablesRequest:
301 ClientAvatar.SendInitialAppearance();
302 foreach (SimClient client in m_clientThreads.Values)
303 {
304 if (client.AgentID != this.AgentID)
305 {
306 ObjectUpdatePacket objupdate = client.ClientAvatar.CreateUpdatePacket();
307 this.OutPacket(objupdate);
308 client.ClientAvatar.SendAppearanceToOtherAgent(this);
309 }
310 }
311 m_world.GetInitialPrims(this);
312 break;
313 case PacketType.AgentIsNowWearing:
314 AgentIsNowWearingPacket wear = (AgentIsNowWearingPacket)Pack;
315 //Console.WriteLine(Pack.ToString());
316 break;
317 case PacketType.AgentSetAppearance:
318 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
319 // Console.WriteLine(appear.ToString());
320 this.ClientAvatar.SetAppearance(appear);
321 break;
322 case PacketType.ObjectAdd:
323 m_world.AddNewPrim((ObjectAddPacket)Pack, this);
324 break;
325 case PacketType.ObjectLink:
326 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW,Pack.ToString());
327 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
328 uint parentprimid = 0;
329 OpenSim.world.Primitive parentprim = null;
330 if (link.ObjectData.Length > 1)
331 {
332 parentprimid = link.ObjectData[0].ObjectLocalID;
333 foreach (Entity ent in m_world.Entities.Values)
334 {
335 if (ent.localid == parentprimid)
336 {
337 parentprim = (OpenSim.world.Primitive)ent;
338
339 }
340 }
341 for (int i = 1; i < link.ObjectData.Length; i++)
342 {
343 foreach (Entity ent in m_world.Entities.Values)
344 {
345 if (ent.localid == link.ObjectData[i].ObjectLocalID)
346 {
347 ((OpenSim.world.Primitive)ent).MakeParent(parentprim);
348 }
349 }
350 }
351 }
352 break;
353 case PacketType.ObjectScale:
354 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW,Pack.ToString());
355 break;
356 case PacketType.ObjectShape:
357 ObjectShapePacket shape = (ObjectShapePacket)Pack;
358 for (int i = 0; i < shape.ObjectData.Length; i++)
359 {
360 foreach (Entity ent in m_world.Entities.Values)
361 {
362 if (ent.localid == shape.ObjectData[i].ObjectLocalID)
363 {
364 ((OpenSim.world.Primitive)ent).UpdateShape(shape.ObjectData[i]);
365 }
366 }
367 }
368 break;
369 case PacketType.RequestImage:
370 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
371 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
372 {
373 m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image);
374 }
375 break;
376 case PacketType.TransferRequest:
377 //Console.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request");
378 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
379 m_assetCache.AddAssetRequest(this, transfer);
380 break;
381 case PacketType.AgentUpdate:
382 ClientAvatar.HandleUpdate((AgentUpdatePacket)Pack);
383 break;
384 case PacketType.ObjectImage:
385 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
386 for (int i = 0; i < imagePack.ObjectData.Length; i++)
387 {
388 foreach (Entity ent in m_world.Entities.Values)
389 {
390 if (ent.localid == imagePack.ObjectData[i].ObjectLocalID)
391 {
392 ((OpenSim.world.Primitive)ent).UpdateTexture(imagePack.ObjectData[i].TextureEntry);
393 }
394 }
395 }
396 break;
397 case PacketType.ObjectFlagUpdate:
398 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
399 foreach (Entity ent in m_world.Entities.Values)
400 {
401 if (ent.localid == flags.AgentData.ObjectLocalID)
402 {
403 ((OpenSim.world.Primitive)ent).UpdateObjectFlags(flags);
404 }
405 }
406 break;
407 case PacketType.AssetUploadRequest:
408 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
409 this.UploadAssets.HandleUploadPacket(request, request.AssetBlock.TransactionID.Combine(this.SecureSessionID));
410 break;
411 case PacketType.RequestXfer:
412 //Console.WriteLine(Pack.ToString());
413 break;
414 case PacketType.SendXferPacket:
415 this.UploadAssets.HandleXferPacket((SendXferPacketPacket)Pack);
416 break;
417 case PacketType.CreateInventoryFolder:
418 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
419 m_inventoryCache.CreateNewInventoryFolder(this, invFolder.FolderData.FolderID, (ushort)invFolder.FolderData.Type, Util.FieldToString(invFolder.FolderData.Name), invFolder.FolderData.ParentID);
420 //Console.WriteLine(Pack.ToString());
421 break;
422 case PacketType.CreateInventoryItem:
423 //Console.WriteLine(Pack.ToString());
424 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
425 if (createItem.InventoryBlock.TransactionID != LLUUID.Zero)
426 {
427 this.UploadAssets.CreateInventoryItem(createItem);
428 }
429 else
430 {
431 // Console.Write(Pack.ToString());
432 this.CreateInventoryItem(createItem);
433 }
434 break;
435 case PacketType.FetchInventory:
436 //Console.WriteLine("fetch item packet");
437 FetchInventoryPacket FetchInventory = (FetchInventoryPacket)Pack;
438 m_inventoryCache.FetchInventory(this, FetchInventory);
439 break;
440 case PacketType.FetchInventoryDescendents:
441 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
442 m_inventoryCache.FetchInventoryDescendents(this, Fetch);
443 break;
444 case PacketType.UpdateInventoryItem:
445 UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
446 //Console.WriteLine(Pack.ToString());
447 for (int i = 0; i < update.InventoryData.Length; i++)
448 {
449 if (update.InventoryData[i].TransactionID != LLUUID.Zero)
450 {
451 AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionID));
452 if (asset != null)
453 {
454 // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToStringHyphenated() + " already in cache");
455 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
456 }
457 else
458 {
459 asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
460 if (asset != null)
461 {
462 //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToStringHyphenated() + " to cache");
463 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
464 }
465 else
466 {
467 //Console.WriteLine("trying to update inventory item, but asset is null");
468 }
469 }
470 }
471 else
472 {
473 m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ;
474 }
475 }
476 break;
477 case PacketType.ViewerEffect:
478 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
479 foreach (SimClient client in m_clientThreads.Values)
480 {
481 if (client.AgentID != this.AgentID)
482 {
483 viewer.AgentData.AgentID = client.AgentID;
484 viewer.AgentData.SessionID = client.SessionID;
485 client.OutPacket(viewer);
486 }
487 }
488 break;
489 case PacketType.RequestTaskInventory:
490 // Console.WriteLine(Pack.ToString());
491 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
492 ReplyTaskInventoryPacket replytask = new ReplyTaskInventoryPacket();
493 bool foundent = false;
494 foreach (Entity ent in m_world.Entities.Values)
495 {
496 if (ent.localid == requesttask.InventoryData.LocalID)
497 {
498 replytask.InventoryData.TaskID = ent.uuid;
499 replytask.InventoryData.Serial = 0;
500 replytask.InventoryData.Filename = new byte[0];
501 foundent = true;
502 }
503 }
504 if (foundent)
505 {
506 this.OutPacket(replytask);
507 }
508 break;
509 case PacketType.UpdateTaskInventory:
510 // Console.WriteLine(Pack.ToString());
511 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
512 AgentInventory myinventory = this.m_inventoryCache.GetAgentsInventory(this.AgentID);
513 if (myinventory != null)
514 {
515 if (updatetask.UpdateData.Key == 0)
516 {
517 if (myinventory.InventoryItems[updatetask.InventoryData.ItemID] != null)
518 {
519 if (myinventory.InventoryItems[updatetask.InventoryData.ItemID].Type == 7)
520 {
521 LLUUID noteaid = myinventory.InventoryItems[updatetask.InventoryData.ItemID].AssetID;
522 AssetBase assBase = this.m_assetCache.GetAsset(noteaid);
523 if (assBase != null)
524 {
525 foreach (Entity ent in m_world.Entities.Values)
526 {
527 if (ent.localid == updatetask.UpdateData.LocalID)
528 {
529 if (ent is OpenSim.world.Primitive)
530 {
531 this.m_world.AddScript(ent, Util.FieldToString(assBase.Data));
532 }
533 }
534 }
535 }
536 }
537 }
538 }
539 }
540 break;
541 case PacketType.AgentAnimation:
542 if (!m_child)
543 {
544 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
545 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
546 {
547 if (AgentAni.AnimationList[i].StartAnim)
548 {
549 ClientAvatar.current_anim = AgentAni.AnimationList[i].AnimID;
550 ClientAvatar.anim_seq = 1;
551 ClientAvatar.SendAnimPack();
552 }
553 }
554 }
555 break;
556 case PacketType.ObjectSelect:
557 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
558 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
559 {
560 foreach (Entity ent in m_world.Entities.Values)
561 {
562 if (ent.localid == incomingselect.ObjectData[i].ObjectLocalID)
563 {
564 ((OpenSim.world.Primitive)ent).GetProperites(this);
565 break;
566 }
567 }
568 }
569 break;
570 case PacketType.MapLayerRequest:
571 this.RequestMapLayer();
572 break;
573 case PacketType.MapBlockRequest:
574 MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
575 this.RequestMapBlock( MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY);
576 break;
577
578 case PacketType.TeleportLandmarkRequest:
579 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
580
581 TeleportStartPacket tpStart = new TeleportStartPacket();
582 tpStart.Info.TeleportFlags = 8; // tp via lm
583 this.OutPacket(tpStart);
584
585 TeleportProgressPacket tpProgress = new TeleportProgressPacket();
586 tpProgress.Info.Message = (new System.Text.ASCIIEncoding()).GetBytes("sending_landmark");
587 tpProgress.Info.TeleportFlags = 8;
588 tpProgress.AgentData.AgentID = tpReq.Info.AgentID;
589 this.OutPacket(tpProgress);
590
591 // Fetch landmark
592 LLUUID lmid = tpReq.Info.LandmarkID;
593 AssetBase lma = this.m_assetCache.GetAsset(lmid);
594 if (lma != null)
595 {
596 AssetLandmark lm = new AssetLandmark(lma);
597
598 if (lm.RegionID == m_regionData.SimUUID)
599 {
600 TeleportLocalPacket tpLocal = new TeleportLocalPacket();
601
602 tpLocal.Info.AgentID = tpReq.Info.AgentID;
603 tpLocal.Info.TeleportFlags = 8; // Teleport via landmark
604 tpLocal.Info.LocationID = 2;
605 tpLocal.Info.Position = lm.Position;
606 OutPacket(tpLocal);
607 }
608 else
609 {
610 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
611 tpCancel.Info.AgentID = tpReq.Info.AgentID;
612 tpCancel.Info.SessionID = tpReq.Info.SessionID;
613 OutPacket(tpCancel);
614 }
615 }
616 else
617 {
618 Console.WriteLine("Cancelling Teleport - fetch asset not yet implemented");
619
620 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
621 tpCancel.Info.AgentID = tpReq.Info.AgentID;
622 tpCancel.Info.SessionID = tpReq.Info.SessionID;
623 OutPacket(tpCancel);
624 }
625 break;
626
627 case PacketType.TeleportLocationRequest:
628 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
629 Console.WriteLine(tpLocReq.ToString());
630
631 tpStart = new TeleportStartPacket();
632 tpStart.Info.TeleportFlags = 16; // Teleport via location
633 Console.WriteLine(tpStart.ToString());
634 OutPacket(tpStart);
635
636 if (m_regionData.RegionHandle != tpLocReq.Info.RegionHandle)
637 {
638 /* m_gridServer.getRegion(tpLocReq.Info.RegionHandle); */
639 Console.WriteLine("Inter-sim teleport not yet implemented");
640 TeleportCancelPacket tpCancel = new TeleportCancelPacket();
641 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
642 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
643
644 OutPacket(tpCancel);
645 }
646 else {
647 Console.WriteLine("Local teleport");
648 TeleportLocalPacket tpLocal = new TeleportLocalPacket();
649 tpLocal.Info.AgentID = tpLocReq.AgentData.AgentID;
650 tpLocal.Info.TeleportFlags = tpStart.Info.TeleportFlags;
651 tpLocal.Info.LocationID = 2;
652 tpLocal.Info.LookAt = tpLocReq.Info.LookAt;
653 tpLocal.Info.Position = tpLocReq.Info.Position;
654 OutPacket(tpLocal);
655 }
656
657 break;
658 }
659 }
660 }
661
662 private void ResendUnacked() 269 private void ResendUnacked()
663 { 270 {
664 int now = Environment.TickCount; 271 int now = Environment.TickCount;
@@ -801,11 +408,11 @@ namespace OpenSim
801 if (Pack.Header.Zerocoded) 408 if (Pack.Header.Zerocoded)
802 { 409 {
803 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); 410 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
804 m_application.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP); 411 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
805 } 412 }
806 else 413 else
807 { 414 {
808 m_application.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP); 415 m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
809 } 416 }
810 } 417 }
811 catch (Exception) 418 catch (Exception)
@@ -900,7 +507,8 @@ namespace OpenSim
900 507
901 protected virtual void AuthUser() 508 protected virtual void AuthUser()
902 { 509 {
903 AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code); 510 // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
511 AuthenticateResponse sessionInfo = this.m_networkServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
904 if (!sessionInfo.Authorised) 512 if (!sessionInfo.Authorised)
905 { 513 {
906 //session/circuit not authorised 514 //session/circuit not authorised
@@ -925,36 +533,41 @@ namespace OpenSim
925 // Create Inventory, currently only works for sandbox mode 533 // Create Inventory, currently only works for sandbox mode
926 if (m_sandboxMode) 534 if (m_sandboxMode)
927 { 535 {
928 AgentInventory inventory = null; 536 this.SetupInventory(sessionInfo);
929 if (sessionInfo.LoginInfo.InventoryFolder != null) 537 }
538
539 ClientLoop();
540 }
541 }
542
543 #region Inventory Creation
544 private void SetupInventory(AuthenticateResponse sessionInfo)
545 {
546 AgentInventory inventory = null;
547 if (sessionInfo.LoginInfo.InventoryFolder != null)
548 {
549 inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder);
550 if (sessionInfo.LoginInfo.BaseFolder != null)
551 {
552 if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder))
930 { 553 {
931 inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder); 554 m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
932 if (sessionInfo.LoginInfo.BaseFolder != null) 555 }
556 this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
557 AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
558 if (inventorySet != null)
559 {
560 for (int i = 0; i < inventorySet.Length; i++)
933 { 561 {
934 if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder)) 562 if (inventorySet[i] != null)
935 {
936 m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
937 }
938 this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
939 AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
940 if (inventorySet != null)
941 { 563 {
942 for (int i = 0; i < inventorySet.Length; i++) 564 m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
943 {
944 if (inventorySet[i] != null)
945 {
946 m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
947 }
948 }
949 } 565 }
950 } 566 }
951 } 567 }
952 } 568 }
953
954 ClientLoop();
955 } 569 }
956 } 570 }
957
958 private AgentInventory CreateInventory(LLUUID baseFolder) 571 private AgentInventory CreateInventory(LLUUID baseFolder)
959 { 572 {
960 AgentInventory inventory = null; 573 AgentInventory inventory = null;
@@ -1015,6 +628,7 @@ namespace OpenSim
1015 m_assetCache.AddAsset(asset); 628 m_assetCache.AddAsset(asset);
1016 m_inventoryCache.AddNewInventoryItem(this, packet.InventoryBlock.FolderID, asset); 629 m_inventoryCache.AddNewInventoryItem(this, packet.InventoryBlock.FolderID, asset);
1017 } 630 }
631 #endregion
1018 632
1019 public class QueItem 633 public class QueItem
1020 { 634 {