aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs142
1 files changed, 121 insertions, 21 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 731dc8e..552f64c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -40,11 +40,9 @@ using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData; 40using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Client; 42using OpenSim.Framework.Client;
43using OpenSim.Framework.Communications.Cache;
44using OpenSim.Framework.Statistics; 43using OpenSim.Framework.Statistics;
45using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Scenes.Hypergrid;
48using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
49using Timer = System.Timers.Timer; 47using Timer = System.Timers.Timer;
50using AssetLandmark = OpenSim.Framework.AssetLandmark; 48using AssetLandmark = OpenSim.Framework.AssetLandmark;
@@ -98,6 +96,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
98 /// </summary> 96 /// </summary>
99 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector 97 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
100 { 98 {
99 /// <value>
100 /// Debug packet level. At the moment, only 255 does anything (prints out all in and out packets).
101 /// </value>
102 protected int m_debugPacketLevel = 0;
103
101 #region Events 104 #region Events
102 105
103 public event GenericMessage OnGenericMessage; 106 public event GenericMessage OnGenericMessage;
@@ -122,7 +125,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
122 public event ObjectAttach OnObjectAttach; 125 public event ObjectAttach OnObjectAttach;
123 public event ObjectDeselect OnObjectDetach; 126 public event ObjectDeselect OnObjectDetach;
124 public event ObjectDrop OnObjectDrop; 127 public event ObjectDrop OnObjectDrop;
125 public event GenericCall2 OnCompleteMovementToRegion; 128 public event GenericCall1 OnCompleteMovementToRegion;
129 public event UpdateAgent OnPreAgentUpdate;
126 public event UpdateAgent OnAgentUpdate; 130 public event UpdateAgent OnAgentUpdate;
127 public event AgentRequestSit OnAgentRequestSit; 131 public event AgentRequestSit OnAgentRequestSit;
128 public event AgentSit OnAgentSit; 132 public event AgentSit OnAgentSit;
@@ -348,11 +352,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; 352 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
349 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates; 353 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
350 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates; 354 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
355
356 /// <value>
357 /// List used in construction of data blocks for an object update packet. This is to stop us having to
358 /// continually recreate it.
359 /// </value>
360 protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
361
362 /// <value>
363 /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
364 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
365 /// ownerless phantom.
366 ///
367 /// All manipulation of this set has to occur under a m_primFullUpdate.SyncRoot lock
368 ///
369 /// </value>
370 protected HashSet<uint> m_killRecord;
371
351 private int m_moneyBalance; 372 private int m_moneyBalance;
352 private int m_animationSequenceNumber = 1; 373 private int m_animationSequenceNumber = 1;
353 private bool m_SendLogoutPacketWhenClosing = true; 374 private bool m_SendLogoutPacketWhenClosing = true;
354 private AgentUpdateArgs lastarg; 375 private AgentUpdateArgs lastarg;
355 private bool m_IsActive = true; 376 private bool m_IsActive = true;
377 private bool m_IsLoggingOut = false;
356 378
357 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 379 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
358 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 380 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -416,6 +438,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 get { return m_IsActive; } 438 get { return m_IsActive; }
417 set { m_IsActive = value; } 439 set { m_IsActive = value; }
418 } 440 }
441 public bool IsLoggingOut
442 {
443 get { return m_IsLoggingOut; }
444 set { m_IsLoggingOut = value; }
445 }
446
419 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 447 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
420 448
421 #endregion Properties 449 #endregion Properties
@@ -437,6 +465,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
437 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 465 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
438 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 466 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
439 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count); 467 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
468 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
469 m_killRecord = new HashSet<uint>();
440 470
441 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 471 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
442 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 472 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
@@ -466,6 +496,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
466 496
467 public void SetDebugPacketLevel(int newDebug) 497 public void SetDebugPacketLevel(int newDebug)
468 { 498 {
499 m_debugPacketLevel = newDebug;
469 } 500 }
470 501
471 #region Client Methods 502 #region Client Methods
@@ -825,6 +856,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
825 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); 856 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
826 gmp.ParamList[i++].Parameter = val; 857 gmp.ParamList[i++].Parameter = val;
827 } 858 }
859
828 OutPacket(gmp, ThrottleOutPacketType.Task); 860 OutPacket(gmp, ThrottleOutPacketType.Task);
829 } 861 }
830 862
@@ -1461,7 +1493,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1461 kill.ObjectData[0].ID = localID; 1493 kill.ObjectData[0].ID = localID;
1462 kill.Header.Reliable = true; 1494 kill.Header.Reliable = true;
1463 kill.Header.Zerocoded = true; 1495 kill.Header.Zerocoded = true;
1464 OutPacket(kill, ThrottleOutPacketType.State); 1496
1497 lock (m_primFullUpdates.SyncRoot)
1498 {
1499 m_killRecord.Add(localID);
1500 OutPacket(kill, ThrottleOutPacketType.State);
1501 }
1465 } 1502 }
1466 1503
1467 /// <summary> 1504 /// <summary>
@@ -2512,6 +2549,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2512 2549
2513 public void SendAsset(AssetRequestToClient req) 2550 public void SendAsset(AssetRequestToClient req)
2514 { 2551 {
2552 if (req.AssetInf.Data == null)
2553 {
2554 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null",
2555 req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2556 return;
2557 }
2558
2515 //m_log.Debug("sending asset " + req.RequestAssetID); 2559 //m_log.Debug("sending asset " + req.RequestAssetID);
2516 TransferInfoPacket Transfer = new TransferInfoPacket(); 2560 TransferInfoPacket Transfer = new TransferInfoPacket();
2517 Transfer.TransferInfo.ChannelType = 2; 2561 Transfer.TransferInfo.ChannelType = 2;
@@ -3501,21 +3545,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3501 if (count == 0) 3545 if (count == 0)
3502 return; 3546 return;
3503 3547
3504 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count]; 3548 m_fullUpdateDataBlocksBuilder.Clear();
3549
3505 for (int i = 0; i < count; i++) 3550 for (int i = 0; i < count; i++)
3506 { 3551 {
3507 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); 3552 ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue();
3508 3553
3554 if (!m_killRecord.Contains(block.ID))
3555 {
3556 m_fullUpdateDataBlocksBuilder.Add(block);
3557
3509// string text = Util.FieldToString(outPacket.ObjectData[i].Text); 3558// string text = Util.FieldToString(outPacket.ObjectData[i].Text);
3510// if (text.IndexOf("\n") >= 0) 3559// if (text.IndexOf("\n") >= 0)
3511// text = text.Remove(text.IndexOf("\n")); 3560// text = text.Remove(text.IndexOf("\n"));
3512// m_log.DebugFormat( 3561// m_log.DebugFormat(
3513// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", 3562// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}",
3514// outPacket.ObjectData[i].ID, text, Name); 3563// outPacket.ObjectData[i].ID, text, Name);
3564 }
3565// else
3566// {
3567// m_log.WarnFormat(
3568// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name);
3569// }
3515 } 3570 }
3516 }
3517 3571
3518 OutPacket(outPacket, ThrottleOutPacketType.State); 3572 outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray();
3573
3574 OutPacket(outPacket, ThrottleOutPacketType.State);
3575 }
3519 } 3576 }
3520 3577
3521 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 3578 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
@@ -4051,10 +4108,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4051 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); 4108 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4052 edata.CovenantID = covenant; 4109 edata.CovenantID = covenant;
4053 edata.CovenantTimestamp = 0; 4110 edata.CovenantTimestamp = 0;
4054 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) 4111 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4055 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4056 else
4057 edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
4058 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); 4112 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName);
4059 einfopack.Data = edata; 4113 einfopack.Data = edata;
4060 OutPacket(einfopack, ThrottleOutPacketType.Task); 4114 OutPacket(einfopack, ThrottleOutPacketType.Task);
@@ -4075,8 +4129,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4075 4129
4076 //Sending Estate Settings 4130 //Sending Estate Settings
4077 returnblock[0].Parameter = Utils.StringToBytes(estateName); 4131 returnblock[0].Parameter = Utils.StringToBytes(estateName);
4078 // TODO: remove this cruft once MasterAvatar is fully deprecated
4079 //
4080 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); 4132 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString());
4081 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); 4133 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString());
4082 4134
@@ -4866,7 +4918,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4866 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 4918 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
4867 lastarg = arg; // save this set of arguments for nexttime 4919 lastarg = arg; // save this set of arguments for nexttime
4868 if (handlerAgentUpdate != null) 4920 if (handlerAgentUpdate != null)
4921 {
4922 OnPreAgentUpdate(this, arg);
4869 OnAgentUpdate(this, arg); 4923 OnAgentUpdate(this, arg);
4924 }
4870 4925
4871 handlerAgentUpdate = null; 4926 handlerAgentUpdate = null;
4872 } 4927 }
@@ -5505,6 +5560,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5505 // for the client session anyway, in order to protect ourselves against bad code in plugins 5560 // for the client session anyway, in order to protect ourselves against bad code in plugins
5506 try 5561 try
5507 { 5562 {
5563
5508 byte[] visualparams = new byte[appear.VisualParam.Length]; 5564 byte[] visualparams = new byte[appear.VisualParam.Length];
5509 for (int i = 0; i < appear.VisualParam.Length; i++) 5565 for (int i = 0; i < appear.VisualParam.Length; i++)
5510 visualparams[i] = appear.VisualParam[i].ParamValue; 5566 visualparams[i] = appear.VisualParam[i].ParamValue;
@@ -5715,10 +5771,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5715 5771
5716 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 5772 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
5717 { 5773 {
5718 GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 5774 GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
5719 if (handlerCompleteMovementToRegion != null) 5775 if (handlerCompleteMovementToRegion != null)
5720 { 5776 {
5721 handlerCompleteMovementToRegion(); 5777 handlerCompleteMovementToRegion(sender);
5722 } 5778 }
5723 handlerCompleteMovementToRegion = null; 5779 handlerCompleteMovementToRegion = null;
5724 5780
@@ -5946,7 +6002,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5946 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f) 6002 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
5947 { 6003 {
5948 ScenePresence avatar = null; 6004 ScenePresence avatar = null;
5949 if (((Scene)m_scene).TryGetAvatar(AgentId, out avatar)) 6005 if (((Scene)m_scene).TryGetScenePresence(AgentId, out avatar))
5950 { 6006 {
5951 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f) 6007 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f)
5952 { 6008 {
@@ -7038,7 +7094,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7038 assetRequestItem = invService.GetItem(assetRequestItem); 7094 assetRequestItem = invService.GetItem(assetRequestItem);
7039 if (assetRequestItem == null) 7095 if (assetRequestItem == null)
7040 { 7096 {
7041 assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); 7097 ILibraryService lib = m_scene.RequestModuleInterface<ILibraryService>();
7098 if (lib != null)
7099 assetRequestItem = lib.LibraryRootFolder.FindItem(itemID);
7042 if (assetRequestItem == null) 7100 if (assetRequestItem == null)
7043 return true; 7101 return true;
7044 } 7102 }
@@ -10928,7 +10986,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10928 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); 10986 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
10929 #endregion BinaryStats 10987 #endregion BinaryStats
10930 10988
10931 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); 10989 OutPacket(packet, throttlePacketType, true);
10932 } 10990 }
10933 10991
10934 /// <summary> 10992 /// <summary>
@@ -10941,6 +10999,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10941 /// handles splitting manually</param> 10999 /// handles splitting manually</param>
10942 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) 11000 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
10943 { 11001 {
11002 if (m_debugPacketLevel >= 255)
11003 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11004
10944 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); 11005 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
10945 } 11006 }
10946 11007
@@ -11012,10 +11073,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11012 /// <param name="Pack">OpenMetaverse.packet</param> 11073 /// <param name="Pack">OpenMetaverse.packet</param>
11013 public void ProcessInPacket(Packet Pack) 11074 public void ProcessInPacket(Packet Pack)
11014 { 11075 {
11015// m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack); 11076 if (m_debugPacketLevel >= 255)
11077 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11016 11078
11017 if (!ProcessPacketMethod(Pack)) 11079 if (!ProcessPacketMethod(Pack))
11018 m_log.Warn("[CLIENT]: unhandled packet " + Pack); 11080 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11019 11081
11020 PacketPool.Instance.ReturnPacket(Pack); 11082 PacketPool.Instance.ReturnPacket(Pack);
11021 } 11083 }
@@ -11336,6 +11398,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11336 const uint m_maxPacketSize = 600; 11398 const uint m_maxPacketSize = 600;
11337 int numPackets = 1; 11399 int numPackets = 1;
11338 11400
11401 if (data == null)
11402 return 0;
11403
11339 if (data.LongLength > m_maxPacketSize) 11404 if (data.LongLength > m_maxPacketSize)
11340 { 11405 {
11341 // over max number of bytes so split up file 11406 // over max number of bytes so split up file
@@ -11581,5 +11646,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11581 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages); 11646 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages);
11582 OutPacket(packet, ThrottleOutPacketType.Task); 11647 OutPacket(packet, ThrottleOutPacketType.Task);
11583 } 11648 }
11649
11650 public void SendChangeUserRights(UUID agentID, UUID friendID, int rights)
11651 {
11652 ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights);
11653
11654 packet.AgentData = new ChangeUserRightsPacket.AgentDataBlock();
11655 packet.AgentData.AgentID = agentID;
11656
11657 packet.Rights = new ChangeUserRightsPacket.RightsBlock[1];
11658 packet.Rights[0] = new ChangeUserRightsPacket.RightsBlock();
11659 packet.Rights[0].AgentRelated = friendID;
11660 packet.Rights[0].RelatedRights = rights;
11661
11662 OutPacket(packet, ThrottleOutPacketType.Task);
11663 }
11664
11665 public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId)
11666 {
11667 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
11668 dialog.Data.ObjectID = objectId;
11669 dialog.Data.ChatChannel = chatChannel;
11670 dialog.Data.ImageID = UUID.Zero;
11671 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
11672 // this is the username of the *owner*
11673 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
11674 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
11675 dialog.Data.Message = Util.StringToBytes256(message);
11676
11677
11678 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
11679 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
11680 buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!");
11681 dialog.Buttons = buttons;
11682 OutPacket(dialog, ThrottleOutPacketType.Task);
11683 }
11584 } 11684 }
11585} 11685}