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.cs386
1 files changed, 320 insertions, 66 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 960e0a2..5b1aa86 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;
@@ -178,6 +182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
178 public event TeleportLocationRequest OnSetStartLocationRequest; 182 public event TeleportLocationRequest OnSetStartLocationRequest;
179 public event UpdateAvatarProperties OnUpdateAvatarProperties; 183 public event UpdateAvatarProperties OnUpdateAvatarProperties;
180 public event CreateNewInventoryItem OnCreateNewInventoryItem; 184 public event CreateNewInventoryItem OnCreateNewInventoryItem;
185 public event LinkInventoryItem OnLinkInventoryItem;
181 public event CreateInventoryFolder OnCreateNewInventoryFolder; 186 public event CreateInventoryFolder OnCreateNewInventoryFolder;
182 public event UpdateInventoryFolder OnUpdateInventoryFolder; 187 public event UpdateInventoryFolder OnUpdateInventoryFolder;
183 public event MoveInventoryFolder OnMoveInventoryFolder; 188 public event MoveInventoryFolder OnMoveInventoryFolder;
@@ -348,11 +353,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; 353 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
349 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates; 354 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
350 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates; 355 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
356
357 /// <value>
358 /// List used in construction of data blocks for an object update packet. This is to stop us having to
359 /// continually recreate it.
360 /// </value>
361 protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
362
363 /// <value>
364 /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
365 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
366 /// ownerless phantom.
367 ///
368 /// All manipulation of this set has to occur under a m_primFullUpdate.SyncRoot lock
369 ///
370 /// </value>
371 protected HashSet<uint> m_killRecord;
372
351 private int m_moneyBalance; 373 private int m_moneyBalance;
352 private int m_animationSequenceNumber = 1; 374 private int m_animationSequenceNumber = 1;
353 private bool m_SendLogoutPacketWhenClosing = true; 375 private bool m_SendLogoutPacketWhenClosing = true;
354 private AgentUpdateArgs lastarg; 376 private AgentUpdateArgs lastarg;
355 private bool m_IsActive = true; 377 private bool m_IsActive = true;
378 private bool m_IsLoggingOut = false;
379 private bool m_IsPresenceReady = false;
356 380
357 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 381 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 382 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -376,6 +400,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
376 400
377 private Timer m_propertiesPacketTimer; 401 private Timer m_propertiesPacketTimer;
378 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); 402 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
403 private List<Packet> m_pendingPackets;
379 404
380 #endregion Class Members 405 #endregion Class Members
381 406
@@ -416,6 +441,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 get { return m_IsActive; } 441 get { return m_IsActive; }
417 set { m_IsActive = value; } 442 set { m_IsActive = value; }
418 } 443 }
444
445 public bool IsLoggingOut
446 {
447 get { return m_IsLoggingOut; }
448 set { m_IsLoggingOut = value; }
449 }
450
419 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 451 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
420 452
421 #endregion Properties 453 #endregion Properties
@@ -437,6 +469,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
437 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 469 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
438 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 470 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
439 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count); 471 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
472 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
473 m_killRecord = new HashSet<uint>();
440 474
441 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 475 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
442 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 476 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
@@ -466,6 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
466 500
467 public void SetDebugPacketLevel(int newDebug) 501 public void SetDebugPacketLevel(int newDebug)
468 { 502 {
503 m_debugPacketLevel = newDebug;
469 } 504 }
470 505
471 #region Client Methods 506 #region Client Methods
@@ -622,7 +657,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
622 if (pprocessor.Async) 657 if (pprocessor.Async)
623 { 658 {
624 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 659 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
625 Util.FireAndForget(ProcessSpecificPacketAsync,obj); 660 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
626 result = true; 661 result = true;
627 } 662 }
628 else 663 else
@@ -650,8 +685,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
650 public void ProcessSpecificPacketAsync(object state) 685 public void ProcessSpecificPacketAsync(object state)
651 { 686 {
652 AsyncPacketProcess packetObject = (AsyncPacketProcess)state; 687 AsyncPacketProcess packetObject = (AsyncPacketProcess)state;
653 packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); 688
654 689 try
690 {
691 packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack);
692 }
693 catch (Exception e)
694 {
695 // Make sure that we see any exception caused by the asynchronous operation.
696 m_log.Error(
697 string.Format("[LLCLIENTVIEW]: Caught exception while processing {0}", packetObject.Pack), e);
698 }
655 } 699 }
656 700
657 #endregion Packet Handling 701 #endregion Packet Handling
@@ -837,6 +881,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
837 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); 881 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
838 gmp.ParamList[i++].Parameter = val; 882 gmp.ParamList[i++].Parameter = val;
839 } 883 }
884
840 OutPacket(gmp, ThrottleOutPacketType.Task); 885 OutPacket(gmp, ThrottleOutPacketType.Task);
841 } 886 }
842 887
@@ -1473,7 +1518,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1473 kill.ObjectData[0].ID = localID; 1518 kill.ObjectData[0].ID = localID;
1474 kill.Header.Reliable = true; 1519 kill.Header.Reliable = true;
1475 kill.Header.Zerocoded = true; 1520 kill.Header.Zerocoded = true;
1476 OutPacket(kill, ThrottleOutPacketType.State); 1521
1522 lock (m_primFullUpdates.SyncRoot)
1523 {
1524 m_killRecord.Add(localID);
1525 OutPacket(kill, ThrottleOutPacketType.State);
1526 }
1477 } 1527 }
1478 1528
1479 /// <summary> 1529 /// <summary>
@@ -2524,6 +2574,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2524 2574
2525 public void SendAsset(AssetRequestToClient req) 2575 public void SendAsset(AssetRequestToClient req)
2526 { 2576 {
2577 if (req.AssetInf.Data == null)
2578 {
2579 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null",
2580 req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2581 return;
2582 }
2583
2527 //m_log.Debug("sending asset " + req.RequestAssetID); 2584 //m_log.Debug("sending asset " + req.RequestAssetID);
2528 TransferInfoPacket Transfer = new TransferInfoPacket(); 2585 TransferInfoPacket Transfer = new TransferInfoPacket();
2529 Transfer.TransferInfo.ChannelType = 2; 2586 Transfer.TransferInfo.ChannelType = 2;
@@ -3513,21 +3570,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3513 if (count == 0) 3570 if (count == 0)
3514 return; 3571 return;
3515 3572
3516 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count]; 3573 m_fullUpdateDataBlocksBuilder.Clear();
3574
3517 for (int i = 0; i < count; i++) 3575 for (int i = 0; i < count; i++)
3518 { 3576 {
3519 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); 3577 ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue();
3520 3578
3579 if (!m_killRecord.Contains(block.ID))
3580 {
3581 m_fullUpdateDataBlocksBuilder.Add(block);
3582
3521// string text = Util.FieldToString(outPacket.ObjectData[i].Text); 3583// string text = Util.FieldToString(outPacket.ObjectData[i].Text);
3522// if (text.IndexOf("\n") >= 0) 3584// if (text.IndexOf("\n") >= 0)
3523// text = text.Remove(text.IndexOf("\n")); 3585// text = text.Remove(text.IndexOf("\n"));
3524// m_log.DebugFormat( 3586// m_log.DebugFormat(
3525// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", 3587// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}",
3526// outPacket.ObjectData[i].ID, text, Name); 3588// outPacket.ObjectData[i].ID, text, Name);
3589 }
3590// else
3591// {
3592// m_log.WarnFormat(
3593// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name);
3594// }
3527 } 3595 }
3528 }
3529 3596
3530 OutPacket(outPacket, ThrottleOutPacketType.State); 3597 outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray();
3598
3599 OutPacket(outPacket, ThrottleOutPacketType.State);
3600 }
3531 } 3601 }
3532 3602
3533 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 3603 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
@@ -4063,10 +4133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4063 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); 4133 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4064 edata.CovenantID = covenant; 4134 edata.CovenantID = covenant;
4065 edata.CovenantTimestamp = 0; 4135 edata.CovenantTimestamp = 0;
4066 if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) 4136 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4067 edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
4068 else
4069 edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
4070 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); 4137 edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName);
4071 einfopack.Data = edata; 4138 einfopack.Data = edata;
4072 OutPacket(einfopack, ThrottleOutPacketType.Task); 4139 OutPacket(einfopack, ThrottleOutPacketType.Task);
@@ -4087,8 +4154,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4087 4154
4088 //Sending Estate Settings 4155 //Sending Estate Settings
4089 returnblock[0].Parameter = Utils.StringToBytes(estateName); 4156 returnblock[0].Parameter = Utils.StringToBytes(estateName);
4090 // TODO: remove this cruft once MasterAvatar is fully deprecated
4091 //
4092 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); 4157 returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString());
4093 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); 4158 returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString());
4094 4159
@@ -4686,6 +4751,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4686 AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); 4751 AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder);
4687 AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder); 4752 AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder);
4688 AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem); 4753 AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem);
4754 AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem);
4689 AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory); 4755 AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory);
4690 AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents); 4756 AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents);
4691 AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents); 4757 AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents);
@@ -4878,7 +4944,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4878 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 4944 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
4879 lastarg = arg; // save this set of arguments for nexttime 4945 lastarg = arg; // save this set of arguments for nexttime
4880 if (handlerAgentUpdate != null) 4946 if (handlerAgentUpdate != null)
4947 {
4948 OnPreAgentUpdate(this, arg);
4881 OnAgentUpdate(this, arg); 4949 OnAgentUpdate(this, arg);
4950 }
4882 4951
4883 handlerAgentUpdate = null; 4952 handlerAgentUpdate = null;
4884 } 4953 }
@@ -5517,6 +5586,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5517 // for the client session anyway, in order to protect ourselves against bad code in plugins 5586 // for the client session anyway, in order to protect ourselves against bad code in plugins
5518 try 5587 try
5519 { 5588 {
5589
5520 byte[] visualparams = new byte[appear.VisualParam.Length]; 5590 byte[] visualparams = new byte[appear.VisualParam.Length];
5521 for (int i = 0; i < appear.VisualParam.Length; i++) 5591 for (int i = 0; i < appear.VisualParam.Length; i++)
5522 visualparams[i] = appear.VisualParam[i].ParamValue; 5592 visualparams[i] = appear.VisualParam[i].ParamValue;
@@ -5727,10 +5797,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5727 5797
5728 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 5798 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
5729 { 5799 {
5730 GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 5800 GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
5731 if (handlerCompleteMovementToRegion != null) 5801 if (handlerCompleteMovementToRegion != null)
5732 { 5802 {
5733 handlerCompleteMovementToRegion(); 5803 handlerCompleteMovementToRegion(sender);
5734 } 5804 }
5735 handlerCompleteMovementToRegion = null; 5805 handlerCompleteMovementToRegion = null;
5736 5806
@@ -5958,7 +6028,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5958 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f) 6028 || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f)
5959 { 6029 {
5960 ScenePresence avatar = null; 6030 ScenePresence avatar = null;
5961 if (((Scene)m_scene).TryGetAvatar(AgentId, out avatar)) 6031 if (((Scene)m_scene).TryGetScenePresence(AgentId, out avatar))
5962 { 6032 {
5963 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f) 6033 if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f)
5964 { 6034 {
@@ -7001,6 +7071,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7001 return true; 7071 return true;
7002 } 7072 }
7003 7073
7074 /// <summary>
7075 /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request
7076 /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets
7077 /// </summary>
7078 /// <param name="sender"></param>
7079 /// <param name="Pack"></param>
7080 /// <returns>This parameter may be ignored since we appear to return true whatever happens</returns>
7004 private bool HandleTransferRequest(IClientAPI sender, Packet Pack) 7081 private bool HandleTransferRequest(IClientAPI sender, Packet Pack)
7005 { 7082 {
7006 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 7083 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
@@ -7011,37 +7088,95 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7011 // Has to be done here, because AssetCache can't do it 7088 // Has to be done here, because AssetCache can't do it
7012 // 7089 //
7013 UUID taskID = UUID.Zero; 7090 UUID taskID = UUID.Zero;
7014 if (transfer.TransferInfo.SourceType == 3) 7091 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7015 { 7092 {
7016 taskID = new UUID(transfer.TransferInfo.Params, 48); 7093 taskID = new UUID(transfer.TransferInfo.Params, 48);
7017 UUID itemID = new UUID(transfer.TransferInfo.Params, 64); 7094 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7018 UUID requestID = new UUID(transfer.TransferInfo.Params, 80); 7095 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7096
7097// m_log.DebugFormat(
7098// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7099// requestID, itemID, taskID, Name);
7100
7019 if (!(((Scene)m_scene).Permissions.BypassPermissions())) 7101 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7020 { 7102 {
7021 if (taskID != UUID.Zero) // Prim 7103 if (taskID != UUID.Zero) // Prim
7022 { 7104 {
7023 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); 7105 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7106
7024 if (part == null) 7107 if (part == null)
7108 {
7109 m_log.WarnFormat(
7110 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7111 Name, requestID, itemID, taskID);
7025 return true; 7112 return true;
7113 }
7026 7114
7027 if (part.OwnerID != AgentId) 7115 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7028 return true; 7116 if (tii == null)
7029 7117 {
7030 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 7118 m_log.WarnFormat(
7031 return true; 7119 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7032 7120 Name, requestID, itemID, taskID);
7033 TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID);
7034 if (ti == null)
7035 return true;
7036
7037 if (ti.OwnerID != AgentId)
7038 return true;
7039
7040 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7041 return true;
7042
7043 if (ti.AssetID != requestID)
7044 return true; 7121 return true;
7122 }
7123
7124 if (tii.Type == (int)AssetType.LSLText)
7125 {
7126 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
7127 return true;
7128 }
7129 else if (tii.Type == (int)AssetType.Notecard)
7130 {
7131 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7132 return true;
7133 }
7134 else
7135 {
7136 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7137 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7138 if (part.OwnerID != AgentId)
7139 {
7140 m_log.WarnFormat(
7141 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7142 Name, requestID, itemID, taskID, part.OwnerID);
7143 return true;
7144 }
7145
7146 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7147 {
7148 m_log.WarnFormat(
7149 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7150 Name, requestID, itemID, taskID);
7151 return true;
7152 }
7153
7154 if (tii.OwnerID != AgentId)
7155 {
7156 m_log.WarnFormat(
7157 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
7158 Name, requestID, itemID, taskID, tii.OwnerID);
7159 return true;
7160 }
7161
7162 if ((
7163 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7164 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
7165 {
7166 m_log.WarnFormat(
7167 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
7168 Name, requestID, itemID, taskID);
7169 return true;
7170 }
7171
7172 if (tii.AssetID != requestID)
7173 {
7174 m_log.WarnFormat(
7175 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
7176 Name, requestID, itemID, taskID, tii.AssetID);
7177 return true;
7178 }
7179 }
7045 } 7180 }
7046 else // Agent 7181 else // Agent
7047 { 7182 {
@@ -7050,7 +7185,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7050 assetRequestItem = invService.GetItem(assetRequestItem); 7185 assetRequestItem = invService.GetItem(assetRequestItem);
7051 if (assetRequestItem == null) 7186 if (assetRequestItem == null)
7052 { 7187 {
7053 assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); 7188 ILibraryService lib = m_scene.RequestModuleInterface<ILibraryService>();
7189 if (lib != null)
7190 assetRequestItem = lib.LibraryRootFolder.FindItem(itemID);
7054 if (assetRequestItem == null) 7191 if (assetRequestItem == null)
7055 return true; 7192 return true;
7056 } 7193 }
@@ -7059,7 +7196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7059 // only to notecards and scripts. All 7196 // only to notecards and scripts. All
7060 // other asset types are always available 7197 // other asset types are always available
7061 // 7198 //
7062 if (assetRequestItem.AssetType == 10) 7199 if (assetRequestItem.AssetType == (int)AssetType.LSLText)
7063 { 7200 {
7064 if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) 7201 if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId))
7065 { 7202 {
@@ -7067,7 +7204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7067 return true; 7204 return true;
7068 } 7205 }
7069 } 7206 }
7070 else if (assetRequestItem.AssetType == 7) 7207 else if (assetRequestItem.AssetType == (int)AssetType.Notecard)
7071 { 7208 {
7072 if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) 7209 if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId))
7073 { 7210 {
@@ -7077,7 +7214,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7077 } 7214 }
7078 7215
7079 if (assetRequestItem.AssetID != requestID) 7216 if (assetRequestItem.AssetID != requestID)
7217 {
7218 m_log.WarnFormat(
7219 "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}",
7220 Name, requestID, itemID, assetRequestItem.AssetID);
7080 return true; 7221 return true;
7222 }
7081 } 7223 }
7082 } 7224 }
7083 } 7225 }
@@ -7280,6 +7422,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7280 return true; 7422 return true;
7281 } 7423 }
7282 7424
7425 private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack)
7426 {
7427 LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack;
7428
7429 #region Packet Session and User Check
7430 if (m_checkPackets)
7431 {
7432 if (createLink.AgentData.SessionID != SessionId ||
7433 createLink.AgentData.AgentID != AgentId)
7434 return true;
7435 }
7436 #endregion
7437
7438 LinkInventoryItem linkInventoryItem = OnLinkInventoryItem;
7439
7440 if (linkInventoryItem != null)
7441 {
7442 linkInventoryItem(
7443 this,
7444 createLink.InventoryBlock.TransactionID,
7445 createLink.InventoryBlock.FolderID,
7446 createLink.InventoryBlock.CallbackID,
7447 Util.FieldToString(createLink.InventoryBlock.Description),
7448 Util.FieldToString(createLink.InventoryBlock.Name),
7449 createLink.InventoryBlock.InvType,
7450 createLink.InventoryBlock.Type,
7451 createLink.InventoryBlock.OldItemID);
7452 }
7453
7454 return true;
7455 }
7456
7283 private bool HandleFetchInventory(IClientAPI sender, Packet Pack) 7457 private bool HandleFetchInventory(IClientAPI sender, Packet Pack)
7284 { 7458 {
7285 if (OnFetchInventory != null) 7459 if (OnFetchInventory != null)
@@ -7624,12 +7798,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7624 newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; 7798 newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask;
7625 newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; 7799 newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask;
7626 newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; 7800 newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask;
7801
7802 // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something
7803 // different
7627 //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; 7804 //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned;
7628 newTaskItem.Type = updatetask.InventoryData.Type; 7805 newTaskItem.Type = updatetask.InventoryData.Type;
7629 newTaskItem.InvType = updatetask.InventoryData.InvType; 7806 newTaskItem.InvType = updatetask.InventoryData.InvType;
7630 newTaskItem.Flags = updatetask.InventoryData.Flags; 7807 newTaskItem.Flags = updatetask.InventoryData.Flags;
7631 //newTaskItem.SaleType=updatetask.InventoryData.SaleType; 7808 //newTaskItem.SaleType=updatetask.InventoryData.SaleType;
7632 //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; 7809 //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;
7633 newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); 7810 newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name);
7634 newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); 7811 newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description);
7635 newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; 7812 newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate;
@@ -7637,7 +7814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7637 newTaskItem, updatetask.UpdateData.LocalID); 7814 newTaskItem, updatetask.UpdateData.LocalID);
7638 } 7815 }
7639 } 7816 }
7640 } 7817 }
7641 7818
7642 return true; 7819 return true;
7643 } 7820 }
@@ -10940,7 +11117,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10940 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); 11117 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
10941 #endregion BinaryStats 11118 #endregion BinaryStats
10942 11119
10943 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); 11120 OutPacket(packet, throttlePacketType, true);
10944 } 11121 }
10945 11122
10946 /// <summary> 11123 /// <summary>
@@ -10953,6 +11130,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10953 /// handles splitting manually</param> 11130 /// handles splitting manually</param>
10954 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) 11131 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
10955 { 11132 {
11133 if (m_debugPacketLevel >= 255)
11134 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11135
10956 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); 11136 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
10957 } 11137 }
10958 11138
@@ -11019,17 +11199,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11019 } 11199 }
11020 11200
11021 /// <summary> 11201 /// <summary>
11202 /// This processes packets which have accumulated while the presence was still in the process of initialising.
11203 /// </summary>
11204 public void ProcessPendingPackets()
11205 {
11206 m_IsPresenceReady = true;
11207 if (m_pendingPackets == null)
11208 return;
11209 foreach (Packet p in m_pendingPackets)
11210 {
11211 ProcessInPacket(p);
11212 }
11213 m_pendingPackets.Clear();
11214 }
11215
11216 /// <summary>
11022 /// Entryway from the client to the simulator. All UDP packets from the client will end up here 11217 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11023 /// </summary> 11218 /// </summary>
11024 /// <param name="Pack">OpenMetaverse.packet</param> 11219 /// <param name="Pack">OpenMetaverse.packet</param>
11025 public void ProcessInPacket(Packet Pack) 11220 public void ProcessInPacket(Packet Pack)
11026 { 11221 {
11027// m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack); 11222 if (!m_IsPresenceReady)
11028 11223 {
11029 if (!ProcessPacketMethod(Pack)) 11224 if (m_pendingPackets == null)
11030 m_log.Warn("[CLIENT]: unhandled packet " + Pack); 11225 {
11226 m_pendingPackets = new List<Packet>();
11227 }
11228 m_pendingPackets.Add(Pack);
11229 }
11230 else
11231 {
11232 if (m_debugPacketLevel >= 255)
11233 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11234
11235 if (!ProcessPacketMethod(Pack))
11236 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11031 11237
11032 PacketPool.Instance.ReturnPacket(Pack); 11238 PacketPool.Instance.ReturnPacket(Pack);
11239 }
11033 } 11240 }
11034 11241
11035 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 11242 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -11247,17 +11454,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11247 return String.Empty; 11454 return String.Empty;
11248 } 11455 }
11249 11456
11250 public void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) 11457 /// <summary>
11458 /// Make an asset request to the asset service in response to a client request.
11459 /// </summary>
11460 /// <param name="transferRequest"></param>
11461 /// <param name="taskID"></param>
11462 protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID)
11251 { 11463 {
11252 UUID requestID = UUID.Zero; 11464 UUID requestID = UUID.Zero;
11253 if (transferRequest.TransferInfo.SourceType == 2) 11465 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11254 { 11466 {
11255 //direct asset request
11256 requestID = new UUID(transferRequest.TransferInfo.Params, 0); 11467 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11257 } 11468 }
11258 else if (transferRequest.TransferInfo.SourceType == 3) 11469 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11259 { 11470 {
11260 //inventory asset request
11261 requestID = new UUID(transferRequest.TransferInfo.Params, 80); 11471 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11262 //m_log.Debug("[XXX] inventory asset request " + requestID); 11472 //m_log.Debug("[XXX] inventory asset request " + requestID);
11263 //if (taskID == UUID.Zero) // Agent 11473 //if (taskID == UUID.Zero) // Agent
@@ -11270,29 +11480,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11270 // } 11480 // }
11271 } 11481 }
11272 11482
11273 //check to see if asset is in local cache, if not we need to request it from asset server. 11483// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11274 //m_log.Debug("asset request " + requestID);
11275 11484
11276 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11485 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11277
11278 } 11486 }
11279 11487
11488 /// <summary>
11489 /// When we get a reply back from the asset service in response to a client request, send back the data.
11490 /// </summary>
11491 /// <param name="id"></param>
11492 /// <param name="sender"></param>
11493 /// <param name="asset"></param>
11280 protected void AssetReceived(string id, Object sender, AssetBase asset) 11494 protected void AssetReceived(string id, Object sender, AssetBase asset)
11281 { 11495 {
11282 TransferRequestPacket transferRequest = (TransferRequestPacket)sender; 11496 TransferRequestPacket transferRequest = (TransferRequestPacket)sender;
11283 11497
11284 UUID requestID = UUID.Zero; 11498 UUID requestID = UUID.Zero;
11285 byte source = 2; 11499 byte source = (byte)SourceType.Asset;
11286 if ((transferRequest.TransferInfo.SourceType == 2) || (transferRequest.TransferInfo.SourceType == 2222)) 11500
11501 if ((transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11502 || (transferRequest.TransferInfo.SourceType == 2222))
11287 { 11503 {
11288 //direct asset request
11289 requestID = new UUID(transferRequest.TransferInfo.Params, 0); 11504 requestID = new UUID(transferRequest.TransferInfo.Params, 0);
11290 } 11505 }
11291 else if ((transferRequest.TransferInfo.SourceType == 3) || (transferRequest.TransferInfo.SourceType == 3333)) 11506 else if ((transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11507 || (transferRequest.TransferInfo.SourceType == 3333))
11292 { 11508 {
11293 //inventory asset request
11294 requestID = new UUID(transferRequest.TransferInfo.Params, 80); 11509 requestID = new UUID(transferRequest.TransferInfo.Params, 80);
11295 source = 3; 11510 source = (byte)SourceType.SimInventoryItem;
11296 //m_log.Debug("asset request " + requestID); 11511 //m_log.Debug("asset request " + requestID);
11297 } 11512 }
11298 11513
@@ -11305,9 +11520,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11305 if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer())) 11520 if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer()))
11306 { 11521 {
11307 m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id); 11522 m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id);
11308 if (transferRequest.TransferInfo.SourceType == 2) 11523 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
11309 transferRequest.TransferInfo.SourceType = 2222; // marker 11524 transferRequest.TransferInfo.SourceType = 2222; // marker
11310 else if (transferRequest.TransferInfo.SourceType == 3) 11525 else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
11311 transferRequest.TransferInfo.SourceType = 3333; // marker 11526 transferRequest.TransferInfo.SourceType = 3333; // marker
11312 11527
11313 m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived); 11528 m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived);
@@ -11322,7 +11537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11322 } 11537 }
11323 11538
11324 // Scripts cannot be retrieved by direct request 11539 // Scripts cannot be retrieved by direct request
11325 if (transferRequest.TransferInfo.SourceType == 2 && asset.Type == 10) 11540 if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10)
11326 return; 11541 return;
11327 11542
11328 // The asset is known to exist and is in our cache, so add it to the AssetRequests list 11543 // The asset is known to exist and is in our cache, so add it to the AssetRequests list
@@ -11348,6 +11563,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11348 const uint m_maxPacketSize = 600; 11563 const uint m_maxPacketSize = 600;
11349 int numPackets = 1; 11564 int numPackets = 1;
11350 11565
11566 if (data == null)
11567 return 0;
11568
11351 if (data.LongLength > m_maxPacketSize) 11569 if (data.LongLength > m_maxPacketSize)
11352 { 11570 {
11353 // over max number of bytes so split up file 11571 // over max number of bytes so split up file
@@ -11552,6 +11770,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11552 public PacketMethod method; 11770 public PacketMethod method;
11553 public bool Async; 11771 public bool Async;
11554 } 11772 }
11773
11555 public class AsyncPacketProcess 11774 public class AsyncPacketProcess
11556 { 11775 {
11557 public bool result = false; 11776 public bool result = false;
@@ -11593,5 +11812,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11593 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages); 11812 packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages);
11594 OutPacket(packet, ThrottleOutPacketType.Task); 11813 OutPacket(packet, ThrottleOutPacketType.Task);
11595 } 11814 }
11815
11816 public void SendChangeUserRights(UUID agentID, UUID friendID, int rights)
11817 {
11818 ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights);
11819
11820 packet.AgentData = new ChangeUserRightsPacket.AgentDataBlock();
11821 packet.AgentData.AgentID = agentID;
11822
11823 packet.Rights = new ChangeUserRightsPacket.RightsBlock[1];
11824 packet.Rights[0] = new ChangeUserRightsPacket.RightsBlock();
11825 packet.Rights[0].AgentRelated = friendID;
11826 packet.Rights[0].RelatedRights = rights;
11827
11828 OutPacket(packet, ThrottleOutPacketType.Task);
11829 }
11830
11831 public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId)
11832 {
11833 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
11834 dialog.Data.ObjectID = objectId;
11835 dialog.Data.ChatChannel = chatChannel;
11836 dialog.Data.ImageID = UUID.Zero;
11837 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
11838 // this is the username of the *owner*
11839 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
11840 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
11841 dialog.Data.Message = Util.StringToBytes256(message);
11842
11843
11844 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
11845 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
11846 buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!");
11847 dialog.Buttons = buttons;
11848 OutPacket(dialog, ThrottleOutPacketType.Task);
11849 }
11596 } 11850 }
11597} 11851}