From 429a84f390212d0f414a08420707fc90aca2a331 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Mon, 5 Oct 2009 17:38:14 -0700 Subject: Beginning work on the new LLUDP implementation --- OpenSim/Region/Application/OpenSimBase.cs | 2 +- OpenSim/Region/ClientStack/IClientNetworkServer.cs | 2 +- .../LindenUDP/ILLClientStackNetworkHandler.cs | 38 - .../ClientStack/LindenUDP/ILLPacketHandler.cs | 83 - OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | 6 +- .../Region/ClientStack/LindenUDP/LLClientView.cs | 12635 +++++++++---------- .../Region/ClientStack/LindenUDP/LLImageManager.cs | 2 +- .../ClientStack/LindenUDP/LLPacketHandler.cs | 7 +- .../Region/ClientStack/LindenUDP/LLPacketServer.cs | 4 +- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 1003 +- OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs | 5 + .../LindenUDP/Tests/PacketHandlerTests.cs | 2 +- .../LindenUDP/Tests/TestLLPacketServer.cs | 2 +- 13 files changed, 6639 insertions(+), 7152 deletions(-) delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 6e7a2a0..4592c31 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -675,7 +675,7 @@ namespace OpenSim if (foundClientServer) { - m_clientServers[clientServerElement].Server.Close(); + m_clientServers[clientServerElement].NetworkStop(); m_clientServers.RemoveAt(clientServerElement); } IScene scene; diff --git a/OpenSim/Region/ClientStack/IClientNetworkServer.cs b/OpenSim/Region/ClientStack/IClientNetworkServer.cs index a71ad4d..54a441b 100644 --- a/OpenSim/Region/ClientStack/IClientNetworkServer.cs +++ b/OpenSim/Region/ClientStack/IClientNetworkServer.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.ClientStack IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager authenticateClass); - Socket Server { get; } + void NetworkStop(); bool HandlesRegion(Location x); void AddScene(IScene x); diff --git a/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs deleted file mode 100644 index ee15171..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Net.Sockets; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public interface ILLClientStackNetworkHandler - { - void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode); // EndPoint packetSender); - void RemoveClientCircuit(uint circuitcode); - void RegisterPacketServer(LLPacketServer server); - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs deleted file mode 100644 index 31f9580..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); - public delegate void PacketDrop(Packet pack, Object id); - public delegate void QueueEmpty(ThrottleOutPacketType queue); - public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType); - - /// - /// Interface to a class that handles all the activity involved with maintaining the client circuit (handling acks, - /// resends, pings, etc.) - /// - public interface ILLPacketHandler : IDisposable - { - event PacketStats OnPacketStats; - event PacketDrop OnPacketDrop; - event QueueEmpty OnQueueEmpty; - SynchronizeClientHandler SynchronizeClient { set; } - - int PacketsReceived { get; } - int PacketsReceivedReported { get; } - uint ResendTimeout { get; set; } - bool ReliableIsImportant { get; set; } - int MaxReliableResends { get; set; } - - /// - /// Initial handling of a received packet. It will be processed later in ProcessInPacket() - /// - /// - void InPacket(Packet packet); - - /// - /// Take action depending on the type and contents of an received packet. - /// - /// - void ProcessInPacket(LLQueItem item); - - void ProcessOutPacket(LLQueItem item); - void OutPacket(Packet NewPack, - ThrottleOutPacketType throttlePacketType); - void OutPacket(Packet NewPack, - ThrottleOutPacketType throttlePacketType, Object id); - LLPacketQueue PacketQueue { get; } - void Flush(); - void Clear(); - ClientInfo GetClientInfo(); - void SetClientInfo(ClientInfo info); - void AddImportantPacket(PacketType type); - void RemoveImportantPacket(PacketType type); - int GetQueueCount(ThrottleOutPacketType queue); - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 19ad0b4..000f455 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs @@ -197,12 +197,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentPacket = StartPacket; } - if ((m_imageManager != null) && (m_imageManager.Client != null) && (m_imageManager.Client.PacketHandler != null)) - if (m_imageManager.Client.PacketHandler.GetQueueCount(ThrottleOutPacketType.Texture) == 0) + if (m_imageManager != null && m_imageManager.Client != null) + { + if (m_imageManager.Client.IsThrottleEmpty(ThrottleOutPacketType.Texture)) { //m_log.Debug("No textures queued, sending one packet to kickstart it"); SendPacket(m_imageManager.Client); } + } } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 0052729..31cd53f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -58,442 +58,120 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector { + // LLClientView Only + public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); + + /// Used to adjust Sun Orbit values so Linden based viewers properly position sun + private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients - /* static variables */ - public static SynchronizeClientHandler SynchronizeClient; - /* private variables */ + private readonly LLUDPServer m_udpServer; + private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; private readonly UUID m_secureSessionId = UUID.Zero; + private readonly UUID m_agentId; + private readonly uint m_circuitCode; + private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL + private readonly Dictionary m_defaultAnimations = new Dictionary(); + private readonly IGroupsModule m_GroupsModule; private int m_debugPacketLevel; - - //private readonly IAssetCache m_assetCache; private int m_cachedTextureSerial; private Timer m_clientPingTimer; - private Timer m_avatarTerseUpdateTimer; private List m_avatarTerseUpdates = new List(); - private Timer m_primTerseUpdateTimer; private List m_primTerseUpdates = new List(); private Timer m_primFullUpdateTimer; - private List m_primFullUpdates = - new List(); - + private List m_primFullUpdates = new List(); private bool m_clientBlocked; - private int m_probesWithNoIngressPackets; - - private readonly UUID m_agentId; - private readonly uint m_circuitCode; private int m_moneyBalance; - private readonly ILLPacketHandler m_PacketHandler; - private int m_animationSequenceNumber = 1; - - private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL - - private readonly Dictionary m_defaultAnimations = new Dictionary(); - private bool m_SendLogoutPacketWhenClosing = true; - private int m_inPacketsChecked; - - // Used to adjust Sun Orbit values so Linden based viewers properly position sun - private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; - - - /* protected variables */ - - protected static Dictionary PacketHandlers = - new Dictionary(); //Global/static handlers for all clients + private AgentUpdateArgs lastarg; + private bool m_IsActive = true; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers - protected IScene m_scene; - - protected LLPacketServer m_networkServer; - protected LLImageManager m_imageManager; - - /* public variables */ protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; protected Vector3 m_startpos; protected EndPoint m_userEndPoint; - protected EndPoint m_proxyEndPoint; protected UUID m_activeGroupID = UUID.Zero; protected string m_activeGroupName = String.Empty; protected ulong m_activeGroupPowers; protected Dictionary m_groupPowers = new Dictionary(); - protected int m_avatarTerseUpdateRate = 50; - protected int m_avatarTerseUpdatesPerPacket = 5; + protected int m_terrainCheckerCount; - // LL uses these limits, apparently. Compressed terse would be - // 23, but we don't have that yet - // + // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet protected int m_primTerseUpdatesPerPacket = 10; protected int m_primFullUpdatesPerPacket = 14; - protected int m_primTerseUpdateRate = 10; protected int m_primFullUpdateRate = 14; - protected int m_textureSendLimit = 20; protected int m_textureDataLimit = 10; - + protected int m_avatarTerseUpdateRate = 50; + protected int m_avatarTerseUpdatesPerPacket = 5; protected int m_packetMTU = 1400; - protected IAssetService m_assetService; - // LLClientView Only - public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); - - /* Instantiated Designated Event Delegates */ - //- used so we don't create new objects for each incoming packet and then toss it out later */ - - private GenericMessage handlerGenericMessage; - private RequestAvatarProperties handlerRequestAvatarProperties; //OnRequestAvatarProperties; - private UpdateAvatarProperties handlerUpdateAvatarProperties; // OnUpdateAvatarProperties; - private ChatMessage handlerChatFromClient; //OnChatFromClient; - private ChatMessage handlerChatFromClient2; //OnChatFromClient; - private ImprovedInstantMessage handlerInstantMessage; //OnInstantMessage; - private FriendActionDelegate handlerApproveFriendRequest; //OnApproveFriendRequest; - private FriendshipTermination handlerTerminateFriendship; //OnTerminateFriendship; - private RezObject handlerRezObject; //OnRezObject; - private DeRezObject handlerDeRezObject; //OnDeRezObject; - private ModifyTerrain handlerModifyTerrain; - private BakeTerrain handlerBakeTerrain; - private EstateChangeInfo handlerEstateChangeInfo; - private Action handlerRegionHandShakeReply; //OnRegionHandShakeReply; - private GenericCall2 handlerRequestWearables; //OnRequestWearables; - private Action handlerRequestAvatarsData; //OnRequestAvatarsData; - private SetAppearance handlerSetAppearance; //OnSetAppearance; - private AvatarNowWearing handlerAvatarNowWearing; //OnAvatarNowWearing; - private RezSingleAttachmentFromInv handlerRezSingleAttachment; //OnRezSingleAttachmentFromInv; - private RezMultipleAttachmentsFromInv handlerRezMultipleAttachments; //OnRezMultipleAttachmentsFromInv; - private UUIDNameRequest handlerDetachAttachmentIntoInv; // Detach attachment! - private ObjectAttach handlerObjectAttach; //OnObjectAttach; - private SetAlwaysRun handlerSetAlwaysRun; //OnSetAlwaysRun; - private GenericCall2 handlerCompleteMovementToRegion; //OnCompleteMovementToRegion; - private UpdateAgent handlerAgentUpdate; //OnAgentUpdate; - private StartAnim handlerStartAnim; - private StopAnim handlerStopAnim; - private AgentRequestSit handlerAgentRequestSit; //OnAgentRequestSit; - private AgentSit handlerAgentSit; //OnAgentSit; - private AvatarPickerRequest handlerAvatarPickerRequest; //OnAvatarPickerRequest; - private FetchInventory handlerAgentDataUpdateRequest; //OnAgentDataUpdateRequest; - private TeleportLocationRequest handlerSetStartLocationRequest; //OnSetStartLocationRequest; - private TeleportLandmarkRequest handlerTeleportLandmarkRequest; //OnTeleportLandmarkRequest; - private LinkObjects handlerLinkObjects; //OnLinkObjects; - private DelinkObjects handlerDelinkObjects; //OnDelinkObjects; - private AddNewPrim handlerAddPrim; //OnAddPrim; - private UpdateShape handlerUpdatePrimShape; //null; - private ObjectExtraParams handlerUpdateExtraParams; //OnUpdateExtraParams; - private ObjectDuplicate handlerObjectDuplicate; - private ObjectDuplicateOnRay handlerObjectDuplicateOnRay; - private ObjectRequest handlerObjectRequest; - private ObjectSelect handlerObjectSelect; - private ObjectDeselect handlerObjectDeselect; - private ObjectIncludeInSearch handlerObjectIncludeInSearch; - private UpdatePrimFlags handlerUpdatePrimFlags; //OnUpdatePrimFlags; - private UpdatePrimTexture handlerUpdatePrimTexture; - private GrabObject handlerGrabObject; //OnGrabObject; - private MoveObject handlerGrabUpdate; //OnGrabUpdate; - private DeGrabObject handlerDeGrabObject; //OnDeGrabObject; - private SpinStart handlerSpinStart; //OnSpinStart; - private SpinObject handlerSpinUpdate; //OnSpinUpdate; - private SpinStop handlerSpinStop; //OnSpinStop; - private GenericCall7 handlerObjectDescription; - private GenericCall7 handlerObjectName; - private GenericCall7 handlerObjectClickAction; - private GenericCall7 handlerObjectMaterial; - private ObjectPermissions handlerObjectPermissions; - private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily; //OnRequestObjectPropertiesFamily; - //private TextureRequest handlerTextureRequest; - private UDPAssetUploadRequest handlerAssetUploadRequest; //OnAssetUploadRequest; - private RequestXfer handlerRequestXfer; //OnRequestXfer; - private XferReceive handlerXferReceive; //OnXferReceive; - private ConfirmXfer handlerConfirmXfer; //OnConfirmXfer; - private AbortXfer handlerAbortXfer; - private CreateInventoryFolder handlerCreateInventoryFolder; //OnCreateNewInventoryFolder; - private UpdateInventoryFolder handlerUpdateInventoryFolder; - private MoveInventoryFolder handlerMoveInventoryFolder; - private CreateNewInventoryItem handlerCreateNewInventoryItem; //OnCreateNewInventoryItem; - private FetchInventory handlerFetchInventory; - private FetchInventoryDescendents handlerFetchInventoryDescendents; //OnFetchInventoryDescendents; - private PurgeInventoryDescendents handlerPurgeInventoryDescendents; //OnPurgeInventoryDescendents; - private UpdateInventoryItem handlerUpdateInventoryItem; - private CopyInventoryItem handlerCopyInventoryItem; - private MoveInventoryItem handlerMoveInventoryItem; - private RemoveInventoryItem handlerRemoveInventoryItem; - private RemoveInventoryFolder handlerRemoveInventoryFolder; - private RequestTaskInventory handlerRequestTaskInventory; //OnRequestTaskInventory; - private UpdateTaskInventory handlerUpdateTaskInventory; //OnUpdateTaskInventory; - private MoveTaskInventory handlerMoveTaskItem; - private RemoveTaskInventory handlerRemoveTaskItem; //OnRemoveTaskItem; - private RezScript handlerRezScript; //OnRezScript; - private RequestMapBlocks handlerRequestMapBlocks; //OnRequestMapBlocks; - private RequestMapName handlerMapNameRequest; //OnMapNameRequest; - private TeleportLocationRequest handlerTeleportLocationRequest; //OnTeleportLocationRequest; - private MoneyBalanceRequest handlerMoneyBalanceRequest; //OnMoneyBalanceRequest; - private UUIDNameRequest handlerNameRequest; - private ParcelAccessListRequest handlerParcelAccessListRequest; //OnParcelAccessListRequest; - private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest; //OnParcelAccessListUpdateRequest; - private ParcelPropertiesRequest handlerParcelPropertiesRequest; //OnParcelPropertiesRequest; - private ParcelDivideRequest handlerParcelDivideRequest; //OnParcelDivideRequest; - private ParcelJoinRequest handlerParcelJoinRequest; //OnParcelJoinRequest; - private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest; //OnParcelPropertiesUpdateRequest; - private ParcelSelectObjects handlerParcelSelectObjects; //OnParcelSelectObjects; - private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest; //OnParcelObjectOwnerRequest; - private ParcelAbandonRequest handlerParcelAbandonRequest; - private ParcelGodForceOwner handlerParcelGodForceOwner; - private ParcelReclaim handlerParcelReclaim; - private RequestTerrain handlerRequestTerrain; - private RequestTerrain handlerUploadTerrain; - private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest; - private RegionInfoRequest handlerRegionInfoRequest; //OnRegionInfoRequest; - private EstateCovenantRequest handlerEstateCovenantRequest; //OnEstateCovenantRequest; - private RequestGodlikePowers handlerReqGodlikePowers; //OnRequestGodlikePowers; - private GodKickUser handlerGodKickUser; //OnGodKickUser; - private ViewerEffectEventHandler handlerViewerEffect; //OnViewerEffect; - private Action handlerLogout; //OnLogout; - private MoneyTransferRequest handlerMoneyTransferRequest; //OnMoneyTransferRequest; - private ParcelBuy handlerParcelBuy; - private EconomyDataRequest handlerEconomoyDataRequest; - - private UpdateVector handlerUpdatePrimSinglePosition; //OnUpdatePrimSinglePosition; - private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation; //OnUpdatePrimSingleRotation; - private UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition; //OnUpdatePrimSingleRotation; - private UpdateVector handlerUpdatePrimScale; //OnUpdatePrimScale; - private UpdateVector handlerUpdatePrimGroupScale; //OnUpdateGroupScale; - private UpdateVector handlerUpdateVector; //OnUpdatePrimGroupPosition; - private UpdatePrimRotation handlerUpdatePrimRotation; //OnUpdatePrimGroupRotation; - // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; //OnUpdatePrimGroupMouseRotation; - // private RequestAsset handlerRequestAsset; // OnRequestAsset; - private UUIDNameRequest handlerTeleportHomeRequest; - - private RegionHandleRequest handlerRegionHandleRequest; // OnRegionHandleRequest - private ParcelInfoRequest handlerParcelInfoRequest; // OnParcelInfoRequest - - private ScriptAnswer handlerScriptAnswer; - private RequestPayPrice handlerRequestPayPrice; - private ObjectSaleInfo handlerObjectSaleInfo; - private ObjectBuy handlerObjectBuy; - //private BuyObjectInventory handlerBuyObjectInventory; - private ObjectDeselect handlerObjectDetach; - private ObjectDrop handlerObjectDrop; - private AgentSit handlerOnUndo; - - private ForceReleaseControls handlerForceReleaseControls; - - private GodLandStatRequest handlerLandStatRequest; - - private UUIDNameRequest handlerUUIDGroupNameRequest; - - private ParcelDeedToGroup handlerParcelDeedToGroup; - - private RequestObjectPropertiesFamily handlerObjectGroupRequest; - private ScriptReset handlerScriptReset; - private GetScriptRunning handlerGetScriptRunning; - private SetScriptRunning handlerSetScriptRunning; - private UpdateVector handlerAutoPilotGo; - //Gesture - private ActivateGesture handlerActivateGesture; - private DeactivateGesture handlerDeactivateGesture; - //Sound - private SoundTrigger handlerSoundTrigger; - private ObjectOwner handlerObjectOwner; - - private DirPlacesQuery handlerDirPlacesQuery; - private DirFindQuery handlerDirFindQuery; - private DirLandQuery handlerDirLandQuery; - private DirPopularQuery handlerDirPopularQuery; - private DirClassifiedQuery handlerDirClassifiedQuery; - private ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime; - - private MapItemRequest handlerMapItemRequest; - - private StartLure handlerStartLure; - private TeleportLureRequest handlerTeleportLureRequest; - - private NetworkStats handlerNetworkStatsUpdate; - - private ClassifiedInfoRequest handlerClassifiedInfoRequest; - private ClassifiedInfoUpdate handlerClassifiedInfoUpdate; - private ClassifiedDelete handlerClassifiedDelete; - private ClassifiedDelete handlerClassifiedGodDelete; - - private EventNotificationAddRequest handlerEventNotificationAddRequest; - private EventNotificationRemoveRequest handlerEventNotificationRemoveRequest; - private EventGodDelete handlerEventGodDelete; - - private ParcelDwellRequest handlerParcelDwellRequest; - - private UserInfoRequest handlerUserInfoRequest; - private UpdateUserInfo handlerUpdateUserInfo; - - private RetrieveInstantMessages handlerRetrieveInstantMessages; - - private PickDelete handlerPickDelete; - private PickGodDelete handlerPickGodDelete; - private PickInfoUpdate handlerPickInfoUpdate; - private AvatarNotesUpdate handlerAvatarNotesUpdate; - - private MuteListRequest handlerMuteListRequest; - - //private AvatarInterestUpdate handlerAvatarInterestUpdate; - - private PlacesQuery handlerPlacesQuery; - - private readonly IGroupsModule m_GroupsModule; - - private AgentUpdateArgs lastarg = null; - - //private TerrainUnacked handlerUnackedTerrain = null; - - //** - - /* Properties */ - - public UUID SecureSessionId - { - get { return m_secureSessionId; } - } - - public IScene Scene - { - get { return m_scene; } - } - - public UUID SessionId - { - get { return m_sessionId; } - } + #region Properties + public UUID SecureSessionId { get { return m_secureSessionId; } } + public IScene Scene { get { return m_scene; } } + public UUID SessionId { get { return m_sessionId; } } public Vector3 StartPos { get { return m_startpos; } set { m_startpos = value; } } - - public UUID AgentId - { - get { return m_agentId; } - } - - public UUID ActiveGroupId - { - get { return m_activeGroupID; } - } - - public string ActiveGroupName - { - get { return m_activeGroupName; } - } - - public ulong ActiveGroupPowers - { - get { return m_activeGroupPowers; } - } - - public bool IsGroupMember(UUID groupID) - { - return m_groupPowers.ContainsKey(groupID); - } - - public ulong GetGroupPowers(UUID groupID) - { - if (groupID == m_activeGroupID) - return m_activeGroupPowers; - - if (m_groupPowers.ContainsKey(groupID)) - return m_groupPowers[groupID]; - - return 0; - } - - /// - /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. - /// - public bool ChildAgentStatus() - { - return m_scene.PresenceChildStatus(AgentId); - } - + public UUID AgentId { get { return m_agentId; } } + public UUID ActiveGroupId { get { return m_activeGroupID; } } + public string ActiveGroupName { get { return m_activeGroupName; } } + public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } + public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } /// /// First name of the agent/avatar represented by the client /// - public string FirstName - { - get { return m_firstName; } - } - + public string FirstName { get { return m_firstName; } } /// /// Last name of the agent/avatar represented by the client /// - public string LastName - { - get { return m_lastName; } - } - + public string LastName { get { return m_lastName; } } /// /// Full name of the client (first name and last name) /// - public string Name - { - get { return FirstName + " " + LastName; } - } - - public uint CircuitCode - { - get { return m_circuitCode; } - } - - public int MoneyBalance - { - get { return m_moneyBalance; } - } - - public int NextAnimationSequenceNumber - { - get { return m_animationSequenceNumber++; } - } - - public ILLPacketHandler PacketHandler - { - get { return m_PacketHandler; } - } - - bool m_IsActive = true; - + public string Name { get { return FirstName + " " + LastName; } } + public uint CircuitCode { get { return m_circuitCode; } } + public int MoneyBalance { get { return m_moneyBalance; } } + public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } public bool IsActive { get { return m_IsActive; } set { m_IsActive = value; } } + public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } - public bool SendLogoutPacketWhenClosing - { - set { m_SendLogoutPacketWhenClosing = value; } - } - - /* METHODS */ + #endregion Properties /// /// Constructor /// - public LLClientView( - EndPoint remoteEP, IScene scene, LLPacketServer packServer, - AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP, - ClientStackUserSettings userSettings) + public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, + UUID agentId, UUID sessionId, uint circuitCode) { - // Should be called first? - RegisterInterfaces(); - + RegisterInterface(this); + RegisterInterface(this); + RegisterInterface(this); m_GroupsModule = scene.RequestModuleInterface(); + m_moneyBalance = 1000; m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); @@ -505,14 +183,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_assetService = m_scene.RequestModuleInterface(); - m_networkServer = packServer; + m_udpServer = udpServer; + m_udpClient = udpClient; m_agentId = agentId; m_sessionId = sessionId; m_circuitCode = circuitCode; m_userEndPoint = remoteEP; - m_proxyEndPoint = proxyEP; m_firstName = sessionInfo.LoginInfo.First; m_lastName = sessionInfo.LoginInfo.Last; @@ -528,40 +206,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // in it to process. It's an on-purpose threadlock though because // without it, the clientloop will suck up all sim resources. - m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings); - m_PacketHandler.SynchronizeClient = SynchronizeClient; - m_PacketHandler.OnPacketStats += PopulateStats; - m_PacketHandler.OnQueueEmpty += HandleQueueEmpty; - - if (scene.Config != null) - { - IConfig clientConfig = scene.Config.Configs["LLClient"]; - if (clientConfig != null) - { - m_PacketHandler.ReliableIsImportant = - clientConfig.GetBoolean("ReliableIsImportant", - false); - m_PacketHandler.MaxReliableResends = clientConfig.GetInt("MaxReliableResends", - m_PacketHandler.MaxReliableResends); - m_primTerseUpdatesPerPacket = clientConfig.GetInt("TerseUpdatesPerPacket", - m_primTerseUpdatesPerPacket); - m_primFullUpdatesPerPacket = clientConfig.GetInt("FullUpdatesPerPacket", - m_primFullUpdatesPerPacket); - - m_primTerseUpdateRate = clientConfig.GetInt("TerseUpdateRate", - m_primTerseUpdateRate); - m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate", - m_primFullUpdateRate); - - m_textureSendLimit = clientConfig.GetInt("TextureSendLimit", - m_textureSendLimit); - - m_textureDataLimit = clientConfig.GetInt("TextureDataLimit", - m_textureDataLimit); - - m_packetMTU = clientConfig.GetInt("PacketMTU", 1400); - } - } + //m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings); + //m_PacketHandler.SynchronizeClient = SynchronizeClient; + //m_PacketHandler.OnPacketStats += PopulateStats; + //m_PacketHandler.OnQueueEmpty += HandleQueueEmpty; RegisterLocalPacketHandlers(); m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); @@ -572,12 +220,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_debugPacketLevel = newDebugPacketLevel; } - # region Client Methods + #region Client Methods private void CloseCleanup(bool shutdownCircuit) { - - m_scene.RemoveClient(AgentId); //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); @@ -645,8 +291,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_imageManager != null) m_imageManager.Close(); - if (m_PacketHandler != null) - m_PacketHandler.Flush(); + if (m_udpServer != null) + m_udpServer.Flush(); // raise an event on the packet server to Shutdown the circuit // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup @@ -700,28 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdateTimer.Stop(); } - public void Restart() - { - // re-construct - m_PacketHandler.Clear(); - - m_clientPingTimer = new Timer(5000); - m_clientPingTimer.Elapsed += CheckClientConnectivity; - m_clientPingTimer.Enabled = true; - - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); - m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); - m_avatarTerseUpdateTimer.AutoReset = false; - - m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); - m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); - m_primTerseUpdateTimer.AutoReset = false; - - m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); - m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); - m_primFullUpdateTimer.AutoReset = false; - } - private void Terminate() { IsActive = false; @@ -730,9 +354,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_avatarTerseUpdateTimer.Close(); m_primTerseUpdateTimer.Close(); m_primFullUpdateTimer.Close(); - - m_PacketHandler.OnPacketStats -= PopulateStats; - m_PacketHandler.Dispose(); + + //m_udpServer.OnPacketStats -= PopulateStats; + m_udpClient.Shutdown(); // wait for thread stoped // m_clientThread.Join(); @@ -741,13 +365,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP //m_networkServer.CloseClient(this); } - #endregion + #endregion Client Methods - # region Packet Handling + #region Packet Handling public void PopulateStats(int inPackets, int outPackets, int unAckedBytes) { - handlerNetworkStatsUpdate = OnNetworkStatsUpdate; + NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate; if (handlerNetworkStatsUpdate != null) { handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes); @@ -856,86 +480,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); } - /// - /// Main packet processing loop for the UDP component of the client session. Both incoming and outgoing - /// packets are processed here. - /// - protected virtual void ClientLoop() - { - m_log.DebugFormat( - "[CLIENT]: Entered main packet processing loop for {0} in {1}", Name, Scene.RegionInfo.RegionName); - - while (IsActive) - { - LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue(); - - if (nextPacket == null) { - m_log.DebugFormat("[CLIENT]: PacketQueue return null LLQueItem"); - continue; - } - - if (nextPacket.Incoming) - { - if (m_debugPacketLevel > 0) - DebugPacket("IN", nextPacket.Packet); - m_PacketHandler.ProcessInPacket(nextPacket); - } - else - { - if (m_debugPacketLevel > 0) - DebugPacket("OUT", nextPacket.Packet); - m_PacketHandler.ProcessOutPacket(nextPacket); - } - } - } - - # endregion - - protected int m_terrainCheckerCount; - - /// - /// Event handler for check client timer - /// Checks to ensure that the client is still connected. If the client has failed to respond to many pings - /// in succession then close down the connection. - /// - /// - /// - protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) - { - if (m_PacketHandler.PacketsReceived == m_inPacketsChecked) - { - // no packet came in since the last time we checked... - - m_probesWithNoIngressPackets++; - if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) // agent active - || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) // agent paused - { - m_clientPingTimer.Enabled = false; - - m_log.WarnFormat( - "[CLIENT]: Client for agent {0} {1} has stopped responding to pings. Closing connection", - Name, AgentId); - - if (OnConnectionClosed != null) - { - OnConnectionClosed(this); - } - } - else - { - // this will normally trigger at least one packet (ping response) - SendStartPingCheck(0); - } - } - else - { - // Something received in the meantime - we can reset the counters - m_probesWithNoIngressPackets = 0; - // ... and store the current number of packets received to find out if another one got in on the next cycle - m_inPacketsChecked = m_PacketHandler.PacketsReceived; - } - - } + #endregion Packet Handling # region Setup @@ -947,11 +492,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); - // Ping the client regularly to check that it's still there - m_clientPingTimer = new Timer(5000); - m_clientPingTimer.Elapsed += CheckClientConnectivity; - m_clientPingTimer.Enabled = true; - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); m_avatarTerseUpdateTimer.AutoReset = false; @@ -981,7 +521,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Run a user session. This method lies at the base of the entire client thread. /// - protected virtual void RunUserSession() + protected void RunUserSession() { //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) //otherwise it will override this and use the system default @@ -991,7 +531,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // This sets up all the timers InitNewClient(); - ClientLoop(); } catch (Exception e) { @@ -1015,11 +554,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP + "Any further actions taken will not be processed.\n" + "Please relog", true); - LLQueItem item = new LLQueItem(); - item.Packet = packet; - item.Sequence = packet.Header.Sequence; - - m_PacketHandler.ProcessOutPacket(item); + m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false); // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to // listeners yet, though. @@ -1037,7 +572,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP # endregion - // Previously ClientView.API partial class + #region Events + public event GenericMessage OnGenericMessage; public event BinaryGenericMessage OnBinaryGenericMessage; public event Action OnLogout; @@ -1197,13 +733,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; - public event TerrainUnacked OnUnackedTerrain; - public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; public event ObjectOwner OnObjectOwner; - public event DirPlacesQuery OnDirPlacesQuery; public event DirFindQuery OnDirFindQuery; public event DirLandQuery OnDirLandQuery; @@ -1211,45 +744,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event DirClassifiedQuery OnDirClassifiedQuery; public event EventInfoRequest OnEventInfoRequest; public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; - public event MapItemRequest OnMapItemRequest; - public event OfferCallingCard OnOfferCallingCard; public event AcceptCallingCard OnAcceptCallingCard; public event DeclineCallingCard OnDeclineCallingCard; public event SoundTrigger OnSoundTrigger; - public event StartLure OnStartLure; public event TeleportLureRequest OnTeleportLureRequest; public event NetworkStats OnNetworkStatsUpdate; - public event ClassifiedInfoRequest OnClassifiedInfoRequest; public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; public event ClassifiedDelete OnClassifiedDelete; public event ClassifiedDelete OnClassifiedGodDelete; - public event EventNotificationAddRequest OnEventNotificationAddRequest; public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; public event EventGodDelete OnEventGodDelete; - public event ParcelDwellRequest OnParcelDwellRequest; - public event UserInfoRequest OnUserInfoRequest; public event UpdateUserInfo OnUpdateUserInfo; - public event RetrieveInstantMessages OnRetrieveInstantMessages; - public event PickDelete OnPickDelete; public event PickGodDelete OnPickGodDelete; public event PickInfoUpdate OnPickInfoUpdate; public event AvatarNotesUpdate OnAvatarNotesUpdate; - public event MuteListRequest OnMuteListRequest; - - //public event AvatarInterestUpdate OnAvatarInterestUpdate; - + public event AvatarInterestUpdate OnAvatarInterestUpdate; public event PlacesQuery OnPlacesQuery; + #endregion Events + public void ActivateGesture(UUID assetId, UUID gestureId) { } @@ -2768,7983 +2291,8017 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(avatarReply, ThrottleOutPacketType.Task); } - #endregion - - // Gesture + /// + /// Send the client an Estate message blue box pop-down with a single OK button + /// + /// + /// + /// + /// + public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) + { + if (!ChildAgentStatus()) + SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); - #region Appearance/ Wearables Methods + //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); + } - public void SendWearables(AvatarWearable[] wearables, int serial) + public void SendLogoutPacket() { - AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); - aw.AgentData.AgentID = AgentId; - aw.AgentData.SerialNum = (uint)serial; - aw.AgentData.SessionID = m_sessionId; + // I know this is a bit of a hack, however there are times when you don't + // want to send this, but still need to do the rest of the shutdown process + // this method gets called from the packet server.. which makes it practically + // impossible to do any other way. - // TODO: don't create new blocks if recycling an old packet - aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; - AgentWearablesUpdatePacket.WearableDataBlock awb; - for (int i = 0; i < wearables.Length; i++) + if (m_SendLogoutPacketWhenClosing) { - awb = new AgentWearablesUpdatePacket.WearableDataBlock(); - awb.WearableType = (byte)i; - awb.AssetID = wearables[i].AssetID; - awb.ItemID = wearables[i].ItemID; - aw.WearableData[i] = awb; + LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); + // TODO: don't create new blocks if recycling an old packet + logReply.AgentData.AgentID = AgentId; + logReply.AgentData.SessionID = SessionId; + logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; + logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); + logReply.InventoryData[0].ItemID = UUID.Zero; -// m_log.DebugFormat( -// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", -// awb.ItemID, awb.AssetID, i, Name); + OutPacket(logReply, ThrottleOutPacketType.Task); } - - OutPacket(aw, ThrottleOutPacketType.Task); } - public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) + public void SendHealth(float health) { - AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); - // TODO: don't create new blocks if recycling an old packet - avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; - avp.ObjectData.TextureEntry = textureEntry; + HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); + healthpacket.HealthData.Health = health; + OutPacket(healthpacket, ThrottleOutPacketType.Task); + } - AvatarAppearancePacket.VisualParamBlock avblock = null; - for (int i = 0; i < visualParams.Length; i++) + public void SendAgentOnline(UUID[] agentIDs) + { + OnlineNotificationPacket onp = new OnlineNotificationPacket(); + OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) { - avblock = new AvatarAppearancePacket.VisualParamBlock(); - avblock.ParamValue = visualParams[i]; - avp.VisualParam[i] = avblock; + OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + onpb[i] = onpbl; } - - avp.Sender.IsTrial = false; - avp.Sender.ID = agentID; - OutPacket(avp, ThrottleOutPacketType.Task); + onp.AgentBlock = onpb; + onp.Header.Reliable = true; + OutPacket(onp, ThrottleOutPacketType.Task); } - public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + public void SendAgentOffline(UUID[] agentIDs) { - //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); - - AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); - // TODO: don't create new blocks if recycling an old packet - ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; - ani.Sender = new AvatarAnimationPacket.SenderBlock(); - ani.Sender.ID = sourceAgentId; - ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; - ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; - - for (int i = 0; i < animations.Length; ++i) + OfflineNotificationPacket offp = new OfflineNotificationPacket(); + OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) { - ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); - ani.AnimationList[i].AnimID = animations[i]; - ani.AnimationList[i].AnimSequenceID = seqs[i]; - - ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); - ani.AnimationSourceList[i].ObjectID = objectIDs[i]; - if (objectIDs[i] == UUID.Zero) - ani.AnimationSourceList[i].ObjectID = sourceAgentId; + OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + offpb[i] = onpbl; } - ani.Header.Reliable = false; - OutPacket(ani, ThrottleOutPacketType.Task); + offp.AgentBlock = offpb; + offp.Header.Reliable = true; + OutPacket(offp, ThrottleOutPacketType.Task); } - #endregion - - #region Avatar Packet/data sending Methods - - /// - /// send a objectupdate packet with information about the clients avatar - /// - public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, - uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) + public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, + Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) { - ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - // TODO: don't create new blocks if recycling an old packet - objupdate.RegionData.RegionHandle = regionHandle; - objupdate.RegionData.TimeDilation = ushort.MaxValue; - objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); - - //give this avatar object a local id and assign the user a name - objupdate.ObjectData[0].ID = avatarLocalID; - objupdate.ObjectData[0].FullID = avatarID; - objupdate.ObjectData[0].ParentID = parentID; - objupdate.ObjectData[0].NameValue = - Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); - - Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); - byte[] pb = pos2.GetBytes(); - Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); - - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); + AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); + avatarSitResponse.SitObject.ID = TargetID; + if (CameraAtOffset != Vector3.Zero) + { + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; + } + avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; + avatarSitResponse.SitTransform.AutoPilot = autopilot; + avatarSitResponse.SitTransform.SitPosition = OffsetPos; + avatarSitResponse.SitTransform.SitRotation = SitOrientation; - objupdate.Header.Zerocoded = true; - OutPacket(objupdate, ThrottleOutPacketType.Task); + OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); } - /// - /// Send a terse positional/rotation/velocity update about an avatar - /// to the client. This avatar can be that of the client itself. - /// - public virtual void SendAvatarTerseUpdate(ulong regionHandle, - ushort timeDilation, uint localID, Vector3 position, - Vector3 velocity, Quaternion rotation, UUID agentid) + public void SendAdminResponse(UUID Token, uint AdminLevel) { - if (rotation.X == rotation.Y && - rotation.Y == rotation.Z && - rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; - - ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = - CreateAvatarImprovedBlock(localID, position, velocity,rotation); - - lock (m_avatarTerseUpdates) - { - m_avatarTerseUpdates.Add(terseBlock); + GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); + GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); + GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); - // If packet is full or own movement packet, send it. - if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) - { - ProcessAvatarTerseUpdates(this, null); - } - else if (m_avatarTerseUpdates.Count == 1) - { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Start(); - } - } + adb.AgentID = AgentId; + adb.SessionID = SessionId; // More security + gdb.GodLevel = (byte)AdminLevel; + gdb.Token = Token; + //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; + respondPacket.GrantData = gdb; + respondPacket.AgentData = adb; + OutPacket(respondPacket, ThrottleOutPacketType.Task); } - private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) + public void SendGroupMembership(GroupMembershipData[] GroupMembership) { - lock (m_avatarTerseUpdates) - { - ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - - terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); - - terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; - terse.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); - - int max = m_avatarTerseUpdatesPerPacket; - if (max > m_avatarTerseUpdates.Count) - max = m_avatarTerseUpdates.Count; - - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + m_groupPowers.Clear(); - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); + AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; - terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; + AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); + Group.AcceptNotices = GroupMembership[i].AcceptNotices; + Group.Contribution = GroupMembership[i].Contribution; + Group.GroupID = GroupMembership[i].GroupID; + Group.GroupInsigniaID = GroupMembership[i].GroupPicture; + Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); + Group.GroupPowers = GroupMembership[i].GroupPowers; + Groups[i] = Group; - for (int i = 0 ; i < count ; i++) - { - terse.ObjectData[i] = m_avatarTerseUpdates[0]; - m_avatarTerseUpdates.RemoveAt(0); - } - terse.Header.Reliable = false; - terse.Header.Zerocoded = true; - OutPacket(terse, ThrottleOutPacketType.Task); + } + Groupupdate.GroupData = Groups; + Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); + Groupupdate.AgentData.AgentID = AgentId; + OutPacket(Groupupdate, ThrottleOutPacketType.Task); - if (m_avatarTerseUpdates.Count == 0) + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Stop(); + eq.GroupMembership(Groupupdate, this.AgentId); } } - } - - public void SendCoarseLocationUpdate(List users, List CoarseLocations) - { - if (!IsActive) return; // We don't need to update inactive clients. - - CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); - // TODO: don't create new blocks if recycling an old packet - int total = CoarseLocations.Count; - CoarseLocationUpdatePacket.IndexBlock ib = - new CoarseLocationUpdatePacket.IndexBlock(); - loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; - loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; - - for (int i = 0; i < total; i++) + catch (Exception ex) { - CoarseLocationUpdatePacket.LocationBlock lb = - new CoarseLocationUpdatePacket.LocationBlock(); - lb.X = (byte)CoarseLocations[i].X; - lb.Y = (byte)CoarseLocations[i].Y; - - lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); - loc.Location[i] = lb; - loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); - loc.AgentData[i].AgentID = users[i]; + m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending group membership data via UDP"); + OutPacket(Groupupdate, ThrottleOutPacketType.Task); } - ib.You = -1; - ib.Prey = -1; - loc.Index = ib; - loc.Header.Reliable = false; - loc.Header.Zerocoded = true; - - OutPacket(loc, ThrottleOutPacketType.Task); } - #endregion - #region Primitive Packet/data Sending Methods - - /// - /// - /// - /// - /// - /// - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) + public void SendGroupNameReply(UUID groupLLUID, string GroupName) { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - - ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); - // TODO: don't create new blocks if recycling an old packet - attach.AgentData.AgentID = AgentId; - attach.AgentData.SessionID = m_sessionId; - attach.AgentData.AttachmentPoint = attachPoint; - attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; - attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); - attach.ObjectData[0].ObjectLocalID = localID; - attach.ObjectData[0].Rotation = rotation; - attach.Header.Zerocoded = true; - OutPacket(attach, ThrottleOutPacketType.Task); + UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); + UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; + UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); + uidnamebloc.ID = groupLLUID; + uidnamebloc.GroupName = Utils.StringToBytes(GroupName); + uidnameblock[0] = uidnamebloc; + pack.UUIDNameBlock = uidnameblock; + OutPacket(pack, ThrottleOutPacketType.Task); } - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, - uint flags, UUID objectID, UUID ownerID, string text, byte[] color, - uint parentID, byte[] particleSystem, byte clickAction, byte material) + public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) { - byte[] textureanim = new byte[0]; - - SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, - acc, rotation, rvel, flags, - objectID, ownerID, text, color, parentID, particleSystem, - clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); + LandStatReplyPacket lsrp = new LandStatReplyPacket(); + // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); + LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; + //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + // lsrepdb. + lsrp.RequestData.ReportType = reportType; + lsrp.RequestData.RequestFlags = requestFlags; + lsrp.RequestData.TotalObjectCount = resultCount; + for (int i = 0; i < lsrpia.Length; i++) + { + LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + lsrepdb.LocationX = lsrpia[i].LocationX; + lsrepdb.LocationY = lsrpia[i].LocationY; + lsrepdb.LocationZ = lsrpia[i].LocationZ; + lsrepdb.Score = lsrpia[i].Score; + lsrepdb.TaskID = lsrpia[i].TaskID; + lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; + lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); + lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); + lsrepdba[i] = lsrepdb; + } + lsrp.ReportData = lsrepdba; + OutPacket(lsrp, ThrottleOutPacketType.Task); } - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, - uint flags, - UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, - byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) + public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) { + ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); + scriptRunningReply.Script.ObjectID = objectID; + scriptRunningReply.Script.ItemID = itemID; + scriptRunningReply.Script.Running = running; - if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) - return; - - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; - - ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); - - objectData.ID = localID; - objectData.FullID = objectID; - objectData.OwnerID = ownerID; - - objectData.Text = LLUtil.StringToPacketBytes(text); - objectData.TextColor[0] = color[0]; - objectData.TextColor[1] = color[1]; - objectData.TextColor[2] = color[2]; - objectData.TextColor[3] = color[3]; - objectData.ParentID = parentID; - objectData.PSBlock = particleSystem; - objectData.ClickAction = clickAction; - objectData.Material = material; - objectData.Flags = 0; + OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); + } - if (attachment) + public void SendAsset(AssetRequestToClient req) + { + //m_log.Debug("sending asset " + req.RequestAssetID); + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + if (req.AssetRequestSource == 2) { - // Necessary??? - objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); - objectData.JointPivot = new Vector3(0, 0, 0); - - // Item from inventory??? - objectData.NameValue = - Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); - objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); + Transfer.TransferInfo.Params = new byte[20]; + Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + int assType = req.AssetInf.Type; + Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); + } + else if (req.AssetRequestSource == 3) + { + Transfer.TransferInfo.Params = req.Params; + // Transfer.TransferInfo.Params = new byte[100]; + //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); } + Transfer.TransferInfo.Size = req.AssetInf.Data.Length; + Transfer.TransferInfo.TransferID = req.TransferRequestID; + Transfer.Header.Zerocoded = true; + OutPacket(Transfer, ThrottleOutPacketType.Asset); - // Xantor 20080528: Send sound info as well - // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again - objectData.Sound = SoundId; - if (SoundId == UUID.Zero) + if (req.NumPackets == 1) { - objectData.OwnerID = UUID.Zero; - objectData.Gain = 0.0f; - objectData.Radius = 0.0f; - objectData.Flags = 0; + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + TransferPacket.TransferData.Data = req.AssetInf.Data; + TransferPacket.TransferData.Status = 1; + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); } else { - objectData.OwnerID = ownerID; - objectData.Gain = (float)SoundGain; - objectData.Radius = (float)SoundRadius; - objectData.Flags = SoundFlags; - } + int processedLength = 0; + int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; + int packetNumber = 0; - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); + while (processedLength < req.AssetInf.Data.Length) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = packetNumber; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; - byte[] vel = velocity.GetBytes(); - Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); + int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); + byte[] chunk = new byte[chunkSize]; + Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); + TransferPacket.TransferData.Data = chunk; - byte[] rvel = rotational_velocity.GetBytes(); - Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); + // 0 indicates more packets to come, 1 indicates last packet + if (req.AssetInf.Data.Length - processedLength > maxChunkSize) + { + TransferPacket.TransferData.Status = 0; + } + else + { + TransferPacket.TransferData.Status = 1; + } + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - if (textureanim.Length > 0) - { - objectData.TextureAnim = textureanim; + processedLength += chunkSize; + packetNumber++; + } } + } - lock (m_primFullUpdates) - { - if (m_primFullUpdates.Count == 0) - m_primFullUpdateTimer.Start(); + public void SendTexture(AssetBase TextureAsset) + { - m_primFullUpdates.Add(objectData); + } - if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - ProcessPrimFullUpdates(this, null); - } + public void SendRegionHandle(UUID regionID, ulong handle) + { + RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); + reply.ReplyBlock.RegionID = regionID; + reply.ReplyBlock.RegionHandle = handle; + OutPacket(reply, ThrottleOutPacketType.Land); } - void HandleQueueEmpty(ThrottleOutPacketType queue) + public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) { - switch (queue) + ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); + reply.AgentData.AgentID = m_agentId; + reply.Data.ParcelID = parcelID; + reply.Data.OwnerID = land.OwnerID; + reply.Data.Name = Utils.StringToBytes(land.Name); + reply.Data.Desc = Utils.StringToBytes(land.Description); + reply.Data.ActualArea = land.Area; + reply.Data.BillableArea = land.Area; // TODO: what is this? + + // Bit 0: Mature, bit 7: on sale, other bits: no idea + reply.Data.Flags = (byte)( + ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + + ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + + Vector3 pos = land.UserLocation; + if (pos.Equals(Vector3.Zero)) { - case ThrottleOutPacketType.Texture: - ProcessTextureRequests(); - break; + pos = (land.AABBMax + land.AABBMin) * 0.5f; } - } + reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; + reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; + reply.Data.GlobalZ = pos.Z; + reply.Data.SimName = Utils.StringToBytes(info.RegionName); + reply.Data.SnapshotID = land.SnapshotID; + reply.Data.Dwell = land.Dwell; + reply.Data.SalePrice = land.SalePrice; + reply.Data.AuctionID = (int)land.AuctionID; - void ProcessTextureRequests() - { - if (m_imageManager != null) - m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); + OutPacket(reply, ThrottleOutPacketType.Land); } - void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) + public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) { - lock (m_primFullUpdates) - { - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - - return; - } + ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); + packet.Data.ObjectName = Utils.StringToBytes(objName); + packet.Data.SimName = Utils.StringToBytes(simName); + packet.Data.SimPosition = pos; + packet.Data.LookAt = lookAt; - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + OutPacket(packet, ThrottleOutPacketType.Task); + } - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) + { + DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); - int count = 0; - int size = 0; + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primFullUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + packet.QueryReplies = + new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; - outPacket.ObjectData = - new ObjectUpdatePacket.ObjectDataBlock[count]; + packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ + data.Length]; - for (int index = 0 ; index < count ; index++) - { - outPacket.ObjectData[index] = m_primFullUpdates[0]; - m_primFullUpdates.RemoveAt(0); - } + packet.AgentData.AgentID = AgentId; - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + packet.QueryData[0].QueryID = queryID; - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); + int i = 0; + foreach (DirPlacesReplyData d in data) + { + packet.QueryReplies[i] = + new DirPlacesReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].Dwell = d.dwell; + packet.StatusData[i].Status = d.Status; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - /// - /// - /// - public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, - Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) + public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); - ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = - CreatePrimImprovedBlock(localID, position, rotation, - velocity, rotationalvelocity, state); + packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - lock (m_primTerseUpdates) - { - if (m_primTerseUpdates.Count == 0) - m_primTerseUpdateTimer.Start(); + packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - m_primTerseUpdates.Add(objectData); + packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ + data.Length]; - if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - ProcessPrimTerseUpdates(this, null); + int i = 0; + foreach (DirPeopleReplyData d in data) + { + packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].AgentID = d.agentID; + packet.QueryReplies[i].FirstName = + Utils.StringToBytes(d.firstName); + packet.QueryReplies[i].LastName = + Utils.StringToBytes(d.lastName); + packet.QueryReplies[i].Group = + Utils.StringToBytes(d.group); + packet.QueryReplies[i].Online = d.online; + packet.QueryReplies[i].Reputation = d.reputation; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) + public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) { - lock (m_primTerseUpdates) - { - if (m_primTerseUpdates.Count == 0) - { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); - return; - } + packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ + data.Length]; - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ + data.Length]; - int count = 0; - int size = 0; + int i = 0; + foreach (DirEventsReplyData d in data) + { + packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].OwnerID = d.ownerID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].EventID = d.eventID; + packet.QueryReplies[i].Date = + Utils.StringToBytes(d.date); + packet.QueryReplies[i].UnixTime = d.unixTime; + packet.QueryReplies[i].EventFlags = d.eventFlags; + packet.StatusData[i].Status = d.Status; + i++; + } - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + OutPacket(packet, ThrottleOutPacketType.Task); + } - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) + { + DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); - outPacket.ObjectData = - new ImprovedTerseObjectUpdatePacket. - ObjectDataBlock[count]; + packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - for (int index = 0 ; index < count ; index++) - { - outPacket.ObjectData[index] = m_primTerseUpdates[0]; - m_primTerseUpdates.RemoveAt(0); - } + packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - outPacket.Header.Reliable = false; - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ + data.Length]; - if (m_primTerseUpdates.Count == 0) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + int i = 0; + foreach (DirGroupsReplyData d in data) + { + packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].GroupID = d.groupID; + packet.QueryReplies[i].GroupName = + Utils.StringToBytes(d.groupName); + packet.QueryReplies[i].Members = d.members; + packet.QueryReplies[i].SearchOrder = d.searchOrder; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - public void FlushPrimUpdates() + public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) { - while (m_primFullUpdates.Count > 0) - { - ProcessPrimFullUpdates(this, null); - } - while (m_primTerseUpdates.Count > 0) - { - ProcessPrimTerseUpdates(this, null); - } - while (m_avatarTerseUpdates.Count > 0) + DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); + + packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ + data.Length]; + packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ + data.Length]; + + int i = 0; + foreach (DirClassifiedReplyData d in data) { - ProcessAvatarTerseUpdates(this, null); + packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ClassifiedID = d.classifiedID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; + packet.QueryReplies[i].CreationDate = d.creationDate; + packet.QueryReplies[i].ExpirationDate = d.expirationDate; + packet.QueryReplies[i].PriceForListing = d.price; + packet.StatusData[i].Status = d.Status; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) + public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) { - AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); - newPack.AssetBlock.Type = AssetType; - newPack.AssetBlock.Success = Success; - newPack.AssetBlock.UUID = AssetFullID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); - } + DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); - public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) - { - RequestXferPacket newPack = new RequestXferPacket(); - newPack.XferID.ID = XferID; - newPack.XferID.VFileType = AssetType; - newPack.XferID.VFileID = vFileID; - newPack.XferID.FilePath = FilePath; - newPack.XferID.Filename = FileName; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); - } + packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - public void SendConfirmXfer(ulong xferID, uint PacketID) - { - ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); - newPack.XferID.ID = xferID; - newPack.XferID.Packet = PacketID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ + data.Length]; + + int i = 0; + foreach (DirLandReplyData d in data) + { + packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].SalePrice = d.salePrice; + packet.QueryReplies[i].ActualArea = d.actualArea; + i++; + } + + OutPacket(packet, ThrottleOutPacketType.Task); } - - public void SendInitiateDownload(string simFileName, string clientFileName) + + public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) { - InitiateDownloadPacket newPack = new InitiateDownloadPacket(); - newPack.AgentData.AgentID = AgentId; - newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); - newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); - OutPacket(newPack, ThrottleOutPacketType.Asset); + DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); + + packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ + data.Length]; + + int i = 0; + foreach (DirPopularReplyData d in data) + { + packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Dwell = d.dwell; + i++; + } + + OutPacket(packet, ThrottleOutPacketType.Task); } - - public void SendImageFirstPart( - ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) + + public void SendEventInfoReply(EventData data) { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = numParts; - im.ImageID.ID = ImageUUID; + EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); - if (ImageSize > 0) - im.ImageID.Size = ImageSize; + packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - im.ImageData.Data = ImageData; - im.ImageID.Codec = imageCodec; - im.Header.Zerocoded = true; - OutPacket(im, ThrottleOutPacketType.Texture); + packet.EventData = new EventInfoReplyPacket.EventDataBlock(); + packet.EventData.EventID = data.eventID; + packet.EventData.Creator = Utils.StringToBytes(data.creator); + packet.EventData.Name = Utils.StringToBytes(data.name); + packet.EventData.Category = Utils.StringToBytes(data.category); + packet.EventData.Desc = Utils.StringToBytes(data.description); + packet.EventData.Date = Utils.StringToBytes(data.date); + packet.EventData.DateUTC = data.dateUTC; + packet.EventData.Duration = data.duration; + packet.EventData.Cover = data.cover; + packet.EventData.Amount = data.amount; + packet.EventData.SimName = Utils.StringToBytes(data.simName); + packet.EventData.GlobalPos = new Vector3d(data.globalPos); + packet.EventData.EventFlags = data.eventFlags; + + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) + public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = partNumber; - im.ImageID.ID = imageUuid; - im.ImageData.Data = imageData; + MapItemReplyPacket mirplk = new MapItemReplyPacket(); + mirplk.AgentData.AgentID = AgentId; + mirplk.RequestData.ItemType = mapitemtype; + mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; + for (int i = 0; i < replies.Length; i++) + { + MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); + mrdata.X = replies[i].x; + mrdata.Y = replies[i].y; + mrdata.ID = replies[i].id; + mrdata.Extra = replies[i].Extra; + mrdata.Extra2 = replies[i].Extra2; + mrdata.Name = Utils.StringToBytes(replies[i].name); + mirplk.Data[i] = mrdata; + } + //m_log.Debug(mirplk.ToString()); + OutPacket(mirplk, ThrottleOutPacketType.Task); - OutPacket(im, ThrottleOutPacketType.Texture); } - public void SendImageNotFound(UUID imageid) + public void SendOfferCallingCard(UUID srcID, UUID transactionID) { - ImageNotInDatabasePacket notFoundPacket - = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); + // a bit special, as this uses AgentID to store the source instead + // of the destination. The destination (the receiver) goes into destID + OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); + p.AgentData.AgentID = srcID; + p.AgentData.SessionID = UUID.Zero; + p.AgentBlock.DestID = AgentId; + p.AgentBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); + } - notFoundPacket.ImageID.ID = imageid; + public void SendAcceptCallingCard(UUID transactionID) + { + AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; + p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); + p.FolderData[0].FolderID = UUID.Zero; + OutPacket(p, ThrottleOutPacketType.Task); + } - OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); + public void SendDeclineCallingCard(UUID transactionID) + { + DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.TransactionBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendShutdownConnectionNotice() + public void SendTerminateFriend(UUID exFriendID) { - OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); + TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = SessionId; + p.ExBlock.OtherID = exFriendID; + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendSimStats(SimStats stats) + public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) { - SimStatsPacket pack = new SimStatsPacket(); - pack.Region = new SimStatsPacket.RegionBlock(); - pack.Region.RegionX = stats.RegionX; - pack.Region.RegionY = stats.RegionY; - pack.Region.RegionFlags = stats.RegionFlags; - pack.Region.ObjectCapacity = stats.ObjectCapacity; - //pack.Region = //stats.RegionBlock; - pack.Stat = stats.StatsBlock; + AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); - pack.Header.Reliable = false; + p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; + p.AgentData.AvatarID = avatarID; - OutPacket(pack, ThrottleOutPacketType.Task); + p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; + int i = 0; + foreach (GroupMembershipData m in data) + { + p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); + p.GroupData[i].GroupPowers = m.GroupPowers; + p.GroupData[i].AcceptNotices = m.AcceptNotices; + p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); + p.GroupData[i].GroupID = m.GroupID; + p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); + p.GroupData[i].GroupInsigniaID = m.GroupPicture; + i++; + } + + p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); + p.NewGroupData.ListInProfile = true; + + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, - uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, - uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, - UUID LastOwnerID, string ObjectName, string Description) + public void SendJoinGroupReply(UUID groupID, bool success) { - ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); - // TODO: don't create new blocks if recycling an old packet + JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); - ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); - objPropDB.RequestFlags = RequestFlags; - objPropDB.ObjectID = ObjectUUID; - if (OwnerID == GroupID) - objPropDB.OwnerID = UUID.Zero; - else - objPropDB.OwnerID = OwnerID; - objPropDB.GroupID = GroupID; - objPropDB.BaseMask = BaseMask; - objPropDB.OwnerMask = OwnerMask; - objPropDB.GroupMask = GroupMask; - objPropDB.EveryoneMask = EveryoneMask; - objPropDB.NextOwnerMask = NextOwnerMask; + p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - // TODO: More properties are needed in SceneObjectPart! - objPropDB.OwnershipCost = OwnershipCost; - objPropDB.SaleType = SaleType; - objPropDB.SalePrice = SalePrice; - objPropDB.Category = Category; - objPropDB.LastOwnerID = LastOwnerID; - objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); - objPropDB.Description = LLUtil.StringToPacketBytes(Description); - objPropFamilyPack.ObjectData = objPropDB; - objPropFamilyPack.Header.Zerocoded = true; - OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); + p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; + + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendObjectPropertiesReply( - UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, - UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, - UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, - string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, - uint BaseMask, byte saleType, int salePrice) + public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) { - ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); - // TODO: don't create new blocks if recycling an old packet + EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); - proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; - proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); - proper.ObjectData[0].ItemID = ItemID; - proper.ObjectData[0].CreationDate = CreationDate; - proper.ObjectData[0].CreatorID = CreatorUUID; - proper.ObjectData[0].FolderID = FolderUUID; - proper.ObjectData[0].FromTaskID = FromTaskUUID; - proper.ObjectData[0].GroupID = GroupUUID; - proper.ObjectData[0].InventorySerial = InventorySerial; + p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = agentID; - proper.ObjectData[0].LastOwnerID = LastOwnerUUID; - // proper.ObjectData[0].LastOwnerID = UUID.Zero; + p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; - proper.ObjectData[0].ObjectID = ObjectUUID; - if (OwnerUUID == GroupUUID) - proper.ObjectData[0].OwnerID = UUID.Zero; - else - proper.ObjectData[0].OwnerID = OwnerUUID; - proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); - proper.ObjectData[0].TextureID = TextureID; - proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); - proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); - proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); - proper.ObjectData[0].OwnerMask = OwnerMask; - proper.ObjectData[0].NextOwnerMask = NextOwnerMask; - proper.ObjectData[0].GroupMask = GroupMask; - proper.ObjectData[0].EveryoneMask = EveryoneMask; - proper.ObjectData[0].BaseMask = BaseMask; - // proper.ObjectData[0].AggregatePerms = 53; - // proper.ObjectData[0].AggregatePermTextures = 0; - // proper.ObjectData[0].AggregatePermTexturesOwner = 0; - proper.ObjectData[0].SaleType = saleType; - proper.ObjectData[0].SalePrice = salePrice; - proper.Header.Zerocoded = true; - OutPacket(proper, ThrottleOutPacketType.Task); + p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); + p.EjectData.Success = success; + + OutPacket(p, ThrottleOutPacketType.Task); } - #endregion + public void SendLeaveGroupReply(UUID groupID, bool success) + { + LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); - #region Estate Data Sending Methods + p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - private static bool convertParamStringToBool(byte[] field) - { - string s = Utils.BytesToString(field); - if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") - { - return true; - } - return false; + p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; + + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) + public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + if (classifiedID.Length != name.Length) + return; - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); - for (int i = 0; i < (6 + EstateManagers.Length); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; - for (int i = 0; i < EstateManagers.Length; i++) + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; + int i; + for (i = 0; i < classifiedID.Length; i++) { - returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; + ac.Data[i].ClassifiedID = classifiedID[i]; + ac.Data[i].Name = Utils.StringToBytes(name[i]); } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + + OutPacket(ac, ThrottleOutPacketType.Task); } - public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) + public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) { - ListBannedUsers = new List(); + ClassifiedInfoReplyPacket cr = + (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ClassifiedInfoReply); - for (int i = 0; i < bl.Length; i++) - { - if (bl[i] == null) - continue; - if (bl[i].BannedUserID == UUID.Zero) - continue; - BannedUsers.Add(bl[i].BannedUserID); - } + cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); + cr.AgentData.AgentID = AgentId; - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); + cr.Data.ClassifiedID = classifiedID; + cr.Data.CreatorID = creatorID; + cr.Data.CreationDate = creationDate; + cr.Data.ExpirationDate = expirationDate; + cr.Data.Category = category; + cr.Data.Name = Utils.StringToBytes(name); + cr.Data.Desc = Utils.StringToBytes(description); + cr.Data.ParcelID = parcelID; + cr.Data.ParentEstate = parentEstate; + cr.Data.SnapshotID = snapshotID; + cr.Data.SimName = Utils.StringToBytes(simName); + cr.Data.PosGlobal = new Vector3d(globalPos); + cr.Data.ParcelName = Utils.StringToBytes(parcelName); + cr.Data.ClassifiedFlags = classifiedFlags; + cr.Data.PriceForListing = price; - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + OutPacket(cr, ThrottleOutPacketType.Task); + } - for (int i = 0; i < (6 + BannedUsers.Count); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + public void SendAgentDropGroup(UUID groupID) + { + AgentDropGroupPacket dg = + (AgentDropGroupPacket)PacketPool.Instance.GetPacket( + PacketType.AgentDropGroup); - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); + dg.AgentData.AgentID = AgentId; + dg.AgentData.GroupID = groupID; - foreach (UUID banned in BannedUsers) - { - returnblock[j].Parameter = banned.GetBytes(); j++; - } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + OutPacket(dg, ThrottleOutPacketType.Task); } - public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) + public void SendAvatarNotesReply(UUID targetID, string text) { - RegionInfoPacket rinfopack = new RegionInfoPacket(); - RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; - rinfoblk.BillableFactor = args.billableFactor; - rinfoblk.EstateID = args.estateID; - rinfoblk.MaxAgents = args.maxAgents; - rinfoblk.ObjectBonusFactor = args.objectBonusFactor; - rinfoblk.ParentEstateID = args.parentEstateID; - rinfoblk.PricePerMeter = args.pricePerMeter; - rinfoblk.RedirectGridX = args.redirectGridX; - rinfoblk.RedirectGridY = args.redirectGridY; - rinfoblk.RegionFlags = args.regionFlags; - rinfoblk.SimAccess = args.simAccess; - rinfoblk.SunHour = args.sunHour; - rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; - rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; - rinfoblk.UseEstateSun = args.useEstateSun; - rinfoblk.WaterHeight = args.waterHeight; - rinfoblk.SimName = Utils.StringToBytes(args.simName); - - rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); - rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; - rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; - rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; - rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; - rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; + AvatarNotesReplyPacket an = + (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarNotesReply); - rinfopack.HasVariableBlocks = true; - rinfopack.RegionInfo = rinfoblk; - rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; + an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); + an.AgentData.AgentID = AgentId; + an.Data = new AvatarNotesReplyPacket.DataBlock(); + an.Data.TargetID = targetID; + an.Data.Notes = Utils.StringToBytes(text); - OutPacket(rinfopack, ThrottleOutPacketType.Task); + OutPacket(an, ThrottleOutPacketType.Task); } - public void SendEstateCovenantInformation(UUID covenant) + public void SendAvatarPicksReply(UUID targetID, Dictionary picks) { - EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); - EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); - edata.CovenantID = covenant; - edata.CovenantTimestamp = 0; - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); - einfopack.Data = edata; - OutPacket(einfopack, ThrottleOutPacketType.Task); - } + AvatarPicksReplyPacket ap = + (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarPicksReply); - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) - { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.MethodData.Invoice = invoice; - packet.AgentData.TransactionID = UUID.Random(); - packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; + ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); + ap.AgentData.AgentID = AgentId; + ap.AgentData.TargetID = targetID; - for (int i = 0; i < 10; i++) + ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; + + int i = 0; + foreach (KeyValuePair pick in picks) { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); + ap.Data[i].PickID = pick.Key; + ap.Data[i].PickName = Utils.StringToBytes(pick.Value); + i++; } - //Sending Estate Settings - returnblock[0].Parameter = Utils.StringToBytes(estateName); - // TODO: remove this cruft once MasterAvatar is fully deprecated - // - returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); - returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); + OutPacket(ap, ThrottleOutPacketType.Task); + } - returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); - returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); - returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); - returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); - returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? - returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? - returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); + public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + { + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); - packet.ParamList = returnblock; - packet.Header.Reliable = false; - //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); - OutPacket(packet, ThrottleOutPacketType.Task); - } + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; - #endregion + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; - #region Land Data Sending Methods + int i = 0; + foreach (KeyValuePair classified in classifieds) + { + ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); + ac.Data[i].ClassifiedID = classified.Key; + ac.Data[i].Name = Utils.StringToBytes(classified.Value); + i++; + } - public void SendLandParcelOverlay(byte[] data, int sequence_id) - { - ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); - packet.ParcelData.Data = data; - packet.ParcelData.SequenceID = sequence_id; - packet.Header.Zerocoded = true; - OutPacket(packet, ThrottleOutPacketType.Task); + OutPacket(ac, ThrottleOutPacketType.Task); } - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) { - ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); - // TODO: don't create new blocks if recycling an old packet + ParcelDwellReplyPacket pd = + (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ParcelDwellReply); - updatePacket.ParcelData.AABBMax = landData.AABBMax; - updatePacket.ParcelData.AABBMin = landData.AABBMin; - updatePacket.ParcelData.Area = landData.Area; - updatePacket.ParcelData.AuctionID = landData.AuctionID; - updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; + pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); + pd.AgentData.AgentID = AgentId; - updatePacket.ParcelData.Bitmap = landData.Bitmap; + pd.Data = new ParcelDwellReplyPacket.DataBlock(); + pd.Data.LocalID = localID; + pd.Data.ParcelID = parcelID; + pd.Data.Dwell = dwell; - updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); - updatePacket.ParcelData.Category = (byte)landData.Category; - updatePacket.ParcelData.ClaimDate = landData.ClaimDate; - updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; - updatePacket.ParcelData.GroupID = landData.GroupID; - updatePacket.ParcelData.GroupPrims = landData.GroupPrims; - updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; - updatePacket.ParcelData.LandingType = landData.LandingType; - updatePacket.ParcelData.LocalID = landData.LocalID; + OutPacket(pd, ThrottleOutPacketType.Land); + } - if (landData.Area > 0) - { - updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; - } - else - { - updatePacket.ParcelData.MaxPrims = 0; - } + public void SendUserInfoReply(bool imViaEmail, bool visible, string email) + { + UserInfoReplyPacket ur = + (UserInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.UserInfoReply); - updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; - updatePacket.ParcelData.MediaID = landData.MediaID; - updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); - updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); - updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); - updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; - updatePacket.ParcelData.OtherCount = 0; //unemplemented - updatePacket.ParcelData.OtherPrims = landData.OtherPrims; - updatePacket.ParcelData.OwnerID = landData.OwnerID; - updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; - updatePacket.ParcelData.ParcelFlags = landData.Flags; - updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; - updatePacket.ParcelData.PassHours = landData.PassHours; - updatePacket.ParcelData.PassPrice = landData.PassPrice; - updatePacket.ParcelData.PublicCount = 0; //unemplemented + string Visible = "hidden"; + if (visible) + Visible = "default"; - updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > - 0); - updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > - 0); - updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) > - 0); - updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) > - 0); + ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); + ur.AgentData.AgentID = AgentId; - updatePacket.ParcelData.RentPrice = 0; - updatePacket.ParcelData.RequestResult = request_result; - updatePacket.ParcelData.SalePrice = landData.SalePrice; - updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; - updatePacket.ParcelData.SelfCount = 0; //unemplemented - updatePacket.ParcelData.SequenceID = sequence_id; - if (landData.SimwideArea > 0) - { - updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; - } - else - { - updatePacket.ParcelData.SimWideMaxPrims = 0; - } - updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; - updatePacket.ParcelData.SnapSelection = snap_selection; - updatePacket.ParcelData.SnapshotID = landData.SnapshotID; - updatePacket.ParcelData.Status = (byte)landData.Status; - updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + - landData.SelectedPrims; - updatePacket.ParcelData.UserLocation = landData.UserLocation; - updatePacket.ParcelData.UserLookAt = landData.UserLookAt; - updatePacket.Header.Zerocoded = true; + ur.UserData = new UserInfoReplyPacket.UserDataBlock(); + ur.UserData.IMViaEMail = imViaEmail; + ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); + ur.UserData.EMail = Utils.StringToBytes(email); - try - { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - eq.ParcelProperties(updatePacket, this.AgentId); - } - } - catch (Exception ex) - { - m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending parcel data via UDP"); - OutPacket(updatePacket, ThrottleOutPacketType.Task); - } + OutPacket(ur, ThrottleOutPacketType.Task); } - public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) + public void SendCreateGroupReply(UUID groupID, bool success, string message) { - ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); - replyPacket.Data.AgentID = AgentId; - replyPacket.Data.Flags = accessFlag; - replyPacket.Data.LocalID = localLandID; - replyPacket.Data.SequenceID = 0; + CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); - List list = new List(); - foreach (UUID avatar in avatars) - { - ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); - block.Flags = accessFlag; - block.ID = avatar; - block.Time = 0; - list.Add(block); - } + createGroupReply.AgentData = + new CreateGroupReplyPacket.AgentDataBlock(); + createGroupReply.ReplyData = + new CreateGroupReplyPacket.ReplyDataBlock(); - replyPacket.List = list.ToArray(); - replyPacket.Header.Zerocoded = true; - OutPacket(replyPacket, ThrottleOutPacketType.Task); + createGroupReply.AgentData.AgentID = AgentId; + createGroupReply.ReplyData.GroupID = groupID; + + createGroupReply.ReplyData.Success = success; + createGroupReply.ReplyData.Message = Utils.StringToBytes(message); + OutPacket(createGroupReply, ThrottleOutPacketType.Task); } - public void SendForceClientSelectObjects(List ObjectIDs) + public void SendUseCachedMuteList() { - bool firstCall = true; - const int MAX_OBJECTS_PER_PACKET = 251; - ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); - ForceObjectSelectPacket.DataBlock[] data; - while (ObjectIDs.Count > 0) - { - if (firstCall) - { - pack._Header.ResetList = true; - firstCall = false; - } - else - { - pack._Header.ResetList = false; - } + UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); - if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) - { - data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; - } - else - { - data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; - } + useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); + useCachedMuteList.AgentData.AgentID = AgentId; - int i; - for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) - { - data[i] = new ForceObjectSelectPacket.DataBlock(); - data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); - ObjectIDs.RemoveAt(0); - } - pack.Data = data; - pack.Header.Zerocoded = true; - OutPacket(pack, ThrottleOutPacketType.Task); - } + OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); } - public void SendCameraConstraint(Vector4 ConstraintPlane) + public void SendMuteListUpdate(string filename) { - CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); - cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); - cpack.CameraCollidePlane.Plane = ConstraintPlane; - //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); - OutPacket(cpack, ThrottleOutPacketType.Task); + MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); + + muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); + muteListUpdate.MuteData.AgentID = AgentId; + muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); + + OutPacket(muteListUpdate, ThrottleOutPacketType.Task); } - public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) + public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) { - + PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); - int notifyCount = ownersAndCount.Count; - ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); + pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); + pickInfoReply.AgentData.AgentID = AgentId; - if (notifyCount > 0) - { - if (notifyCount > 32) - { - m_log.InfoFormat( - "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" - + " - a developer might want to investigate whether this is a hard limit", 32); - - notifyCount = 32; - } + pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); + pickInfoReply.Data.PickID = pickID; + pickInfoReply.Data.CreatorID = creatorID; + pickInfoReply.Data.TopPick = topPick; + pickInfoReply.Data.ParcelID = parcelID; + pickInfoReply.Data.Name = Utils.StringToBytes(name); + pickInfoReply.Data.Desc = Utils.StringToBytes(desc); + pickInfoReply.Data.SnapshotID = snapshotID; + pickInfoReply.Data.User = Utils.StringToBytes(user); + pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); + pickInfoReply.Data.SimName = Utils.StringToBytes(simName); + pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); + pickInfoReply.Data.SortOrder = sortOrder; + pickInfoReply.Data.Enabled = enabled; - ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock - = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; + OutPacket(pickInfoReply, ThrottleOutPacketType.Task); + } - int num = 0; - foreach (UUID owner in ownersAndCount.Keys) - { - dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); - dataBlock[num].Count = ownersAndCount[owner]; + #endregion Scene/Avatar to Client - if (land.GroupID == owner || groups.Contains(owner)) - dataBlock[num].IsGroupOwned = true; + // Gesture - dataBlock[num].OnlineStatus = true; //TODO: fix me later - dataBlock[num].OwnerID = owner; + #region Appearance/ Wearables Methods - num++; + public void SendWearables(AvatarWearable[] wearables, int serial) + { + AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); + aw.AgentData.AgentID = AgentId; + aw.AgentData.SerialNum = (uint)serial; + aw.AgentData.SessionID = m_sessionId; - if (num >= notifyCount) - { - break; - } - } + // TODO: don't create new blocks if recycling an old packet + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + for (int i = 0; i < wearables.Length; i++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = wearables[i].AssetID; + awb.ItemID = wearables[i].ItemID; + aw.WearableData[i] = awb; - pack.Data = dataBlock; +// m_log.DebugFormat( +// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", +// awb.ItemID, awb.AssetID, i, Name); } - pack.Header.Zerocoded = true; - this.OutPacket(pack, ThrottleOutPacketType.Task); - } - - #endregion - #region Helper Methods + OutPacket(aw, ThrottleOutPacketType.Task); + } - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, - Vector3 velocity, - Quaternion rotation) + public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { - byte[] bytes = new byte[60]; - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - - dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; + AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); + // TODO: don't create new blocks if recycling an old packet + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + avp.ObjectData.TextureEntry = textureEntry; - uint ID = localID; + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) + { + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; + } - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = 0; - bytes[i++] = 1; - i += 14; - bytes[i++] = 128; - bytes[i++] = 63; + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + OutPacket(avp, ThrottleOutPacketType.Task); + } - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; + public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + { + //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); - Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); + AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); + // TODO: don't create new blocks if recycling an old packet + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = sourceAgentId; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; + ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; - internDirec = internDirec / 128.0f; - internDirec.X += 1; - internDirec.Y += 1; - internDirec.Z += 1; + for (int i = 0; i < animations.Length; ++i) + { + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; - ushort InternVelocityX = (ushort)(32768 * internDirec.X); - ushort InternVelocityY = (ushort)(32768 * internDirec.Y); - ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); + ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[i].ObjectID = objectIDs[i]; + if (objectIDs[i] == UUID.Zero) + ani.AnimationSourceList[i].ObjectID = sourceAgentId; + } + ani.Header.Reliable = false; + OutPacket(ani, ThrottleOutPacketType.Task); + } - ushort ac = 32767; - bytes[i++] = (byte)(InternVelocityX % 256); - bytes[i++] = (byte)((InternVelocityX >> 8) % 256); - bytes[i++] = (byte)(InternVelocityY % 256); - bytes[i++] = (byte)((InternVelocityY >> 8) % 256); - bytes[i++] = (byte)(InternVelocityZ % 256); - bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); + #endregion - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + #region Avatar Packet/data sending Methods - //rotation - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + /// + /// send a objectupdate packet with information about the clients avatar + /// + public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, + uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) + { + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + objupdate.RegionData.RegionHandle = regionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatarLocalID; + objupdate.ObjectData[0].FullID = avatarID; + objupdate.ObjectData[0].ParentID = parentID; + objupdate.ObjectData[0].NameValue = + Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); - //rotation vel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); - dat.Data = bytes; + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); - return (dat); + objupdate.Header.Zerocoded = true; + OutPacket(objupdate, ThrottleOutPacketType.Task); } /// - /// + /// Send a terse positional/rotation/velocity update about an avatar + /// to the client. This avatar can be that of the client itself. /// - /// - /// - /// - /// - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, - Vector3 position, - Quaternion rotation, - Vector3 velocity, - Vector3 rotationalvelocity, - byte state) + public virtual void SendAvatarTerseUpdate(ulong regionHandle, + ushort timeDilation, uint localID, Vector3 position, + Vector3 velocity, Quaternion rotation, UUID agentid) { - uint ID = localID; - byte[] bytes = new byte[60]; - - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - dat.TextureEntry = new byte[0]; - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); - bytes[i++] = 0; + if (rotation.X == rotation.Y && + rotation.Y == rotation.Z && + rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - byte[] pb = position.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; - ushort ac = 32767; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = + CreateAvatarImprovedBlock(localID, position, velocity,rotation); + + lock (m_avatarTerseUpdates) + { + m_avatarTerseUpdates.Add(terseBlock); - ushort velx, vely, velz; - Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); + // If packet is full or own movement packet, send it. + if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) + { + ProcessAvatarTerseUpdates(this, null); + } + else if (m_avatarTerseUpdates.Count == 1) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Start(); + } + } + } - vel = vel / 128.0f; - vel.X += 1; - vel.Y += 1; - vel.Z += 1; - //vel - velx = (ushort)(32768 * (vel.X)); - vely = (ushort)(32768 * (vel.Y)); - velz = (ushort)(32768 * (vel.Z)); + private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) + { + lock (m_avatarTerseUpdates) + { + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - bytes[i++] = (byte)(velx % 256); - bytes[i++] = (byte)((velx >> 8) % 256); - bytes[i++] = (byte)(vely % 256); - bytes[i++] = (byte)((vely >> 8) % 256); - bytes[i++] = (byte)(velz % 256); - bytes[i++] = (byte)((velz >> 8) % 256); + terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; + terse.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + int max = m_avatarTerseUpdatesPerPacket; + if (max > m_avatarTerseUpdates.Count) + max = m_avatarTerseUpdates.Count; - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + int count = 0; + int size = 0; - //rotation vel - Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - rvel = rvel / 128.0f; - rvel.X += 1; - rvel.Y += 1; - rvel.Z += 1; - //vel - ushort rvelx = (ushort)(32768 * (rvel.X)); - ushort rvely = (ushort)(32768 * (rvel.Y)); - ushort rvelz = (ushort)(32768 * (rvel.Z)); + for (count = 0 ; count < max ; count++) + { + int length = 0; + m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } - bytes[i++] = (byte)(rvelx % 256); - bytes[i++] = (byte)((rvelx >> 8) % 256); - bytes[i++] = (byte)(rvely % 256); - bytes[i++] = (byte)((rvely >> 8) % 256); - bytes[i++] = (byte)(rvelz % 256); - bytes[i++] = (byte)((rvelz >> 8) % 256); - dat.Data = bytes; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; - return dat; + for (int i = 0 ; i < count ; i++) + { + terse.ObjectData[i] = m_avatarTerseUpdates[0]; + m_avatarTerseUpdates.RemoveAt(0); + } + + terse.Header.Reliable = false; + terse.Header.Zerocoded = true; + OutPacket(terse, ThrottleOutPacketType.Task); + + if (m_avatarTerseUpdates.Count == 0) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Stop(); + } + } } - /// - /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) - /// - /// - /// - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + public void SendCoarseLocationUpdate(List users, List CoarseLocations) { - ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); - SetDefaultPrimPacketValues(objupdate); - objupdate.UpdateFlags = flags; - SetPrimPacketShapeData(objupdate, primShape); + if (!IsActive) return; // We don't need to update inactive clients. - if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) + CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); + // TODO: don't create new blocks if recycling an old packet + int total = CoarseLocations.Count; + CoarseLocationUpdatePacket.IndexBlock ib = + new CoarseLocationUpdatePacket.IndexBlock(); + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; + + for (int i = 0; i < total; i++) { - objupdate.Data = new byte[1]; - objupdate.Data[0] = primShape.State; + CoarseLocationUpdatePacket.LocationBlock lb = + new CoarseLocationUpdatePacket.LocationBlock(); + lb.X = (byte)CoarseLocations[i].X; + lb.Y = (byte)CoarseLocations[i].Y; + + lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); + loc.Location[i] = lb; + loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); + loc.AgentData[i].AgentID = users[i]; } - return objupdate; - } + ib.You = -1; + ib.Prey = -1; + loc.Index = ib; + loc.Header.Reliable = false; + loc.Header.Zerocoded = true; - protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) - { - objectData.TextureEntry = primData.TextureEntry; - objectData.PCode = primData.PCode; - objectData.State = primData.State; - objectData.PathBegin = primData.PathBegin; - objectData.PathEnd = primData.PathEnd; - objectData.PathScaleX = primData.PathScaleX; - objectData.PathScaleY = primData.PathScaleY; - objectData.PathShearX = primData.PathShearX; - objectData.PathShearY = primData.PathShearY; - objectData.PathSkew = primData.PathSkew; - objectData.ProfileBegin = primData.ProfileBegin; - objectData.ProfileEnd = primData.ProfileEnd; - objectData.Scale = primData.Scale; - objectData.PathCurve = primData.PathCurve; - objectData.ProfileCurve = primData.ProfileCurve; - objectData.ProfileHollow = primData.ProfileHollow; - objectData.PathRadiusOffset = primData.PathRadiusOffset; - objectData.PathRevolutions = primData.PathRevolutions; - objectData.PathTaperX = primData.PathTaperX; - objectData.PathTaperY = primData.PathTaperY; - objectData.PathTwist = primData.PathTwist; - objectData.PathTwistBegin = primData.PathTwistBegin; - objectData.ExtraParams = primData.ExtraParams; + OutPacket(loc, ThrottleOutPacketType.Task); } - /// - /// Set some default values in a ObjectUpdatePacket - /// - /// - protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) - { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 3; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - objdata.State = 0; - objdata.Data = new byte[0]; + #endregion - objdata.ObjectData = new byte[60]; - objdata.ObjectData[46] = 128; - objdata.ObjectData[47] = 63; - } + #region Primitive Packet/data Sending Methods /// /// /// - /// - public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + /// + /// + /// + public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) { - ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); - // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - - SetDefaultAvatarPacketValues(ref objdata); - objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); - objdata.PathCurve = 16; - objdata.ProfileCurve = 1; - objdata.PathScaleX = 100; - objdata.PathScaleY = 100; - objdata.ParentID = 0; - objdata.OwnerID = UUID.Zero; - objdata.Scale = new Vector3(1, 1, 1); - objdata.PCode = (byte)PCode.Avatar; - if (textureEntry != null) - { - objdata.TextureEntry = textureEntry; - } - Vector3 pos = new Vector3(objdata.ObjectData, 16); - pos.X = 100f; - objdata.ID = 8880000; - objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); - //Vector3 pos2 = new Vector3(100f, 100f, 23f); - //objdata.FullID=user.AgentId; - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; - return objdata; + ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); + // TODO: don't create new blocks if recycling an old packet + attach.AgentData.AgentID = AgentId; + attach.AgentData.SessionID = m_sessionId; + attach.AgentData.AttachmentPoint = attachPoint; + attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; + attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); + attach.ObjectData[0].ObjectLocalID = localID; + attach.ObjectData[0].Rotation = rotation; + attach.Header.Zerocoded = true; + OutPacket(attach, ThrottleOutPacketType.Task); } - /// - /// - /// - /// - protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, + uint flags, UUID objectID, UUID ownerID, string text, byte[] color, + uint parentID, byte[] particleSystem, byte clickAction, byte material) { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 4; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); - objdata.TextureEntry = ntex.GetBytes(); + byte[] textureanim = new byte[0]; - objdata.State = 0; - objdata.Data = new byte[0]; - - objdata.ObjectData = new byte[76]; - objdata.ObjectData[15] = 128; - objdata.ObjectData[16] = 63; - objdata.ObjectData[56] = 128; - objdata.ObjectData[61] = 102; - objdata.ObjectData[62] = 40; - objdata.ObjectData[63] = 61; - objdata.ObjectData[64] = 189; + SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, + acc, rotation, rvel, flags, + objectID, ownerID, text, color, parentID, particleSystem, + clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); } - public void SendNameReply(UUID profileId, string firstname, string lastname) + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, + uint flags, + UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, + byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) { - UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); - // TODO: don't create new blocks if recycling an old packet - packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; - packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); - packet.UUIDNameBlock[0].ID = profileId; - packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); - packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); - OutPacket(packet, ThrottleOutPacketType.Task); - } + if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; + if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) + return; - #endregion + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - /// - /// This is a different way of processing packets then ProcessInPacket - /// - protected virtual void RegisterLocalPacketHandlers() - { - AddLocalPacketHandler(PacketType.LogoutRequest, Logout); - AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); - AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); - AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); - AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); - AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); - AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); - } + ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); - private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) - { - MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; - // validate the agent owns the agentID and sessionID - if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && - money.AgentData.SessionID == sender.SessionId) + objectData.ID = localID; + objectData.FullID = objectID; + objectData.OwnerID = ownerID; + + objectData.Text = LLUtil.StringToPacketBytes(text); + objectData.TextColor[0] = color[0]; + objectData.TextColor[1] = color[1]; + objectData.TextColor[2] = color[2]; + objectData.TextColor[3] = color[3]; + objectData.ParentID = parentID; + objectData.PSBlock = particleSystem; + objectData.ClickAction = clickAction; + objectData.Material = material; + objectData.Flags = 0; + + if (attachment) { - handlerMoneyTransferRequest = OnMoneyTransferRequest; - if (handlerMoneyTransferRequest != null) - { - handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, - money.MoneyData.Amount, money.MoneyData.TransactionType, - Util.FieldToString(money.MoneyData.Description)); - } + // Necessary??? + objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); + objectData.JointPivot = new Vector3(0, 0, 0); - return true; + // Item from inventory??? + objectData.NameValue = + Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); + objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); } - return false; + // Xantor 20080528: Send sound info as well + // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again + objectData.Sound = SoundId; + if (SoundId == UUID.Zero) + { + objectData.OwnerID = UUID.Zero; + objectData.Gain = 0.0f; + objectData.Radius = 0.0f; + objectData.Flags = 0; + } + else + { + objectData.OwnerID = ownerID; + objectData.Gain = (float)SoundGain; + objectData.Radius = (float)SoundRadius; + objectData.Flags = SoundFlags; + } + + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); + + byte[] vel = velocity.GetBytes(); + Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); + + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); + + byte[] rvel = rotational_velocity.GetBytes(); + Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); + + if (textureanim.Length > 0) + { + objectData.TextureAnim = textureanim; + } + + lock (m_primFullUpdates) + { + if (m_primFullUpdates.Count == 0) + m_primFullUpdateTimer.Start(); + + m_primFullUpdates.Add(objectData); + + if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) + ProcessPrimFullUpdates(this, null); + } } - private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) + void HandleQueueEmpty(ThrottleOutPacketType queue) { - ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; - if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) + switch (queue) { - handlerParcelBuy = OnParcelBuy; - if (handlerParcelBuy != null) - { - handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, - parcel.Data.IsGroupOwned, - parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, - parcel.ParcelData.Price, - false); - } - return true; + case ThrottleOutPacketType.Texture: + ProcessTextureRequests(); + break; } - return false; } - private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) + void ProcessTextureRequests() { - UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; - + if (m_imageManager != null) + m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); + } - for (int i = 0; i < upack.UUIDNameBlock.Length; i++) + void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) + { + lock (m_primFullUpdates) { - handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; - if (handlerUUIDGroupNameRequest != null) + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) { - handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + + return; } - } - return true; - } + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - public bool HandleGenericMessage(IClientAPI sender, Packet pack) - { - GenericMessagePacket gmpack = (GenericMessagePacket) pack; - if (m_genericPacketHandlers.Count == 0) return false; - if (gmpack.AgentData.SessionID != SessionId) return false; + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - handlerGenericMessage = null; + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; - string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); + int count = 0; + int size = 0; - if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) - { - List msg = new List(); - List msgBytes = new List(); + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - if (handlerGenericMessage != null) + for (count = 0 ; count < max ; count++) { - foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) - { - msg.Add(Util.FieldToString(block.Parameter)); - msgBytes.Add(block.Parameter); - } - try - { - if (OnBinaryGenericMessage != null) - { - OnBinaryGenericMessage(this, method, msgBytes.ToArray()); - } - handlerGenericMessage(sender, method, msg); - return true; - } - catch (Exception e) - { - m_log.Error("[GENERICMESSAGE] " + e); - } + int length = 0; + m_primFullUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; } - } - m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); - return false; - } - - public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) - { - ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; - if (ogpack.AgentData.SessionID != SessionId) return false; + outPacket.ObjectData = + new ObjectUpdatePacket.ObjectDataBlock[count]; - handlerObjectGroupRequest = OnObjectGroupRequest; - if (handlerObjectGroupRequest != null) - { - for (int i = 0; i < ogpack.ObjectData.Length; i++) + for (int index = 0 ; index < count ; index++) { - handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); + outPacket.ObjectData[index] = m_primFullUpdates[0]; + m_primFullUpdates.RemoveAt(0); } + + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task); + + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); } - return true; } - private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + /// + /// + /// + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, + Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) { - ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; - if (viewer.AgentData.SessionID != SessionId) return false; - handlerViewerEffect = OnViewerEffect; - if (handlerViewerEffect != null) + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; + + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; + + ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = + CreatePrimImprovedBlock(localID, position, rotation, + velocity, rotationalvelocity, state); + + lock (m_primTerseUpdates) { - int length = viewer.Effect.Length; - List args = new List(length); - for (int i = 0; i < length; i++) - { - //copy the effects block arguments into the event handler arg. - ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); - argument.AgentID = viewer.Effect[i].AgentID; - argument.Color = viewer.Effect[i].Color; - argument.Duration = viewer.Effect[i].Duration; - argument.ID = viewer.Effect[i].ID; - argument.Type = viewer.Effect[i].Type; - argument.TypeData = viewer.Effect[i].TypeData; - args.Add(argument); - } + if (m_primTerseUpdates.Count == 0) + m_primTerseUpdateTimer.Start(); - handlerViewerEffect(sender, args); - } + m_primTerseUpdates.Add(objectData); - return true; + if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) + ProcessPrimTerseUpdates(this, null); + } } - public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) + void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { - ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); - scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); - // TODO: don't create new blocks if recycling an old packet - scriptQuestion.Data.TaskID = taskID; - scriptQuestion.Data.ItemID = itemID; - scriptQuestion.Data.Questions = question; - scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); - scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); + lock (m_primTerseUpdates) + { + if (m_primTerseUpdates.Count == 0) + { + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); - OutPacket(scriptQuestion, ThrottleOutPacketType.Task); + return; + } + + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); + + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; + + int count = 0; + int size = 0; + + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + + for (count = 0 ; count < max ; count++) + { + int length = 0; + m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } + + outPacket.ObjectData = + new ImprovedTerseObjectUpdatePacket. + ObjectDataBlock[count]; + + for (int index = 0 ; index < count ; index++) + { + outPacket.ObjectData[index] = m_primTerseUpdates[0]; + m_primTerseUpdates.RemoveAt(0); + } + + outPacket.Header.Reliable = false; + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task); + + if (m_primTerseUpdates.Count == 0) + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); + } } - private void InitDefaultAnimations() + public void FlushPrimUpdates() { - using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) + while (m_primFullUpdates.Count > 0) { - XmlDocument doc = new XmlDocument(); - doc.Load(reader); - if (doc.DocumentElement != null) - foreach (XmlNode nod in doc.DocumentElement.ChildNodes) - { - if (nod.Attributes["name"] != null) - { - string name = nod.Attributes["name"].Value.ToLower(); - string id = nod.InnerText; - m_defaultAnimations.Add(name, (UUID)id); - } - } + ProcessPrimFullUpdates(this, null); + } + while (m_primTerseUpdates.Count > 0) + { + ProcessPrimTerseUpdates(this, null); + } + while (m_avatarTerseUpdates.Count > 0) + { + ProcessAvatarTerseUpdates(this, null); } } - public UUID GetDefaultAnimation(string name) + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) { - if (m_defaultAnimations.ContainsKey(name)) - return m_defaultAnimations[name]; - return UUID.Zero; + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = AssetType; + newPack.AssetBlock.Success = Success; + newPack.AssetBlock.UUID = AssetFullID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - /// - /// Handler called when we receive a logout packet. - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client, Packet packet) + public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) { - if (packet.Type == PacketType.LogoutRequest) - { - if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; - } - - return Logout(client); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = AssetType; + newPack.XferID.VFileID = vFileID; + newPack.XferID.FilePath = FilePath; + newPack.XferID.Filename = FileName; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - /// - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client) + public void SendConfirmXfer(ulong xferID, uint PacketID) { - m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); - - handlerLogout = OnLogout; + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = PacketID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + public void SendInitiateDownload(string simFileName, string clientFileName) + { + InitiateDownloadPacket newPack = new InitiateDownloadPacket(); + newPack.AgentData.AgentID = AgentId; + newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); + newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); + OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + public void SendImageFirstPart( + ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = numParts; + im.ImageID.ID = ImageUUID; - if (handlerLogout != null) - { - handlerLogout(client); - } + if (ImageSize > 0) + im.ImageID.Size = ImageSize; - return true; + im.ImageData.Data = ImageData; + im.ImageID.Codec = imageCodec; + im.Header.Zerocoded = true; + OutPacket(im, ThrottleOutPacketType.Texture); } - /// - /// Send a response back to a client when it asks the asset server (via the region server) if it has - /// its appearance texture cached. - /// - /// At the moment, we always reply that there is no cached texture. - /// - /// - /// - /// - protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) { - //m_log.Debug("texture cached: " + packet.ToString()); - AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; - AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = partNumber; + im.ImageID.ID = imageUuid; + im.ImageData.Data = imageData; - if (cachedtex.AgentData.SessionID != SessionId) return false; + OutPacket(im, ThrottleOutPacketType.Texture); + } - // TODO: don't create new blocks if recycling an old packet - cachedresp.AgentData.AgentID = AgentId; - cachedresp.AgentData.SessionID = m_sessionId; - cachedresp.AgentData.SerialNum = m_cachedTextureSerial; - m_cachedTextureSerial++; - cachedresp.WearableData = - new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; + public void SendImageNotFound(UUID imageid) + { + ImageNotInDatabasePacket notFoundPacket + = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); - for (int i = 0; i < cachedtex.WearableData.Length; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - cachedresp.WearableData[i].HostName = new byte[0]; - } + notFoundPacket.ImageID.ID = imageid; - cachedresp.Header.Zerocoded = true; - OutPacket(cachedresp, ThrottleOutPacketType.Task); - - return true; + OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); } - protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + public void SendShutdownConnectionNotice() { - MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); - Scene tScene = (Scene)m_scene; - - for (int i = 0; i < multipleupdate.ObjectData.Length; i++) - { - MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; + OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); + } - // Can't act on Null Data - if (block.Data != null) - { - uint localId = block.ObjectLocalID; - SceneObjectPart part = tScene.GetSceneObjectPart(localId); + public void SendSimStats(SimStats stats) + { + SimStatsPacket pack = new SimStatsPacket(); + pack.Region = new SimStatsPacket.RegionBlock(); + pack.Region.RegionX = stats.RegionX; + pack.Region.RegionY = stats.RegionY; + pack.Region.RegionFlags = stats.RegionFlags; + pack.Region.ObjectCapacity = stats.ObjectCapacity; + //pack.Region = //stats.RegionBlock; + pack.Stat = stats.StatsBlock; - if (part == null) - { - // It's a ghost! tell the client to delete it from view. - simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); - } - else - { - // UUID partId = part.UUID; - UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; + pack.Header.Reliable = false; - switch (block.Type) - { - case 1: - Vector3 pos1 = new Vector3(block.Data, 0); + OutPacket(pack, ThrottleOutPacketType.Task); + } - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - handlerUpdatePrimSinglePosition(localId, pos1, this); - } - break; - case 2: - Quaternion rot1 = new Quaternion(block.Data, 0, true); + public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, + uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, + uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, + UUID LastOwnerID, string ObjectName, string Description) + { + ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); + // TODO: don't create new blocks if recycling an old packet - handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; - if (handlerUpdatePrimSingleRotation != null) - { - // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); - handlerUpdatePrimSingleRotation(localId, rot1, this); - } - break; - case 3: - Vector3 rotPos = new Vector3(block.Data, 0); - Quaternion rot2 = new Quaternion(block.Data, 12, true); + ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); + objPropDB.RequestFlags = RequestFlags; + objPropDB.ObjectID = ObjectUUID; + if (OwnerID == GroupID) + objPropDB.OwnerID = UUID.Zero; + else + objPropDB.OwnerID = OwnerID; + objPropDB.GroupID = GroupID; + objPropDB.BaseMask = BaseMask; + objPropDB.OwnerMask = OwnerMask; + objPropDB.GroupMask = GroupMask; + objPropDB.EveryoneMask = EveryoneMask; + objPropDB.NextOwnerMask = NextOwnerMask; - handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; - if (handlerUpdatePrimSingleRotationPosition != null) - { - // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); - // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); - handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); - } - break; - case 4: - case 20: - Vector3 scale4 = new Vector3(block.Data, 0); + // TODO: More properties are needed in SceneObjectPart! + objPropDB.OwnershipCost = OwnershipCost; + objPropDB.SaleType = SaleType; + objPropDB.SalePrice = SalePrice; + objPropDB.Category = Category; + objPropDB.LastOwnerID = LastOwnerID; + objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); + objPropDB.Description = LLUtil.StringToPacketBytes(Description); + objPropFamilyPack.ObjectData = objPropDB; + objPropFamilyPack.Header.Zerocoded = true; + OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); + } - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { -// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); - handlerUpdatePrimScale(localId, scale4, this); - } - break; - case 5: + public void SendObjectPropertiesReply( + UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, + UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, + UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, + string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, + uint BaseMask, byte saleType, int salePrice) + { + ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + // TODO: don't create new blocks if recycling an old packet - Vector3 scale1 = new Vector3(block.Data, 12); - Vector3 pos11 = new Vector3(block.Data, 0); + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; + proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); + proper.ObjectData[0].ItemID = ItemID; + proper.ObjectData[0].CreationDate = CreationDate; + proper.ObjectData[0].CreatorID = CreatorUUID; + proper.ObjectData[0].FolderID = FolderUUID; + proper.ObjectData[0].FromTaskID = FromTaskUUID; + proper.ObjectData[0].GroupID = GroupUUID; + proper.ObjectData[0].InventorySerial = InventorySerial; - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale1, this); + proper.ObjectData[0].LastOwnerID = LastOwnerUUID; + // proper.ObjectData[0].LastOwnerID = UUID.Zero; - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos11, this); - } - } - break; - case 9: - Vector3 pos2 = new Vector3(block.Data, 0); + proper.ObjectData[0].ObjectID = ObjectUUID; + if (OwnerUUID == GroupUUID) + proper.ObjectData[0].OwnerID = UUID.Zero; + else + proper.ObjectData[0].OwnerID = OwnerUUID; + proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); + proper.ObjectData[0].TextureID = TextureID; + proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); + proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); + proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); + proper.ObjectData[0].OwnerMask = OwnerMask; + proper.ObjectData[0].NextOwnerMask = NextOwnerMask; + proper.ObjectData[0].GroupMask = GroupMask; + proper.ObjectData[0].EveryoneMask = EveryoneMask; + proper.ObjectData[0].BaseMask = BaseMask; + // proper.ObjectData[0].AggregatePerms = 53; + // proper.ObjectData[0].AggregatePermTextures = 0; + // proper.ObjectData[0].AggregatePermTexturesOwner = 0; + proper.ObjectData[0].SaleType = saleType; + proper.ObjectData[0].SalePrice = salePrice; + proper.Header.Zerocoded = true; + OutPacket(proper, ThrottleOutPacketType.Task); + } - handlerUpdateVector = OnUpdatePrimGroupPosition; + #endregion - if (handlerUpdateVector != null) - { + #region Estate Data Sending Methods - handlerUpdateVector(localId, pos2, this); - } - break; - case 10: - Quaternion rot3 = new Quaternion(block.Data, 0, true); + private static bool convertParamStringToBool(byte[] field) + { + string s = Utils.BytesToString(field); + if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") + { + return true; + } + return false; + } - handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - { - // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); - handlerUpdatePrimRotation(localId, rot3, this); - } - break; - case 11: - Vector3 pos3 = new Vector3(block.Data, 0); - Quaternion rot4 = new Quaternion(block.Data, 12, true); + public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) + { + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; - if (handlerUpdatePrimGroupRotation != null) - { - // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); - handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); - } - break; - case 12: - case 28: - Vector3 scale7 = new Vector3(block.Data, 0); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { -// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); - handlerUpdatePrimGroupScale(localId, scale7, this); - } - break; - case 13: - Vector3 scale2 = new Vector3(block.Data, 12); - Vector3 pos4 = new Vector3(block.Data, 0); + for (int i = 0; i < (6 + EstateManagers.Length); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale2, this); + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; + for (int i = 0; i < EstateManagers.Length; i++) + { + returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); + } - // Change the position based on scale (for bug number 246) - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos4, this); - } - } - break; - case 29: - Vector3 scale5 = new Vector3(block.Data, 12); - Vector3 pos5 = new Vector3(block.Data, 0); - - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimGroupScale(localId, scale5, this); - handlerUpdateVector = OnUpdatePrimGroupPosition; - - if (handlerUpdateVector != null) - { - handlerUpdateVector(localId, pos5, this); - } - } - break; - case 21: - Vector3 scale6 = new Vector3(block.Data, 12); - Vector3 pos6 = new Vector3(block.Data, 0); + public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) + { + ListBannedUsers = new List(); - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale6, this); - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos6, this); - } - } - break; - default: - m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); - break; - } - } - } + for (int i = 0; i < bl.Length; i++) + { + if (bl[i] == null) + continue; + if (bl[i].BannedUserID == UUID.Zero) + continue; + BannedUsers.Add(bl[i].BannedUserID); } - return true; - } - public void RequestMapLayer() - { - //should be getting the map layer from the grid server - //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) - MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); - // TODO: don't create new blocks if recycling an old packet - mapReply.AgentData.AgentID = AgentId; - mapReply.AgentData.Flags = 0; - mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; - mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); - mapReply.LayerData[0].Bottom = 0; - mapReply.LayerData[0].Left = 0; - mapReply.LayerData[0].Top = 30000; - mapReply.LayerData[0].Right = 30000; - mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); - mapReply.Header.Zerocoded = true; - OutPacket(mapReply, ThrottleOutPacketType.Land); - } + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) - { - /* - IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); - MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); - mbReply.AgentData.AgentId = AgentId; - int len; - if (simMapProfiles == null) - len = 0; - else - len = simMapProfiles.Count; + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; - mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; - int iii; - for (iii = 0; iii < len; iii++) + for (int i = 0; i < (6 + BannedUsers.Count); i++) { - Hashtable mp = (Hashtable)simMapProfiles[iii]; - mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); - mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); - mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); - mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); - mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); - mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); - mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); - mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); - mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); } - this.OutPacket(mbReply, ThrottleOutPacketType.Land); - */ - } - - /// - /// returns a byte array of the client set throttles Gets multiplied by the multiplier - /// - /// - /// non 1 multiplier for subdividing the throttles between individual regions - /// - public byte[] GetThrottlesPacked(float multiplier) - { - return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier); - } - /// - /// sets the throttles from values supplied by the client - /// - /// - public void SetChildAgentThrottle(byte[] throttles) - { - m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); - } - - /// - /// Method gets called when a new packet has arrived from the UDP - /// server. This happens after it's been decoded into a libsl object. - /// - /// object containing the packet. - public virtual void InPacket(object NewPack) - { - // Cast NewPack to Packet. - m_PacketHandler.InPacket((Packet) NewPack); - } + int j = 0; - /// - /// This is the starting point for sending a simulator packet out to the client. - /// - /// Please do not call this from outside the LindenUDP client stack. - /// - /// - /// Corresponds to the type of data that is going out. Enum - public void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) - { - m_PacketHandler.OutPacket(NewPack, throttlePacketType); - } + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - public bool AddMoney(int debit) - { - if (m_moneyBalance + debit >= 0) + foreach (UUID banned in BannedUsers) { - m_moneyBalance += debit; - SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); - return true; + returnblock[j].Parameter = banned.GetBytes(); j++; } - return false; + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); } - /// - /// Breaks down the genericMessagePacket into specific events - /// - /// - /// - /// - public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) + public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) { - switch (gmMethod) - { - case "autopilot": - float locx; - float locy; - float locz; - - try - { - uint regionX; - uint regionY; - Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; - locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; - locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); - } - catch (InvalidCastException) - { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; - } + RegionInfoPacket rinfopack = new RegionInfoPacket(); + RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; + rinfoblk.BillableFactor = args.billableFactor; + rinfoblk.EstateID = args.estateID; + rinfoblk.MaxAgents = args.maxAgents; + rinfoblk.ObjectBonusFactor = args.objectBonusFactor; + rinfoblk.ParentEstateID = args.parentEstateID; + rinfoblk.PricePerMeter = args.pricePerMeter; + rinfoblk.RedirectGridX = args.redirectGridX; + rinfoblk.RedirectGridY = args.redirectGridY; + rinfoblk.RegionFlags = args.regionFlags; + rinfoblk.SimAccess = args.simAccess; + rinfoblk.SunHour = args.sunHour; + rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; + rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; + rinfoblk.UseEstateSun = args.useEstateSun; + rinfoblk.WaterHeight = args.waterHeight; + rinfoblk.SimName = Utils.StringToBytes(args.simName); + + rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); + rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; + rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; + rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; + rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; + rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; - handlerAutoPilotGo = OnAutoPilotGo; - if (handlerAutoPilotGo != null) - { - handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); - } - m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); + rinfopack.HasVariableBlocks = true; + rinfopack.RegionInfo = rinfoblk; + rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; - break; - default: - m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); - for (int hi = 0; hi < gmParams.Length; hi++) - { - Console.WriteLine(gmParams[hi].ToString()); - } - //gmpack.MethodData. - break; + OutPacket(rinfopack, ThrottleOutPacketType.Task); + } - } + public void SendEstateCovenantInformation(UUID covenant) + { + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); + EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); + edata.CovenantID = covenant; + edata.CovenantTimestamp = 0; + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); + einfopack.Data = edata; + OutPacket(einfopack, ThrottleOutPacketType.Task); } - /// - /// Entryway from the client to the simulator. All UDP packets from the client will end up here - /// - /// OpenMetaverse.packet - public void ProcessInPacket(Packet Pack) + public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) { + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.MethodData.Invoice = invoice; + packet.AgentData.TransactionID = UUID.Random(); + packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; - if (ProcessPacketMethod(Pack)) + for (int i = 0; i < 10; i++) { - return; + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); } - const bool m_checkPackets = true; - - // Main packet processing conditional - switch (Pack.Type) - { - #region Scene/Avatar - - case PacketType.AvatarPropertiesRequest: - AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (avatarProperties.AgentData.SessionID != SessionId || - avatarProperties.AgentData.AgentID != AgentId) - break; - } - #endregion + //Sending Estate Settings + returnblock[0].Parameter = Utils.StringToBytes(estateName); + // TODO: remove this cruft once MasterAvatar is fully deprecated + // + returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); + returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); - handlerRequestAvatarProperties = OnRequestAvatarProperties; - if (handlerRequestAvatarProperties != null) - { - handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); - } + returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); + returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); + returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); + returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); + returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? + returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? + returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); - break; + packet.ParamList = returnblock; + packet.Header.Reliable = false; + //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.ChatFromViewer: - ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + #endregion - #region Packet Session and User Check - if (m_checkPackets) - { - if (inchatpack.AgentData.SessionID != SessionId || - inchatpack.AgentData.AgentID != AgentId) - break; - } - #endregion + #region Land Data Sending Methods - string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; - byte[] message = inchatpack.ChatData.Message; - byte type = inchatpack.ChatData.Type; - Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; - // UUID fromAgentID = AgentId; + public void SendLandParcelOverlay(byte[] data, int sequence_id) + { + ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); + packet.ParcelData.Data = data; + packet.ParcelData.SequenceID = sequence_id; + packet.Header.Zerocoded = true; + OutPacket(packet, ThrottleOutPacketType.Task); + } - int channel = inchatpack.ChatData.Channel; + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + { + ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); + // TODO: don't create new blocks if recycling an old packet - if (OnChatFromClient != null) - { - OSChatMessage args = new OSChatMessage(); - args.Channel = channel; - args.From = fromName; - args.Message = Utils.BytesToString(message); - args.Type = (ChatTypeEnum)type; - args.Position = fromPos; + updatePacket.ParcelData.AABBMax = landData.AABBMax; + updatePacket.ParcelData.AABBMin = landData.AABBMin; + updatePacket.ParcelData.Area = landData.Area; + updatePacket.ParcelData.AuctionID = landData.AuctionID; + updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; - args.Scene = Scene; - args.Sender = this; - args.SenderUUID = this.AgentId; + updatePacket.ParcelData.Bitmap = landData.Bitmap; - handlerChatFromClient = OnChatFromClient; - if (handlerChatFromClient != null) - handlerChatFromClient(this, args); - } - break; + updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); + updatePacket.ParcelData.Category = (byte)landData.Category; + updatePacket.ParcelData.ClaimDate = landData.ClaimDate; + updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; + updatePacket.ParcelData.GroupID = landData.GroupID; + updatePacket.ParcelData.GroupPrims = landData.GroupPrims; + updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; + updatePacket.ParcelData.LandingType = landData.LandingType; + updatePacket.ParcelData.LocalID = landData.LocalID; - case PacketType.AvatarPropertiesUpdate: - AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; + if (landData.Area > 0) + { + updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.MaxPrims = 0; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avatarProps.AgentData.SessionID != SessionId || - avatarProps.AgentData.AgentID != AgentId) - break; - } - #endregion + updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; + updatePacket.ParcelData.MediaID = landData.MediaID; + updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); + updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); + updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); + updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; + updatePacket.ParcelData.OtherCount = 0; //unemplemented + updatePacket.ParcelData.OtherPrims = landData.OtherPrims; + updatePacket.ParcelData.OwnerID = landData.OwnerID; + updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; + updatePacket.ParcelData.ParcelFlags = landData.Flags; + updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; + updatePacket.ParcelData.PassHours = landData.PassHours; + updatePacket.ParcelData.PassPrice = landData.PassPrice; + updatePacket.ParcelData.PublicCount = 0; //unemplemented - handlerUpdateAvatarProperties = OnUpdateAvatarProperties; - if (handlerUpdateAvatarProperties != null) - { - AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; - UserProfileData UserProfile = new UserProfileData(); - UserProfile.ID = AgentId; - UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); - UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); - UserProfile.FirstLifeImage = Properties.FLImageID; - UserProfile.Image = Properties.ImageID; - UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); + updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > + 0); + updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > + 0); + updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) > + 0); + updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) > + 0); - handlerUpdateAvatarProperties(this, UserProfile); - } - break; + updatePacket.ParcelData.RentPrice = 0; + updatePacket.ParcelData.RequestResult = request_result; + updatePacket.ParcelData.SalePrice = landData.SalePrice; + updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; + updatePacket.ParcelData.SelfCount = 0; //unemplemented + updatePacket.ParcelData.SequenceID = sequence_id; + if (landData.SimwideArea > 0) + { + updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.SimWideMaxPrims = 0; + } + updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; + updatePacket.ParcelData.SnapSelection = snap_selection; + updatePacket.ParcelData.SnapshotID = landData.SnapshotID; + updatePacket.ParcelData.Status = (byte)landData.Status; + updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + + landData.SelectedPrims; + updatePacket.ParcelData.UserLocation = landData.UserLocation; + updatePacket.ParcelData.UserLookAt = landData.UserLookAt; + updatePacket.Header.Zerocoded = true; - case PacketType.ScriptDialogReply: - ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + eq.ParcelProperties(updatePacket, this.AgentId); + } + } + catch (Exception ex) + { + m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending parcel data via UDP"); + OutPacket(updatePacket, ThrottleOutPacketType.Task); + } + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (rdialog.AgentData.SessionID != SessionId || - rdialog.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) + { + ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); + replyPacket.Data.AgentID = AgentId; + replyPacket.Data.Flags = accessFlag; + replyPacket.Data.LocalID = localLandID; + replyPacket.Data.SequenceID = 0; - int ch = rdialog.Data.ChatChannel; - byte[] msg = rdialog.Data.ButtonLabel; - if (OnChatFromClient != null) - { - OSChatMessage args = new OSChatMessage(); - args.Channel = ch; - args.From = String.Empty; - args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; - args.Position = new Vector3(); - args.Scene = Scene; - args.Sender = this; - handlerChatFromClient2 = OnChatFromClient; - if (handlerChatFromClient2 != null) - handlerChatFromClient2(this, args); - } + List list = new List(); + foreach (UUID avatar in avatars) + { + ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); + block.Flags = accessFlag; + block.ID = avatar; + block.Time = 0; + list.Add(block); + } - break; + replyPacket.List = list.ToArray(); + replyPacket.Header.Zerocoded = true; + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } - case PacketType.ImprovedInstantMessage: - ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; + public void SendForceClientSelectObjects(List ObjectIDs) + { + bool firstCall = true; + const int MAX_OBJECTS_PER_PACKET = 251; + ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); + ForceObjectSelectPacket.DataBlock[] data; + while (ObjectIDs.Count > 0) + { + if (firstCall) + { + pack._Header.ResetList = true; + firstCall = false; + } + else + { + pack._Header.ResetList = false; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (msgpack.AgentData.SessionID != SessionId || - msgpack.AgentData.AgentID != AgentId) - break; - } - #endregion + if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) + { + data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; + } + else + { + data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; + } - string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); - string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); - handlerInstantMessage = OnInstantMessage; + int i; + for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) + { + data[i] = new ForceObjectSelectPacket.DataBlock(); + data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); + ObjectIDs.RemoveAt(0); + } + pack.Data = data; + pack.Header.Zerocoded = true; + OutPacket(pack, ThrottleOutPacketType.Task); + } + } - if (handlerInstantMessage != null) - { - GridInstantMessage im = new GridInstantMessage(Scene, - msgpack.AgentData.AgentID, - IMfromName, - msgpack.MessageBlock.ToAgentID, - msgpack.MessageBlock.Dialog, - msgpack.MessageBlock.FromGroup, - IMmessage, - msgpack.MessageBlock.ID, - msgpack.MessageBlock.Offline != 0 ? true : false, - msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + public void SendCameraConstraint(Vector4 ConstraintPlane) + { + CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); + cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); + cpack.CameraCollidePlane.Plane = ConstraintPlane; + //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); + OutPacket(cpack, ThrottleOutPacketType.Task); + } - handlerInstantMessage(this, im); - } - break; + public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) + { + - case PacketType.AcceptFriendship: - AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; + int notifyCount = ownersAndCount.Count; + ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (afriendpack.AgentData.SessionID != SessionId || - afriendpack.AgentData.AgentID != AgentId) - break; - } - #endregion + if (notifyCount > 0) + { + if (notifyCount > 32) + { + m_log.InfoFormat( + "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" + + " - a developer might want to investigate whether this is a hard limit", 32); - // My guess is this is the folder to stick the calling card into - List callingCardFolders = new List(); + notifyCount = 32; + } - UUID agentID = afriendpack.AgentData.AgentID; - UUID transactionID = afriendpack.TransactionBlock.TransactionID; + ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock + = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; - for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) - { - callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); - } + int num = 0; + foreach (UUID owner in ownersAndCount.Keys) + { + dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); + dataBlock[num].Count = ownersAndCount[owner]; - handlerApproveFriendRequest = OnApproveFriendRequest; - if (handlerApproveFriendRequest != null) - { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); - } - break; + if (land.GroupID == owner || groups.Contains(owner)) + dataBlock[num].IsGroupOwned = true; - case PacketType.DeclineFriendship: - DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; + dataBlock[num].OnlineStatus = true; //TODO: fix me later + dataBlock[num].OwnerID = owner; - #region Packet Session and User Check - if (m_checkPackets) - { - if (dfriendpack.AgentData.SessionID != SessionId || - dfriendpack.AgentData.AgentID != AgentId) - break; - } - #endregion + num++; - if (OnDenyFriendRequest != null) + if (num >= notifyCount) { - OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, - dfriendpack.TransactionBlock.TransactionID, - null); + break; } - break; + } - case PacketType.TerminateFriendship: - TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; + pack.Data = dataBlock; + } + pack.Header.Zerocoded = true; + this.OutPacket(pack, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (tfriendpack.AgentData.SessionID != SessionId || - tfriendpack.AgentData.AgentID != AgentId) - break; - } - #endregion + #endregion - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; - UUID exFriendID = tfriendpack.ExBlock.OtherID; + #region Helper Methods - handlerTerminateFriendship = OnTerminateFriendship; - if (handlerTerminateFriendship != null) - { - handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); - } - break; + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, + Vector3 velocity, + Quaternion rotation) + { + byte[] bytes = new byte[60]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - case PacketType.RezObject: - RezObjectPacket rezPacket = (RezObjectPacket)Pack; + dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; - #region Packet Session and User Check - if (m_checkPackets) - { - if (rezPacket.AgentData.SessionID != SessionId || - rezPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + uint ID = localID; - handlerRezObject = OnRezObject; - if (handlerRezObject != null) - { - handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, - rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, - rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, - rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, - rezPacket.RezData.FromTaskID); - } - break; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = 0; + bytes[i++] = 1; + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; - case PacketType.DeRezObject: - DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; - #region Packet Session and User Check - if (m_checkPackets) - { - if (DeRezPacket.AgentData.SessionID != SessionId || - DeRezPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); - handlerDeRezObject = OnDeRezObject; - if (handlerDeRezObject != null) - { - List deRezIDs = new List(); + internDirec = internDirec / 128.0f; + internDirec.X += 1; + internDirec.Y += 1; + internDirec.Z += 1; - foreach (DeRezObjectPacket.ObjectDataBlock data in - DeRezPacket.ObjectData) - { - deRezIDs.Add(data.ObjectLocalID); - } - // It just so happens that the values on the DeRezAction enumerator match the Destination - // values given by a Second Life client - handlerDeRezObject(this, deRezIDs, - DeRezPacket.AgentBlock.GroupID, - (DeRezAction)DeRezPacket.AgentBlock.Destination, - DeRezPacket.AgentBlock.DestinationID); - - } - break; + ushort InternVelocityX = (ushort)(32768 * internDirec.X); + ushort InternVelocityY = (ushort)(32768 * internDirec.Y); + ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); - case PacketType.ModifyLand: - ModifyLandPacket modify = (ModifyLandPacket)Pack; + ushort ac = 32767; + bytes[i++] = (byte)(InternVelocityX % 256); + bytes[i++] = (byte)((InternVelocityX >> 8) % 256); + bytes[i++] = (byte)(InternVelocityY % 256); + bytes[i++] = (byte)((InternVelocityY >> 8) % 256); + bytes[i++] = (byte)(InternVelocityZ % 256); + bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); - #region Packet Session and User Check - if (m_checkPackets) - { - if (modify.AgentData.SessionID != SessionId || - modify.AgentData.AgentID != AgentId) - break; - } + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - #endregion - //m_log.Info("[LAND]: LAND:" + modify.ToString()); - if (modify.ParcelData.Length > 0) - { - if (OnModifyTerrain != null) - { - for (int i = 0; i < modify.ParcelData.Length; i++) - { - handlerModifyTerrain = OnModifyTerrain; - if (handlerModifyTerrain != null) - { - handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, - modify.ModifyBlock.BrushSize, - modify.ModifyBlock.Action, modify.ParcelData[i].North, - modify.ParcelData[i].West, modify.ParcelData[i].South, - modify.ParcelData[i].East, AgentId); - } - } - } - } - - break; - - case PacketType.RegionHandshakeReply: + //rotation + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - handlerRegionHandShakeReply = OnRegionHandShakeReply; - if (handlerRegionHandShakeReply != null) - { - handlerRegionHandShakeReply(this); - } + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - break; + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - case PacketType.AgentWearablesRequest: - handlerRequestWearables = OnRequestWearables; + dat.Data = bytes; - if (handlerRequestWearables != null) - { - handlerRequestWearables(); - } + return (dat); + } - handlerRequestAvatarsData = OnRequestAvatarsData; + /// + /// + /// + /// + /// + /// + /// + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, + Vector3 position, + Quaternion rotation, + Vector3 velocity, + Vector3 rotationalvelocity, + byte state) + { + uint ID = localID; + byte[] bytes = new byte[60]; - if (handlerRequestAvatarsData != null) - { - handlerRequestAvatarsData(this); - } + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); + dat.TextureEntry = new byte[0]; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); + bytes[i++] = 0; - break; + byte[] pb = position.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; - case PacketType.AgentSetAppearance: - AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + ushort velx, vely, velz; + Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); - #region Packet Session and User Check - if (m_checkPackets) - { - if (appear.AgentData.SessionID != SessionId || - appear.AgentData.AgentID != AgentId) - break; - } - #endregion + vel = vel / 128.0f; + vel.X += 1; + vel.Y += 1; + vel.Z += 1; + //vel + velx = (ushort)(32768 * (vel.X)); + vely = (ushort)(32768 * (vel.Y)); + velz = (ushort)(32768 * (vel.Z)); - handlerSetAppearance = OnSetAppearance; - if (handlerSetAppearance != null) - { - // Temporarily protect ourselves from the mantis #951 failure. - // However, we could do this for several other handlers where a failure isn't terminal - // for the client session anyway, in order to protect ourselves against bad code in plugins - try - { - byte[] visualparams = new byte[appear.VisualParam.Length]; - for (int i = 0; i < appear.VisualParam.Length; i++) - visualparams[i] = appear.VisualParam[i].ParamValue; + bytes[i++] = (byte)(velx % 256); + bytes[i++] = (byte)((velx >> 8) % 256); + bytes[i++] = (byte)(vely % 256); + bytes[i++] = (byte)((vely >> 8) % 256); + bytes[i++] = (byte)(velz % 256); + bytes[i++] = (byte)((velz >> 8) % 256); - Primitive.TextureEntry te = null; - if (appear.ObjectData.TextureEntry.Length > 1) - te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - handlerSetAppearance(te, visualparams); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", - e); - } - } + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - break; - - case PacketType.AgentIsNowWearing: - if (OnAvatarNowWearing != null) - { - AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - #region Packet Session and User Check - if (m_checkPackets) - { - if (nowWearing.AgentData.SessionID != SessionId || - nowWearing.AgentData.AgentID != AgentId) - break; - } - #endregion + //rotation vel + Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); - AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); - for (int i = 0; i < nowWearing.WearableData.Length; i++) - { - AvatarWearingArgs.Wearable wearable = - new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, - nowWearing.WearableData[i].WearableType); - wearingArgs.NowWearing.Add(wearable); - } + rvel = rvel / 128.0f; + rvel.X += 1; + rvel.Y += 1; + rvel.Z += 1; + //vel + ushort rvelx = (ushort)(32768 * (rvel.X)); + ushort rvely = (ushort)(32768 * (rvel.Y)); + ushort rvelz = (ushort)(32768 * (rvel.Z)); - handlerAvatarNowWearing = OnAvatarNowWearing; - if (handlerAvatarNowWearing != null) - { - handlerAvatarNowWearing(this, wearingArgs); - } - } - break; + bytes[i++] = (byte)(rvelx % 256); + bytes[i++] = (byte)((rvelx >> 8) % 256); + bytes[i++] = (byte)(rvely % 256); + bytes[i++] = (byte)((rvely >> 8) % 256); + bytes[i++] = (byte)(rvelz % 256); + bytes[i++] = (byte)((rvelz >> 8) % 256); + dat.Data = bytes; - case PacketType.RezSingleAttachmentFromInv: - handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; - if (handlerRezSingleAttachment != null) - { - RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; + return dat; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (rez.AgentData.SessionID != SessionId || - rez.AgentData.AgentID != AgentId) - break; - } - #endregion + /// + /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + { + ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); + SetDefaultPrimPacketValues(objupdate); + objupdate.UpdateFlags = flags; + SetPrimPacketShapeData(objupdate, primShape); - handlerRezSingleAttachment(this, rez.ObjectData.ItemID, - rez.ObjectData.AttachmentPt); - } + if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) + { + objupdate.Data = new byte[1]; + objupdate.Data[0] = primShape.State; + } + return objupdate; + } - break; + protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) + { + objectData.TextureEntry = primData.TextureEntry; + objectData.PCode = primData.PCode; + objectData.State = primData.State; + objectData.PathBegin = primData.PathBegin; + objectData.PathEnd = primData.PathEnd; + objectData.PathScaleX = primData.PathScaleX; + objectData.PathScaleY = primData.PathScaleY; + objectData.PathShearX = primData.PathShearX; + objectData.PathShearY = primData.PathShearY; + objectData.PathSkew = primData.PathSkew; + objectData.ProfileBegin = primData.ProfileBegin; + objectData.ProfileEnd = primData.ProfileEnd; + objectData.Scale = primData.Scale; + objectData.PathCurve = primData.PathCurve; + objectData.ProfileCurve = primData.ProfileCurve; + objectData.ProfileHollow = primData.ProfileHollow; + objectData.PathRadiusOffset = primData.PathRadiusOffset; + objectData.PathRevolutions = primData.PathRevolutions; + objectData.PathTaperX = primData.PathTaperX; + objectData.PathTaperY = primData.PathTaperY; + objectData.PathTwist = primData.PathTwist; + objectData.PathTwistBegin = primData.PathTwistBegin; + objectData.ExtraParams = primData.ExtraParams; + } - case PacketType.RezMultipleAttachmentsFromInv: - handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; - if (handlerRezMultipleAttachments != null) - { - RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; - handlerRezMultipleAttachments(this, rez.HeaderData, - rez.ObjectData); - } + /// + /// Set some default values in a ObjectUpdatePacket + /// + /// + protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 3; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + objdata.State = 0; + objdata.Data = new byte[0]; - break; + objdata.ObjectData = new byte[60]; + objdata.ObjectData[46] = 128; + objdata.ObjectData[47] = 63; + } - case PacketType.DetachAttachmentIntoInv: - handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; - if (handlerDetachAttachmentIntoInv != null) - { - DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; + /// + /// + /// + /// + public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + { + ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); + // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - #region Packet Session and User Check - // UNSUPPORTED ON THIS PACKET - #endregion + SetDefaultAvatarPacketValues(ref objdata); + objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objdata.PathCurve = 16; + objdata.ProfileCurve = 1; + objdata.PathScaleX = 100; + objdata.PathScaleY = 100; + objdata.ParentID = 0; + objdata.OwnerID = UUID.Zero; + objdata.Scale = new Vector3(1, 1, 1); + objdata.PCode = (byte)PCode.Avatar; + if (textureEntry != null) + { + objdata.TextureEntry = textureEntry; + } + Vector3 pos = new Vector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); + //Vector3 pos2 = new Vector3(100f, 100f, 23f); + //objdata.FullID=user.AgentId; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); - UUID itemID = detachtoInv.ObjectData.ItemID; - // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; + return objdata; + } - handlerDetachAttachmentIntoInv(itemID, this); - } - break; + /// + /// + /// + /// + protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 4; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); + objdata.TextureEntry = ntex.GetBytes(); - case PacketType.ObjectAttach: - if (OnObjectAttach != null) - { - ObjectAttachPacket att = (ObjectAttachPacket)Pack; + objdata.State = 0; + objdata.Data = new byte[0]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (att.AgentData.SessionID != SessionId || - att.AgentData.AgentID != AgentId) - break; - } - #endregion + objdata.ObjectData = new byte[76]; + objdata.ObjectData[15] = 128; + objdata.ObjectData[16] = 63; + objdata.ObjectData[56] = 128; + objdata.ObjectData[61] = 102; + objdata.ObjectData[62] = 40; + objdata.ObjectData[63] = 61; + objdata.ObjectData[64] = 189; + } - handlerObjectAttach = OnObjectAttach; + public void SendNameReply(UUID profileId, string firstname, string lastname) + { + UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); + // TODO: don't create new blocks if recycling an old packet + packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; + packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); + packet.UUIDNameBlock[0].ID = profileId; + packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); + packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); - if (handlerObjectAttach != null) - { - if (att.ObjectData.Length > 0) - { - handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); - } - } - } - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.ObjectDetach: - ObjectDetachPacket dett = (ObjectDetachPacket)Pack; + public ulong GetGroupPowers(UUID groupID) + { + if (groupID == m_activeGroupID) + return m_activeGroupPowers; - #region Packet Session and User Check - if (m_checkPackets) - { - if (dett.AgentData.SessionID != SessionId || - dett.AgentData.AgentID != AgentId) - break; - } - #endregion + if (m_groupPowers.ContainsKey(groupID)) + return m_groupPowers[groupID]; - for (int j = 0; j < dett.ObjectData.Length; j++) - { - uint obj = dett.ObjectData[j].ObjectLocalID; - handlerObjectDetach = OnObjectDetach; - if (handlerObjectDetach != null) - { - handlerObjectDetach(obj, this); - } + return 0; + } - } - break; + /// + /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. + /// + public bool ChildAgentStatus() + { + return m_scene.PresenceChildStatus(AgentId); + } - case PacketType.ObjectDrop: - ObjectDropPacket dropp = (ObjectDropPacket)Pack; + #endregion - #region Packet Session and User Check - if (m_checkPackets) - { - if (dropp.AgentData.SessionID != SessionId || - dropp.AgentData.AgentID != AgentId) - break; - } - #endregion + /// + /// This is a different way of processing packets then ProcessInPacket + /// + protected virtual void RegisterLocalPacketHandlers() + { + AddLocalPacketHandler(PacketType.LogoutRequest, Logout); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); + AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); + AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); + AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); + } - for (int j = 0; j < dropp.ObjectData.Length; j++) - { - uint obj = dropp.ObjectData[j].ObjectLocalID; - handlerObjectDrop = OnObjectDrop; - if (handlerObjectDrop != null) - { - handlerObjectDrop(obj, this); - } - } - break; + #region Packet Handlers - case PacketType.SetAlwaysRun: - SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; + private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) + { + MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; + // validate the agent owns the agentID and sessionID + if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && + money.AgentData.SessionID == sender.SessionId) + { + MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest; + if (handlerMoneyTransferRequest != null) + { + handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, + money.MoneyData.Amount, money.MoneyData.TransactionType, + Util.FieldToString(money.MoneyData.Description)); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (run.AgentData.SessionID != SessionId || - run.AgentData.AgentID != AgentId) - break; - } - #endregion + return true; + } - handlerSetAlwaysRun = OnSetAlwaysRun; - if (handlerSetAlwaysRun != null) - handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); + return false; + } - break; + private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) + { + ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; + if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) + { + ParcelBuy handlerParcelBuy = OnParcelBuy; + if (handlerParcelBuy != null) + { + handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, + parcel.Data.IsGroupOwned, + parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, + parcel.ParcelData.Price, + false); + } + return true; + } + return false; + } - case PacketType.CompleteAgentMovement: - handlerCompleteMovementToRegion = OnCompleteMovementToRegion; - if (handlerCompleteMovementToRegion != null) - { - handlerCompleteMovementToRegion(); - } - handlerCompleteMovementToRegion = null; - - break; - - case PacketType.AgentUpdate: - if (OnAgentUpdate != null) - { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (agenUpdate.AgentData.SessionID != SessionId || - agenUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion - - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - - // We can only check when we have something to check - // against. + private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) + { + UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; + - if (lastarg != null) - { - update = - ( - (x.BodyRotation != lastarg.BodyRotation) || - (x.CameraAtAxis != lastarg.CameraAtAxis) || - (x.CameraCenter != lastarg.CameraCenter) || - (x.CameraLeftAxis != lastarg.CameraLeftAxis) || - (x.CameraUpAxis != lastarg.CameraUpAxis) || - (x.ControlFlags != lastarg.ControlFlags) || - (x.Far != lastarg.Far) || - (x.Flags != lastarg.Flags) || - (x.State != lastarg.State) || - (x.HeadRotation != lastarg.HeadRotation) || - (x.SessionID != lastarg.SessionID) || - (x.AgentID != lastarg.AgentID) - ); - } - else - update = true; + for (int i = 0; i < upack.UUIDNameBlock.Length; i++) + { + UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; + if (handlerUUIDGroupNameRequest != null) + { + handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); + } + } - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. + return true; + } - if (update) - { - AgentUpdateArgs arg = new AgentUpdateArgs(); - arg.AgentID = x.AgentID; - arg.BodyRotation = x.BodyRotation; - arg.CameraAtAxis = x.CameraAtAxis; - arg.CameraCenter = x.CameraCenter; - arg.CameraLeftAxis = x.CameraLeftAxis; - arg.CameraUpAxis = x.CameraUpAxis; - arg.ControlFlags = x.ControlFlags; - arg.Far = x.Far; - arg.Flags = x.Flags; - arg.HeadRotation = x.HeadRotation; - arg.SessionID = x.SessionID; - arg.State = x.State; - handlerAgentUpdate = OnAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime - if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + public bool HandleGenericMessage(IClientAPI sender, Packet pack) + { + GenericMessagePacket gmpack = (GenericMessagePacket) pack; + if (m_genericPacketHandlers.Count == 0) return false; + if (gmpack.AgentData.SessionID != SessionId) return false; - handlerAgentUpdate = null; - } + GenericMessage handlerGenericMessage = null; - } - break; + string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); - case PacketType.AgentAnimation: - AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) + { + List msg = new List(); + List msgBytes = new List(); - #region Packet Session and User Check - if (m_checkPackets) + if (handlerGenericMessage != null) + { + foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) { - if (AgentAni.AgentData.SessionID != SessionId || - AgentAni.AgentData.AgentID != AgentId) - break; + msg.Add(Util.FieldToString(block.Parameter)); + msgBytes.Add(block.Parameter); } - #endregion - - handlerStartAnim = null; - handlerStopAnim = null; - - for (int i = 0; i < AgentAni.AnimationList.Length; i++) + try { - if (AgentAni.AnimationList[i].StartAnim) - { - handlerStartAnim = OnStartAnim; - if (handlerStartAnim != null) - { - handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); - } - } - else + if (OnBinaryGenericMessage != null) { - handlerStopAnim = OnStopAnim; - if (handlerStopAnim != null) - { - handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); - } + OnBinaryGenericMessage(this, method, msgBytes.ToArray()); } + handlerGenericMessage(sender, method, msg); + return true; } - break; - - case PacketType.AgentRequestSit: - if (OnAgentRequestSit != null) + catch (Exception e) { - AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentRequestSit.AgentData.SessionID != SessionId || - agentRequestSit.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerAgentRequestSit = OnAgentRequestSit; - if (handlerAgentRequestSit != null) - handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, - agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + m_log.Error("[GENERICMESSAGE] " + e); } - break; + } + } + m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); + return false; + } - case PacketType.AgentSit: - if (OnAgentSit != null) - { - AgentSitPacket agentSit = (AgentSitPacket)Pack; + public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) + { - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentSit.AgentData.SessionID != SessionId || - agentSit.AgentData.AgentID != AgentId) - break; - } - #endregion + ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; + if (ogpack.AgentData.SessionID != SessionId) return false; - handlerAgentSit = OnAgentSit; - if (handlerAgentSit != null) - { - OnAgentSit(this, agentSit.AgentData.AgentID); - } - } - break; + RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest; + if (handlerObjectGroupRequest != null) + { + for (int i = 0; i < ogpack.ObjectData.Length; i++) + { + handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); + } + } + return true; + } - case PacketType.SoundTrigger: - SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; + private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + { + ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; + if (viewer.AgentData.SessionID != SessionId) return false; + ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect; + if (handlerViewerEffect != null) + { + int length = viewer.Effect.Length; + List args = new List(length); + for (int i = 0; i < length; i++) + { + //copy the effects block arguments into the event handler arg. + ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); + argument.AgentID = viewer.Effect[i].AgentID; + argument.Color = viewer.Effect[i].Color; + argument.Duration = viewer.Effect[i].Duration; + argument.ID = viewer.Effect[i].ID; + argument.Type = viewer.Effect[i].Type; + argument.TypeData = viewer.Effect[i].TypeData; + args.Add(argument); + } - #region Packet Session and User Check - if (m_checkPackets) - { - // UNSUPPORTED ON THIS PACKET - } - #endregion + handlerViewerEffect(sender, args); + } - handlerSoundTrigger = OnSoundTrigger; - if (handlerSoundTrigger != null) - { - handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, - soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, - soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, - soundTriggerPacket.SoundData.Handle); + return true; + } - } - break; + #endregion Packet Handlers - case PacketType.AvatarPickerRequest: - AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) + { + ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); + scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); + // TODO: don't create new blocks if recycling an old packet + scriptQuestion.Data.TaskID = taskID; + scriptQuestion.Data.ItemID = itemID; + scriptQuestion.Data.Questions = question; + scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); + scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); - #region Packet Session and User Check - if (m_checkPackets) + OutPacket(scriptQuestion, ThrottleOutPacketType.Task); + } + + private void InitDefaultAnimations() + { + using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) + { + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + if (doc.DocumentElement != null) + foreach (XmlNode nod in doc.DocumentElement.ChildNodes) { - if (avRequestQuery.AgentData.SessionID != SessionId || - avRequestQuery.AgentData.AgentID != AgentId) - break; + if (nod.Attributes["name"] != null) + { + string name = nod.Attributes["name"].Value.ToLower(); + string id = nod.InnerText; + m_defaultAnimations.Add(name, (UUID)id); + } } - #endregion + } + } - AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; - AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; - //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); + public UUID GetDefaultAnimation(string name) + { + if (m_defaultAnimations.ContainsKey(name)) + return m_defaultAnimations[name]; + return UUID.Zero; + } - handlerAvatarPickerRequest = OnAvatarPickerRequest; - if (handlerAvatarPickerRequest != null) - { - handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, - Utils.BytesToString(querydata.Name)); - } - break; + /// + /// Handler called when we receive a logout packet. + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client, Packet packet) + { + if (packet.Type == PacketType.LogoutRequest) + { + if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; + } + + return Logout(client); + } - case PacketType.AgentDataUpdateRequest: - AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; + /// + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client) + { + m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); - #region Packet Session and User Check - if (m_checkPackets) - { - if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || - avRequestDataUpdatePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + Action handlerLogout = OnLogout; - handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; + if (handlerLogout != null) + { + handlerLogout(client); + } - if (handlerAgentDataUpdateRequest != null) - { - handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); - } + return true; + } - break; - - case PacketType.UserInfoRequest: - handlerUserInfoRequest = OnUserInfoRequest; - if (handlerUserInfoRequest != null) - { - handlerUserInfoRequest(this); - } - else - { - SendUserInfoReply(false, true, ""); - } - break; - - case PacketType.UpdateUserInfo: - UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; + /// + /// Send a response back to a client when it asks the asset server (via the region server) if it has + /// its appearance texture cached. + /// + /// At the moment, we always reply that there is no cached texture. + /// + /// + /// + /// + protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + { + //m_log.Debug("texture cached: " + packet.ToString()); + AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); - #region Packet Session and User Check - if (m_checkPackets) - { - if (updateUserInfo.AgentData.SessionID != SessionId || - updateUserInfo.AgentData.AgentID != AgentId) - break; - } - #endregion + if (cachedtex.AgentData.SessionID != SessionId) return false; - handlerUpdateUserInfo = OnUpdateUserInfo; - if (handlerUpdateUserInfo != null) - { - bool visible = true; - string DirectoryVisibility = - Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); - if (DirectoryVisibility == "hidden") - visible = false; + // TODO: don't create new blocks if recycling an old packet + cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.SessionID = m_sessionId; + cachedresp.AgentData.SerialNum = m_cachedTextureSerial; + m_cachedTextureSerial++; + cachedresp.WearableData = + new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - handlerUpdateUserInfo( - updateUserInfo.UserData.IMViaEMail, - visible, this); - } - break; - - case PacketType.SetStartLocationRequest: - SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || - avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + cachedresp.Header.Zerocoded = true; + OutPacket(cachedresp, ThrottleOutPacketType.Task); + + return true; + } - if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) - { - handlerSetStartLocationRequest = OnSetStartLocationRequest; - if (handlerSetStartLocationRequest != null) - { - handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, - avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, - avSetStartLocationRequestPacket.StartLocationData.LocationID); - } - } - break; + protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + { + MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; + if (multipleupdate.AgentData.SessionID != SessionId) return false; + // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + Scene tScene = (Scene)m_scene; - case PacketType.AgentThrottle: - AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; - #region Packet Session and User Check - if (m_checkPackets) + // Can't act on Null Data + if (block.Data != null) + { + uint localId = block.ObjectLocalID; + SceneObjectPart part = tScene.GetSceneObjectPart(localId); + + if (part == null) { - if (atpack.AgentData.SessionID != SessionId || - atpack.AgentData.AgentID != AgentId) - break; + // It's a ghost! tell the client to delete it from view. + simClient.SendKillObject(Scene.RegionInfo.RegionHandle, + localId); } - #endregion + else + { + // UUID partId = part.UUID; + UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; - m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles); - break; + switch (block.Type) + { + case 1: + Vector3 pos1 = new Vector3(block.Data, 0); - case PacketType.AgentPause: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = true; - break; + UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + handlerUpdatePrimSinglePosition(localId, pos1, this); + } + break; + case 2: + Quaternion rot1 = new Quaternion(block.Data, 0, true); - case PacketType.AgentResume: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = false; - SendStartPingCheck(0); + UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; + if (handlerUpdatePrimSingleRotation != null) + { + // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); + handlerUpdatePrimSingleRotation(localId, rot1, this); + } + break; + case 3: + Vector3 rotPos = new Vector3(block.Data, 0); + Quaternion rot2 = new Quaternion(block.Data, 12, true); - break; + UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; + if (handlerUpdatePrimSingleRotationPosition != null) + { + // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); + // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); + handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); + } + break; + case 4: + case 20: + Vector3 scale4 = new Vector3(block.Data, 0); - case PacketType.ForceScriptControlRelease: - handlerForceReleaseControls = OnForceReleaseControls; - if (handlerForceReleaseControls != null) - { - handlerForceReleaseControls(this, AgentId); - } - break; + UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { +// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); + handlerUpdatePrimScale(localId, scale4, this); + } + break; + case 5: - #endregion + Vector3 scale1 = new Vector3(block.Data, 12); + Vector3 pos11 = new Vector3(block.Data, 0); - #region Objects/m_sceneObjects + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale1, this); - case PacketType.ObjectLink: - ObjectLinkPacket link = (ObjectLinkPacket)Pack; + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos11, this); + } + } + break; + case 9: + Vector3 pos2 = new Vector3(block.Data, 0); - #region Packet Session and User Check - if (m_checkPackets) - { - if (link.AgentData.SessionID != SessionId || - link.AgentData.AgentID != AgentId) - break; - } - #endregion - - uint parentprimid = 0; - List childrenprims = new List(); - if (link.ObjectData.Length > 1) - { - parentprimid = link.ObjectData[0].ObjectLocalID; - - for (int i = 1; i < link.ObjectData.Length; i++) - { - childrenprims.Add(link.ObjectData[i].ObjectLocalID); - } - } - handlerLinkObjects = OnLinkObjects; - if (handlerLinkObjects != null) - { - handlerLinkObjects(this, parentprimid, childrenprims); - } - break; - - case PacketType.ObjectDelink: - ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (delink.AgentData.SessionID != SessionId || - delink.AgentData.AgentID != AgentId) - break; - } - #endregion + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; - // It appears the prim at index 0 is not always the root prim (for - // instance, when one prim of a link set has been edited independently - // of the others). Therefore, we'll pass all the ids onto the delink - // method for it to decide which is the root. - List prims = new List(); - for (int i = 0; i < delink.ObjectData.Length; i++) - { - prims.Add(delink.ObjectData[i].ObjectLocalID); - } - handlerDelinkObjects = OnDelinkObjects; - if (handlerDelinkObjects != null) - { - handlerDelinkObjects(prims); - } - - break; - - case PacketType.ObjectAdd: - if (OnAddPrim != null) - { - ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + if (handlerUpdateVector != null) + { - #region Packet Session and User Check - if (m_checkPackets) - { - if (addPacket.AgentData.SessionID != SessionId || - addPacket.AgentData.AgentID != AgentId) + handlerUpdateVector(localId, pos2, this); + } break; - } - #endregion + case 10: + Quaternion rot3 = new Quaternion(block.Data, 0, true); - PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); - // m_log.Info("[REZData]: " + addPacket.ToString()); - //BypassRaycast: 1 - //RayStart: <69.79469, 158.2652, 98.40343> - //RayEnd: <61.97724, 141.995, 92.58341> - //RayTargetID: 00000000-0000-0000-0000-000000000000 + UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + { + // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); + handlerUpdatePrimRotation(localId, rot3, this); + } + break; + case 11: + Vector3 pos3 = new Vector3(block.Data, 0); + Quaternion rot4 = new Quaternion(block.Data, 12, true); - //Check to see if adding the prim is allowed; useful for any module wanting to restrict the - //object from rezing initially + handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; + if (handlerUpdatePrimGroupRotation != null) + { + // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); + handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); + } + break; + case 12: + case 28: + Vector3 scale7 = new Vector3(block.Data, 0); - handlerAddPrim = OnAddPrim; - if (handlerAddPrim != null) - handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); - } - break; - - case PacketType.ObjectShape: - ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { +// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); + handlerUpdatePrimGroupScale(localId, scale7, this); + } + break; + case 13: + Vector3 scale2 = new Vector3(block.Data, 12); + Vector3 pos4 = new Vector3(block.Data, 0); - #region Packet Session and User Check - if (m_checkPackets) - { - if (shapePacket.AgentData.SessionID != SessionId || - shapePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale2, this); - handlerUpdatePrimShape = null; - for (int i = 0; i < shapePacket.ObjectData.Length; i++) - { - handlerUpdatePrimShape = OnUpdatePrimShape; - if (handlerUpdatePrimShape != null) - { - UpdateShapeArgs shapeData = new UpdateShapeArgs(); - shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; - shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; - shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; - shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; - shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; - shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; - shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; - shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; - shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; - shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; - shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; - shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; - shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; - shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; - shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; - shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; - shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; - shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; - shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; + // Change the position based on scale (for bug number 246) + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos4, this); + } + } + break; + case 29: + Vector3 scale5 = new Vector3(block.Data, 12); + Vector3 pos5 = new Vector3(block.Data, 0); - handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, - shapeData); - } - } - break; - - case PacketType.ObjectExtraParams: - ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimGroupScale(localId, scale5, this); + handlerUpdateVector = OnUpdatePrimGroupPosition; - #region Packet Session and User Check - if (m_checkPackets) - { - if (extraPar.AgentData.SessionID != SessionId || - extraPar.AgentData.AgentID != AgentId) - break; - } - #endregion + if (handlerUpdateVector != null) + { + handlerUpdateVector(localId, pos5, this); + } + } + break; + case 21: + Vector3 scale6 = new Vector3(block.Data, 12); + Vector3 pos6 = new Vector3(block.Data, 0); - handlerUpdateExtraParams = OnUpdateExtraParams; - if (handlerUpdateExtraParams != null) - { - for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) - { - handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, - extraPar.ObjectData[i].ParamType, - extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale6, this); + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos6, this); + } + } + break; + default: + m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + break; } } - break; - case PacketType.ObjectDuplicate: - ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + } + } + return true; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (dupe.AgentData.SessionID != SessionId || - dupe.AgentData.AgentID != AgentId) - break; - } - #endregion + public void RequestMapLayer() + { + //should be getting the map layer from the grid server + //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) + MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); + // TODO: don't create new blocks if recycling an old packet + mapReply.AgentData.AgentID = AgentId; + mapReply.AgentData.Flags = 0; + mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + mapReply.LayerData[0].Bottom = 0; + mapReply.LayerData[0].Left = 0; + mapReply.LayerData[0].Top = 30000; + mapReply.LayerData[0].Right = 30000; + mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); + mapReply.Header.Zerocoded = true; + OutPacket(mapReply, ThrottleOutPacketType.Land); + } - ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) + { + /* + IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); + MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); + mbReply.AgentData.AgentId = AgentId; + int len; + if (simMapProfiles == null) + len = 0; + else + len = simMapProfiles.Count; - handlerObjectDuplicate = null; + mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; + int iii; + for (iii = 0; iii < len; iii++) + { + Hashtable mp = (Hashtable)simMapProfiles[iii]; + mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); + mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); + mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); + mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); + mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); + mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); + mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); + mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); + mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + } + this.OutPacket(mbReply, ThrottleOutPacketType.Land); + */ + } - for (int i = 0; i < dupe.ObjectData.Length; i++) - { - handlerObjectDuplicate = OnObjectDuplicate; - if (handlerObjectDuplicate != null) - { - handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, - dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, - AgentandGroupData.GroupID); - } - } + /// + /// Sets the throttles from values supplied by the client + /// + /// + public void SetChildAgentThrottle(byte[] throttles) + { + m_udpClient.SetThrottles(throttles); + } - break; + public byte[] GetThrottlesPacked(float multiplier) + { + return m_udpClient.GetThrottlesPacked(); + } - case PacketType.RequestMultipleObjects: - RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; + public bool IsThrottleEmpty(ThrottleOutPacketType category) + { + return m_udpClient.IsThrottleEmpty(category); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (incomingRequest.AgentData.SessionID != SessionId || - incomingRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + /// + /// Unused + /// + public virtual void InPacket(object NewPack) + { + throw new NotImplementedException(); + } - handlerObjectRequest = null; + /// + /// This is the starting point for sending a simulator packet out to the client + /// + /// Packet to send + /// Throttling category for the packet + private void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) + { + m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); + } - for (int i = 0; i < incomingRequest.ObjectData.Length; i++) - { - handlerObjectRequest = OnObjectRequest; - if (handlerObjectRequest != null) - { - handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); - } - } - break; - case PacketType.ObjectSelect: - ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; + public bool AddMoney(int debit) + { + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); + return true; + } + return false; + } - #region Packet Session and User Check - if (m_checkPackets) + /// + /// Breaks down the genericMessagePacket into specific events + /// + /// + /// + /// + public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) + { + switch (gmMethod) + { + case "autopilot": + float locx; + float locy; + float locz; + + try { - if (incomingselect.AgentData.SessionID != SessionId || - incomingselect.AgentData.AgentID != AgentId) - break; + uint regionX; + uint regionY; + Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; + locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; + locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); } - #endregion - - handlerObjectSelect = null; - - for (int i = 0; i < incomingselect.ObjectData.Length; i++) + catch (InvalidCastException) { - handlerObjectSelect = OnObjectSelect; - if (handlerObjectSelect != null) - { - handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); - } + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; } - break; - case PacketType.ObjectDeselect: - ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) + UpdateVector handlerAutoPilotGo = OnAutoPilotGo; + if (handlerAutoPilotGo != null) { - if (incomingdeselect.AgentData.SessionID != SessionId || - incomingdeselect.AgentData.AgentID != AgentId) - break; + handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); } - #endregion + m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); - handlerObjectDeselect = null; - for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) - { - handlerObjectDeselect = OnObjectDeselect; - if (handlerObjectDeselect != null) - { - OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); - } - } break; - case PacketType.ObjectPosition: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectPositionPacket position = (ObjectPositionPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + default: + m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); + for (int hi = 0; hi < gmParams.Length; hi++) { - if (position.AgentData.SessionID != SessionId || - position.AgentData.AgentID != AgentId) - break; + Console.WriteLine(gmParams[hi].ToString()); } - #endregion + //gmpack.MethodData. + break; + } + } - for (int i = 0; i < position.ObjectData.Length; i++) - { - handlerUpdateVector = OnUpdatePrimGroupPosition; - if (handlerUpdateVector != null) - handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); - } + /// + /// Entryway from the client to the simulator. All UDP packets from the client will end up here + /// + /// OpenMetaverse.packet + public void ProcessInPacket(Packet Pack) + { - break; - case PacketType.ObjectScale: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectScalePacket scale = (ObjectScalePacket)Pack; + if (ProcessPacketMethod(Pack)) + { + return; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (scale.AgentData.SessionID != SessionId || - scale.AgentData.AgentID != AgentId) - break; - } - #endregion + const bool m_checkPackets = true; - for (int i = 0; i < scale.ObjectData.Length; i++) - { - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); - } + // Main packet processing conditional + switch (Pack.Type) + { + #region Scene/Avatar - break; - case PacketType.ObjectRotation: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; + case PacketType.AvatarPropertiesRequest: + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rotation.AgentData.SessionID != SessionId || - rotation.AgentData.AgentID != AgentId) + if (avatarProperties.AgentData.SessionID != SessionId || + avatarProperties.AgentData.AgentID != AgentId) break; } #endregion - for (int i = 0; i < rotation.ObjectData.Length; i++) + RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties; + if (handlerRequestAvatarProperties != null) { - handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); + handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); } break; - case PacketType.ObjectFlagUpdate: - ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (flags.AgentData.SessionID != SessionId || - flags.AgentData.AgentID != AgentId) + if (inchatpack.AgentData.SessionID != SessionId || + inchatpack.AgentData.AgentID != AgentId) break; } #endregion - handlerUpdatePrimFlags = OnUpdatePrimFlags; - - if (handlerUpdatePrimFlags != null) - { - byte[] data = Pack.ToBytes(); - // 46,47,48 are special positions within the packet - // This may change so perhaps we need a better way - // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) - bool UsePhysics = (data[46] != 0) ? true : false; - bool IsTemporary = (data[47] != 0) ? true : false; - bool IsPhantom = (data[48] != 0) ? true : false; - handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); - } - break; - case PacketType.ObjectImage: - ObjectImagePacket imagePack = (ObjectImagePacket)Pack; + string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; + byte[] message = inchatpack.ChatData.Message; + byte type = inchatpack.ChatData.Type; + Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; + // UUID fromAgentID = AgentId; - handlerUpdatePrimTexture = null; - for (int i = 0; i < imagePack.ObjectData.Length; i++) - { - handlerUpdatePrimTexture = OnUpdatePrimTexture; - if (handlerUpdatePrimTexture != null) - { - handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, - imagePack.ObjectData[i].TextureEntry, this); - } - } - break; - case PacketType.ObjectGrab: - ObjectGrabPacket grab = (ObjectGrabPacket)Pack; + int channel = inchatpack.ChatData.Channel; - #region Packet Session and User Check - if (m_checkPackets) + if (OnChatFromClient != null) { - if (grab.AgentData.SessionID != SessionId || - grab.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerGrabObject = OnGrabObject; + OSChatMessage args = new OSChatMessage(); + args.Channel = channel; + args.From = fromName; + args.Message = Utils.BytesToString(message); + args.Type = (ChatTypeEnum)type; + args.Position = fromPos; - if (handlerGrabObject != null) - { - List touchArgs = new List(); - if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) - { - foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); + args.Scene = Scene; + args.Sender = this; + args.SenderUUID = this.AgentId; + + ChatMessage handlerChatFromClient = OnChatFromClient; + if (handlerChatFromClient != null) + handlerChatFromClient(this, args); } break; - case PacketType.ObjectGrabUpdate: - ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; + + case PacketType.AvatarPropertiesUpdate: + AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (grabUpdate.AgentData.SessionID != SessionId || - grabUpdate.AgentData.AgentID != AgentId) + if (avatarProps.AgentData.SessionID != SessionId || + avatarProps.AgentData.AgentID != AgentId) break; } #endregion - handlerGrabUpdate = OnGrabUpdate; - - if (handlerGrabUpdate != null) + UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties; + if (handlerUpdateAvatarProperties != null) { - List touchArgs = new List(); - if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) - { - foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, - grabUpdate.ObjectData.GrabPosition, this, touchArgs); + AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; + UserProfileData UserProfile = new UserProfileData(); + UserProfile.ID = AgentId; + UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); + UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); + UserProfile.FirstLifeImage = Properties.FLImageID; + UserProfile.Image = Properties.ImageID; + UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); + + handlerUpdateAvatarProperties(this, UserProfile); } break; - case PacketType.ObjectDeGrab: - ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + + case PacketType.ScriptDialogReply: + ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deGrab.AgentData.SessionID != SessionId || - deGrab.AgentData.AgentID != AgentId) + if (rdialog.AgentData.SessionID != SessionId || + rdialog.AgentData.AgentID != AgentId) break; } #endregion - handlerDeGrabObject = OnDeGrabObject; - if (handlerDeGrabObject != null) + int ch = rdialog.Data.ChatChannel; + byte[] msg = rdialog.Data.ButtonLabel; + if (OnChatFromClient != null) { - List touchArgs = new List(); - if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) - { - foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); + OSChatMessage args = new OSChatMessage(); + args.Channel = ch; + args.From = String.Empty; + args.Message = Utils.BytesToString(msg); + args.Type = ChatTypeEnum.Shout; + args.Position = new Vector3(); + args.Scene = Scene; + args.Sender = this; + ChatMessage handlerChatFromClient2 = OnChatFromClient; + if (handlerChatFromClient2 != null) + handlerChatFromClient2(this, args); } + break; - case PacketType.ObjectSpinStart: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); - ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; + + case PacketType.ImprovedInstantMessage: + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStart.AgentData.SessionID != SessionId || - spinStart.AgentData.AgentID != AgentId) + if (msgpack.AgentData.SessionID != SessionId || + msgpack.AgentData.AgentID != AgentId) break; } #endregion - handlerSpinStart = OnSpinStart; - if (handlerSpinStart != null) + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); + ImprovedInstantMessage handlerInstantMessage = OnInstantMessage; + + if (handlerInstantMessage != null) { - handlerSpinStart(spinStart.ObjectData.ObjectID, this); + GridInstantMessage im = new GridInstantMessage(Scene, + msgpack.AgentData.AgentID, + IMfromName, + msgpack.MessageBlock.ToAgentID, + msgpack.MessageBlock.Dialog, + msgpack.MessageBlock.FromGroup, + IMmessage, + msgpack.MessageBlock.ID, + msgpack.MessageBlock.Offline != 0 ? true : false, + msgpack.MessageBlock.Position, + msgpack.MessageBlock.BinaryBucket); + + handlerInstantMessage(this, im); } break; - case PacketType.ObjectSpinUpdate: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); - ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; + + case PacketType.AcceptFriendship: + AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinUpdate.AgentData.SessionID != SessionId || - spinUpdate.AgentData.AgentID != AgentId) + if (afriendpack.AgentData.SessionID != SessionId || + afriendpack.AgentData.AgentID != AgentId) break; } #endregion - Vector3 axis; - float angle; - spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); - //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); + // My guess is this is the folder to stick the calling card into + List callingCardFolders = new List(); - handlerSpinUpdate = OnSpinUpdate; - if (handlerSpinUpdate != null) + UUID agentID = afriendpack.AgentData.AgentID; + UUID transactionID = afriendpack.TransactionBlock.TransactionID; + + for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) { - handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); + callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); + } + + FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; + if (handlerApproveFriendRequest != null) + { + handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); } break; - case PacketType.ObjectSpinStop: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); - ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; + + case PacketType.DeclineFriendship: + DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStop.AgentData.SessionID != SessionId || - spinStop.AgentData.AgentID != AgentId) + if (dfriendpack.AgentData.SessionID != SessionId || + dfriendpack.AgentData.AgentID != AgentId) break; } #endregion - handlerSpinStop = OnSpinStop; - if (handlerSpinStop != null) + if (OnDenyFriendRequest != null) { - handlerSpinStop(spinStop.ObjectData.ObjectID, this); + OnDenyFriendRequest(this, + dfriendpack.AgentData.AgentID, + dfriendpack.TransactionBlock.TransactionID, + null); } break; - case PacketType.ObjectDescription: - ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; + case PacketType.TerminateFriendship: + TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objDes.AgentData.SessionID != SessionId || - objDes.AgentData.AgentID != AgentId) + if (tfriendpack.AgentData.SessionID != SessionId || + tfriendpack.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectDescription = null; + UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; + UUID exFriendID = tfriendpack.ExBlock.OtherID; - for (int i = 0; i < objDes.ObjectData.Length; i++) + FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship; + if (handlerTerminateFriendship != null) { - handlerObjectDescription = OnObjectDescription; - if (handlerObjectDescription != null) - { - handlerObjectDescription(this, objDes.ObjectData[i].LocalID, - Util.FieldToString(objDes.ObjectData[i].Description)); - } + handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); } break; - case PacketType.ObjectName: - ObjectNamePacket objName = (ObjectNamePacket)Pack; - + + case PacketType.RezObject: + RezObjectPacket rezPacket = (RezObjectPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (objName.AgentData.SessionID != SessionId || - objName.AgentData.AgentID != AgentId) + if (rezPacket.AgentData.SessionID != SessionId || + rezPacket.AgentData.AgentID != AgentId) break; } #endregion - - handlerObjectName = null; - for (int i = 0; i < objName.ObjectData.Length; i++) - { - handlerObjectName = OnObjectName; - if (handlerObjectName != null) - { - handlerObjectName(this, objName.ObjectData[i].LocalID, - Util.FieldToString(objName.ObjectData[i].Name)); - } - } - break; - case PacketType.ObjectPermissions: - if (OnObjectPermissions != null) - { - ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (newobjPerms.AgentData.SessionID != SessionId || - newobjPerms.AgentData.AgentID != AgentId) - break; - } - #endregion - - UUID AgentID = newobjPerms.AgentData.AgentID; - UUID SessionID = newobjPerms.AgentData.SessionID; - - handlerObjectPermissions = null; - - for (int i = 0; i < newobjPerms.ObjectData.Length; i++) - { - ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; - - byte field = permChanges.Field; - uint localID = permChanges.ObjectLocalID; - uint mask = permChanges.Mask; - byte set = permChanges.Set; - handlerObjectPermissions = OnObjectPermissions; - - if (handlerObjectPermissions != null) - handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); - } + RezObject handlerRezObject = OnRezObject; + if (handlerRezObject != null) + { + handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, + rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, + rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, + rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, + rezPacket.RezData.FromTaskID); } - - // Here's our data, - // PermField contains the field the info goes into - // PermField determines which mask we're changing - // - // chmask is the mask of the change - // setTF is whether we're adding it or taking it away - // - // objLocalID is the localID of the object. - - // Unfortunately, we have to pass the event the packet because objData is an array - // That means multiple object perms may be updated in a single packet. - break; - case PacketType.Undo: - UndoPacket undoitem = (UndoPacket)Pack; + case PacketType.DeRezObject: + DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; #region Packet Session and User Check if (m_checkPackets) - { - if (undoitem.AgentData.SessionID != SessionId || - undoitem.AgentData.AgentID != AgentId) + { + if (DeRezPacket.AgentData.SessionID != SessionId || + DeRezPacket.AgentData.AgentID != AgentId) break; } #endregion - if (undoitem.ObjectData.Length > 0) + DeRezObject handlerDeRezObject = OnDeRezObject; + if (handlerDeRezObject != null) { - for (int i = 0; i < undoitem.ObjectData.Length; i++) - { - UUID objiD = undoitem.ObjectData[i].ObjectID; - handlerOnUndo = OnUndo; - if (handlerOnUndo != null) - { - handlerOnUndo(this, objiD); - } + List deRezIDs = new List(); + foreach (DeRezObjectPacket.ObjectDataBlock data in + DeRezPacket.ObjectData) + { + deRezIDs.Add(data.ObjectLocalID); } + // It just so happens that the values on the DeRezAction enumerator match the Destination + // values given by a Second Life client + handlerDeRezObject(this, deRezIDs, + DeRezPacket.AgentBlock.GroupID, + (DeRezAction)DeRezPacket.AgentBlock.Destination, + DeRezPacket.AgentBlock.DestinationID); + } break; - case PacketType.ObjectDuplicateOnRay: - ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; + + case PacketType.ModifyLand: + ModifyLandPacket modify = (ModifyLandPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dupeOnRay.AgentData.SessionID != SessionId || - dupeOnRay.AgentData.AgentID != AgentId) + if (modify.AgentData.SessionID != SessionId || + modify.AgentData.AgentID != AgentId) break; } - #endregion - - handlerObjectDuplicateOnRay = null; - - for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) + #endregion + //m_log.Info("[LAND]: LAND:" + modify.ToString()); + if (modify.ParcelData.Length > 0) { - handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; - if (handlerObjectDuplicateOnRay != null) + if (OnModifyTerrain != null) { - handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, - dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, - dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); + for (int i = 0; i < modify.ParcelData.Length; i++) + { + ModifyTerrain handlerModifyTerrain = OnModifyTerrain; + if (handlerModifyTerrain != null) + { + handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, + modify.ModifyBlock.BrushSize, + modify.ModifyBlock.Action, modify.ParcelData[i].North, + modify.ParcelData[i].West, modify.ParcelData[i].South, + modify.ParcelData[i].East, AgentId); + } + } } } break; - case PacketType.RequestObjectPropertiesFamily: - //This powers the little tooltip that appears when you move your mouse over an object - RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) + case PacketType.RegionHandshakeReply: + + Action handlerRegionHandShakeReply = OnRegionHandShakeReply; + if (handlerRegionHandShakeReply != null) { - if (packToolTip.AgentData.SessionID != SessionId || - packToolTip.AgentData.AgentID != AgentId) - break; + handlerRegionHandShakeReply(this); } - #endregion - RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + break; - handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; + case PacketType.AgentWearablesRequest: + GenericCall2 handlerRequestWearables = OnRequestWearables; - if (handlerRequestObjectPropertiesFamily != null) + if (handlerRequestWearables != null) { - handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, - packObjBlock.ObjectID); + handlerRequestWearables(); + } + + Action handlerRequestAvatarsData = OnRequestAvatarsData; + + if (handlerRequestAvatarsData != null) + { + handlerRequestAvatarsData(this); } break; - case PacketType.ObjectIncludeInSearch: - //This lets us set objects to appear in search (stuff like DataSnapshot, etc) - ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; - handlerObjectIncludeInSearch = null; + + case PacketType.AgentSetAppearance: + AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (packInSearch.AgentData.SessionID != SessionId || - packInSearch.AgentData.AgentID != AgentId) + if (appear.AgentData.SessionID != SessionId || + appear.AgentData.AgentID != AgentId) break; } #endregion - foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) + SetAppearance handlerSetAppearance = OnSetAppearance; + if (handlerSetAppearance != null) { - bool inSearch = objData.IncludeInSearch; - uint localID = objData.ObjectLocalID; + // Temporarily protect ourselves from the mantis #951 failure. + // However, we could do this for several other handlers where a failure isn't terminal + // for the client session anyway, in order to protect ourselves against bad code in plugins + try + { + byte[] visualparams = new byte[appear.VisualParam.Length]; + for (int i = 0; i < appear.VisualParam.Length; i++) + visualparams[i] = appear.VisualParam[i].ParamValue; - handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + Primitive.TextureEntry te = null; + if (appear.ObjectData.TextureEntry.Length > 1) + te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - if (handlerObjectIncludeInSearch != null) + handlerSetAppearance(te, visualparams); + } + catch (Exception e) { - handlerObjectIncludeInSearch(this, inSearch, localID); + m_log.ErrorFormat( + "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", + e); } } + break; + + case PacketType.AgentIsNowWearing: + if (OnAvatarNowWearing != null) + { + AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; - case PacketType.ScriptAnswerYes: - ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (nowWearing.AgentData.SessionID != SessionId || + nowWearing.AgentData.AgentID != AgentId) + break; + } + #endregion - #region Packet Session and User Check - if (m_checkPackets) - { - if (scriptAnswer.AgentData.SessionID != SessionId || - scriptAnswer.AgentData.AgentID != AgentId) - break; + AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); + for (int i = 0; i < nowWearing.WearableData.Length; i++) + { + AvatarWearingArgs.Wearable wearable = + new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, + nowWearing.WearableData[i].WearableType); + wearingArgs.NowWearing.Add(wearable); + } + + AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing; + if (handlerAvatarNowWearing != null) + { + handlerAvatarNowWearing(this, wearingArgs); + } } - #endregion + break; - handlerScriptAnswer = OnScriptAnswer; - if (handlerScriptAnswer != null) + case PacketType.RezSingleAttachmentFromInv: + RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; + if (handlerRezSingleAttachment != null) { - handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); + RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rez.AgentData.SessionID != SessionId || + rez.AgentData.AgentID != AgentId) + break; + } + #endregion + + handlerRezSingleAttachment(this, rez.ObjectData.ItemID, + rez.ObjectData.AttachmentPt); } + break; - case PacketType.ObjectClickAction: - ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; + case PacketType.RezMultipleAttachmentsFromInv: + RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; + if (handlerRezMultipleAttachments != null) + { + RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; + handlerRezMultipleAttachments(this, rez.HeaderData, + rez.ObjectData); + } - #region Packet Session and User Check - if (m_checkPackets) + break; + + case PacketType.DetachAttachmentIntoInv: + UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; + if (handlerDetachAttachmentIntoInv != null) { - if (ocpacket.AgentData.SessionID != SessionId || - ocpacket.AgentData.AgentID != AgentId) - break; + DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; + + #region Packet Session and User Check + // UNSUPPORTED ON THIS PACKET + #endregion + + UUID itemID = detachtoInv.ObjectData.ItemID; + // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; + + handlerDetachAttachmentIntoInv(itemID, this); } - #endregion + break; - handlerObjectClickAction = OnObjectClickAction; - if (handlerObjectClickAction != null) + case PacketType.ObjectAttach: + if (OnObjectAttach != null) { - foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) + ObjectAttachPacket att = (ObjectAttachPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - byte action = odata.ClickAction; - uint localID = odata.ObjectLocalID; - handlerObjectClickAction(this, localID, action.ToString()); + if (att.AgentData.SessionID != SessionId || + att.AgentData.AgentID != AgentId) + break; + } + #endregion + + ObjectAttach handlerObjectAttach = OnObjectAttach; + + if (handlerObjectAttach != null) + { + if (att.ObjectData.Length > 0) + { + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); + } } } break; - case PacketType.ObjectMaterial: - ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; + case PacketType.ObjectDetach: + ObjectDetachPacket dett = (ObjectDetachPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ompacket.AgentData.SessionID != SessionId || - ompacket.AgentData.AgentID != AgentId) + if (dett.AgentData.SessionID != SessionId || + dett.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectMaterial = OnObjectMaterial; - if (handlerObjectMaterial != null) + for (int j = 0; j < dett.ObjectData.Length; j++) { - foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) + uint obj = dett.ObjectData[j].ObjectLocalID; + ObjectDeselect handlerObjectDetach = OnObjectDetach; + if (handlerObjectDetach != null) { - byte material = odata.Material; - uint localID = odata.ObjectLocalID; - handlerObjectMaterial(this, localID, material.ToString()); + handlerObjectDetach(obj, this); } + } break; - #endregion - - #region Inventory/Asset/Other related packets - - case PacketType.RequestImage: - RequestImagePacket imageRequest = (RequestImagePacket)Pack; - //m_log.Debug("image request: " + Pack.ToString()); - + case PacketType.ObjectDrop: + ObjectDropPacket dropp = (ObjectDropPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (imageRequest.AgentData.SessionID != SessionId || - imageRequest.AgentData.AgentID != AgentId) + if (dropp.AgentData.SessionID != SessionId || + dropp.AgentData.AgentID != AgentId) break; } #endregion - //handlerTextureRequest = null; - - for (int i = 0; i < imageRequest.RequestImage.Length; i++) + for (int j = 0; j < dropp.ObjectData.Length; j++) { - if (OnRequestTexture != null) + uint obj = dropp.ObjectData[j].ObjectLocalID; + ObjectDrop handlerObjectDrop = OnObjectDrop; + if (handlerObjectDrop != null) { - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = imageRequest.RequestImage[i].Image; - args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; - args.PacketNumber = imageRequest.RequestImage[i].Packet; - args.Priority = imageRequest.RequestImage[i].DownloadPriority; - args.requestSequence = imageRequest.Header.Sequence; - - //handlerTextureRequest = OnRequestTexture; - - //if (handlerTextureRequest != null) - //OnRequestTexture(this, args); - - // in the end, we null this, so we have to check if it's null - if (m_imageManager != null) - { - m_imageManager.EnqueueReq(args); - } + handlerObjectDrop(obj, this); } } break; - case PacketType.TransferRequest: - //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); + case PacketType.SetAlwaysRun: + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; - TransferRequestPacket transfer = (TransferRequestPacket)Pack; - //m_log.Debug("Transfer Request: " + transfer.ToString()); - // Validate inventory transfers - // Has to be done here, because AssetCache can't do it - // - - if (transfer.TransferInfo.SourceType == 3) + #region Packet Session and User Check + if (m_checkPackets) { - UUID taskID = new UUID(transfer.TransferInfo.Params, 48); - UUID itemID = new UUID(transfer.TransferInfo.Params, 64); - UUID requestID = new UUID(transfer.TransferInfo.Params, 80); - if (!(((Scene)m_scene).Permissions.BypassPermissions())) - { - if (taskID != UUID.Zero) // Prim - { - SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); - if (part == null) - break; - - if (part.OwnerID != AgentId) - break; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - break; + if (run.AgentData.SessionID != SessionId || + run.AgentData.AgentID != AgentId) + break; + } + #endregion - TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); - if (ti == null) - break; + SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun; + if (handlerSetAlwaysRun != null) + handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); - if (ti.OwnerID != AgentId) - break; + break; - if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - break; + case PacketType.CompleteAgentMovement: + GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; + if (handlerCompleteMovementToRegion != null) + { + handlerCompleteMovementToRegion(); + } + handlerCompleteMovementToRegion = null; - if (ti.AssetID != requestID) - break; - } - else // Agent - { - IInventoryService invService = m_scene.RequestModuleInterface(); - InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); - assetRequestItem = invService.GetItem(assetRequestItem); - if (assetRequestItem == null) - { - assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); - if (assetRequestItem == null) - return; - } + break; - // At this point, we need to apply perms - // only to notecards and scripts. All - // other asset types are always available - // - if (assetRequestItem.AssetType == 10) - { - if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view script", false); - break; - } - } - else if (assetRequestItem.AssetType == 7) - { - if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view notecard", false); - break; - } - } + case PacketType.AgentUpdate: + if (OnAgentUpdate != null) + { + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; - if (assetRequestItem.AssetID != requestID) - break; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (agenUpdate.AgentData.SessionID != SessionId || + agenUpdate.AgentData.AgentID != AgentId) + break; } - } - - //m_assetCache.AddAssetRequest(this, transfer); + #endregion - MakeAssetRequest(transfer); + AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - /* RequestAsset = OnRequestAsset; - if (RequestAsset != null) - { - RequestAsset(this, transfer); - }*/ - break; - case PacketType.AssetUploadRequest: - AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; + // We can only check when we have something to check + // against. - - // m_log.Debug("upload request " + request.ToString()); - // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); - UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); + if (lastarg != null) + { + update = + ( + (x.BodyRotation != lastarg.BodyRotation) || + (x.CameraAtAxis != lastarg.CameraAtAxis) || + (x.CameraCenter != lastarg.CameraCenter) || + (x.CameraLeftAxis != lastarg.CameraLeftAxis) || + (x.CameraUpAxis != lastarg.CameraUpAxis) || + (x.ControlFlags != lastarg.ControlFlags) || + (x.Far != lastarg.Far) || + (x.Flags != lastarg.Flags) || + (x.State != lastarg.State) || + (x.HeadRotation != lastarg.HeadRotation) || + (x.SessionID != lastarg.SessionID) || + (x.AgentID != lastarg.AgentID) + ); + } + else + update = true; - handlerAssetUploadRequest = OnAssetUploadRequest; + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. - if (handlerAssetUploadRequest != null) - { - handlerAssetUploadRequest(this, temp, - request.AssetBlock.TransactionID, request.AssetBlock.Type, - request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, - request.AssetBlock.Tempfile); - } - break; - case PacketType.RequestXfer: - RequestXferPacket xferReq = (RequestXferPacket)Pack; - - handlerRequestXfer = OnRequestXfer; + if (update) + { + AgentUpdateArgs arg = new AgentUpdateArgs(); + arg.AgentID = x.AgentID; + arg.BodyRotation = x.BodyRotation; + arg.CameraAtAxis = x.CameraAtAxis; + arg.CameraCenter = x.CameraCenter; + arg.CameraLeftAxis = x.CameraLeftAxis; + arg.CameraUpAxis = x.CameraUpAxis; + arg.ControlFlags = x.ControlFlags; + arg.Far = x.Far; + arg.Flags = x.Flags; + arg.HeadRotation = x.HeadRotation; + arg.SessionID = x.SessionID; + arg.State = x.State; + UpdateAgent handlerAgentUpdate = OnAgentUpdate; + lastarg = arg; // save this set of arguments for nexttime + if (handlerAgentUpdate != null) + OnAgentUpdate(this, arg); - if (handlerRequestXfer != null) - { - handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); - } - break; - case PacketType.SendXferPacket: - SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; + handlerAgentUpdate = null; + } - handlerXferReceive = OnXferReceive; - if (handlerXferReceive != null) - { - handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); - } - break; - case PacketType.ConfirmXferPacket: - ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; - - handlerConfirmXfer = OnConfirmXfer; - if (handlerConfirmXfer != null) - { - handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); } break; - case PacketType.AbortXfer: - AbortXferPacket abortXfer = (AbortXferPacket)Pack; - handlerAbortXfer = OnAbortXfer; - if (handlerAbortXfer != null) - { - handlerAbortXfer(this, abortXfer.XferID.ID); - } - break; - case PacketType.CreateInventoryFolder: - CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; + case PacketType.AgentAnimation: + AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFolder.AgentData.SessionID != SessionId || - invFolder.AgentData.AgentID != AgentId) + if (AgentAni.AgentData.SessionID != SessionId || + AgentAni.AgentData.AgentID != AgentId) break; } #endregion - handlerCreateInventoryFolder = OnCreateNewInventoryFolder; - if (handlerCreateInventoryFolder != null) + StartAnim handlerStartAnim = null; + StopAnim handlerStopAnim = null; + + for (int i = 0; i < AgentAni.AnimationList.Length; i++) { - handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, - (ushort)invFolder.FolderData.Type, - Util.FieldToString(invFolder.FolderData.Name), - invFolder.FolderData.ParentID); + if (AgentAni.AnimationList[i].StartAnim) + { + handlerStartAnim = OnStartAnim; + if (handlerStartAnim != null) + { + handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); + } + } + else + { + handlerStopAnim = OnStopAnim; + if (handlerStopAnim != null) + { + handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); + } + } } break; - case PacketType.UpdateInventoryFolder: - if (OnUpdateInventoryFolder != null) + + case PacketType.AgentRequestSit: + if (OnAgentRequestSit != null) { - UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; + AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFolderx.AgentData.SessionID != SessionId || - invFolderx.AgentData.AgentID != AgentId) + if (agentRequestSit.AgentData.SessionID != SessionId || + agentRequestSit.AgentData.AgentID != AgentId) break; } #endregion - handlerUpdateInventoryFolder = null; - - for (int i = 0; i < invFolderx.FolderData.Length; i++) - { - handlerUpdateInventoryFolder = OnUpdateInventoryFolder; - if (handlerUpdateInventoryFolder != null) - { - OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, - (ushort)invFolderx.FolderData[i].Type, - Util.FieldToString(invFolderx.FolderData[i].Name), - invFolderx.FolderData[i].ParentID); - } - } + AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; + if (handlerAgentRequestSit != null) + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); } break; - case PacketType.MoveInventoryFolder: - if (OnMoveInventoryFolder != null) + + case PacketType.AgentSit: + if (OnAgentSit != null) { - MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; + AgentSitPacket agentSit = (AgentSitPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFoldery.AgentData.SessionID != SessionId || - invFoldery.AgentData.AgentID != AgentId) + if (agentSit.AgentData.SessionID != SessionId || + agentSit.AgentData.AgentID != AgentId) break; } #endregion - handlerMoveInventoryFolder = null; - - for (int i = 0; i < invFoldery.InventoryData.Length; i++) + AgentSit handlerAgentSit = OnAgentSit; + if (handlerAgentSit != null) { - handlerMoveInventoryFolder = OnMoveInventoryFolder; - if (handlerMoveInventoryFolder != null) - { - OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, - invFoldery.InventoryData[i].ParentID); - } + OnAgentSit(this, agentSit.AgentData.AgentID); } } break; - case PacketType.CreateInventoryItem: - CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; - + + case PacketType.SoundTrigger: + SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (createItem.AgentData.SessionID != SessionId || - createItem.AgentData.AgentID != AgentId) - break; + // UNSUPPORTED ON THIS PACKET } #endregion - handlerCreateNewInventoryItem = OnCreateNewInventoryItem; - if (handlerCreateNewInventoryItem != null) + SoundTrigger handlerSoundTrigger = OnSoundTrigger; + if (handlerSoundTrigger != null) { - handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, - createItem.InventoryBlock.FolderID, - createItem.InventoryBlock.CallbackID, - Util.FieldToString(createItem.InventoryBlock.Description), - Util.FieldToString(createItem.InventoryBlock.Name), - createItem.InventoryBlock.InvType, - createItem.InventoryBlock.Type, - createItem.InventoryBlock.WearableType, - createItem.InventoryBlock.NextOwnerMask, - Util.UnixTimeSinceEpoch()); + handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, + soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, + soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, + soundTriggerPacket.SoundData.Handle); + } break; - case PacketType.FetchInventory: - if (OnFetchInventory != null) - { - FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (FetchInventoryx.AgentData.SessionID != SessionId || - FetchInventoryx.AgentData.AgentID != AgentId) - break; - } - #endregion + case PacketType.AvatarPickerRequest: + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; - handlerFetchInventory = null; + #region Packet Session and User Check + if (m_checkPackets) + { + if (avRequestQuery.AgentData.SessionID != SessionId || + avRequestQuery.AgentData.AgentID != AgentId) + break; + } + #endregion - for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) - { - handlerFetchInventory = OnFetchInventory; + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); - if (handlerFetchInventory != null) - { - OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, - FetchInventoryx.InventoryData[i].OwnerID); - } - } + AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest; + if (handlerAvatarPickerRequest != null) + { + handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, + Utils.BytesToString(querydata.Name)); } break; - case PacketType.FetchInventoryDescendents: - FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + + case PacketType.AgentDataUpdateRequest: + AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Fetch.AgentData.SessionID != SessionId || - Fetch.AgentData.AgentID != AgentId) + if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || + avRequestDataUpdatePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerFetchInventoryDescendents = OnFetchInventoryDescendents; - if (handlerFetchInventoryDescendents != null) + FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; + + if (handlerAgentDataUpdateRequest != null) { - handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, - Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, - Fetch.InventoryData.SortOrder); + handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); } + break; - case PacketType.PurgeInventoryDescendents: - PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + + case PacketType.UserInfoRequest: + UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest; + if (handlerUserInfoRequest != null) + { + handlerUserInfoRequest(this); + } + else + { + SendUserInfoReply(false, true, ""); + } + break; + + case PacketType.UpdateUserInfo: + UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Purge.AgentData.SessionID != SessionId || - Purge.AgentData.AgentID != AgentId) + if (updateUserInfo.AgentData.SessionID != SessionId || + updateUserInfo.AgentData.AgentID != AgentId) break; } #endregion - handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; - if (handlerPurgeInventoryDescendents != null) + UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo; + if (handlerUpdateUserInfo != null) { - handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + bool visible = true; + string DirectoryVisibility = + Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); + if (DirectoryVisibility == "hidden") + visible = false; + + handlerUpdateUserInfo( + updateUserInfo.UserData.IMViaEMail, + visible, this); } break; - case PacketType.UpdateInventoryItem: - UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; - + + case PacketType.SetStartLocationRequest: + SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (inventoryItemUpdate.AgentData.SessionID != SessionId || - inventoryItemUpdate.AgentData.AgentID != AgentId) + if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || + avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnUpdateInventoryItem != null) + if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) { - handlerUpdateInventoryItem = null; - for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest; + if (handlerSetStartLocationRequest != null) { - handlerUpdateInventoryItem = OnUpdateInventoryItem; - - if (handlerUpdateInventoryItem != null) - { - InventoryItemBase itemUpd = new InventoryItemBase(); - itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; - itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); - itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); - itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; - itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; - itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; - itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; - itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; - itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; - itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; - itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; - itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; - itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; - itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; - /* - OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, - inventoryItemUpdate.InventoryData[i].ItemID, - Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name), - Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description), - inventoryItemUpdate.InventoryData[i].NextOwnerMask); - */ - OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, - inventoryItemUpdate.InventoryData[i].ItemID, - itemUpd); - } + handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, + avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, + avSetStartLocationRequestPacket.StartLocationData.LocationID); } } - //m_log.Debug(Pack.ToString()); - /*for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) - { - if (inventoryItemUpdate.InventoryData[i].TransactionID != UUID.Zero) - { - AssetBase asset = m_assetCache.GetAsset(inventoryItemUpdate.InventoryData[i].TransactionID.Combine(this.SecureSessionId)); - if (asset != null) - { - // m_log.Debug("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache"); - m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); - } - else - { - asset = this.UploadAssets.AddUploadToAssetCache(inventoryItemUpdate.InventoryData[i].TransactionID); - if (asset != null) - { - //m_log.Debug("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache"); - m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); - } - else - { - //m_log.Debug("trying to update inventory item, but asset is null"); - } - } - } - else - { - m_inventoryCache.UpdateInventoryItemDetails(this, inventoryItemUpdate.InventoryData[i].ItemID, inventoryItemUpdate.InventoryData[i]); ; - } - }*/ break; - case PacketType.CopyInventoryItem: - CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; + + case PacketType.AgentThrottle: + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (atpack.AgentData.SessionID != SessionId || + atpack.AgentData.AgentID != AgentId) + break; + } + #endregion + + m_udpClient.SetThrottles(atpack.Throttle.Throttles); + break; + + case PacketType.AgentPause: + m_probesWithNoIngressPackets = 0; + m_clientBlocked = true; + break; + + case PacketType.AgentResume: + m_probesWithNoIngressPackets = 0; + m_clientBlocked = false; + SendStartPingCheck(0); + + break; + + case PacketType.ForceScriptControlRelease: + ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls; + if (handlerForceReleaseControls != null) + { + handlerForceReleaseControls(this, AgentId); + } + break; + + #endregion + + #region Objects/m_sceneObjects + + case PacketType.ObjectLink: + ObjectLinkPacket link = (ObjectLinkPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (copyitem.AgentData.SessionID != SessionId || - copyitem.AgentData.AgentID != AgentId) + if (link.AgentData.SessionID != SessionId || + link.AgentData.AgentID != AgentId) break; } #endregion - handlerCopyInventoryItem = null; - if (OnCopyInventoryItem != null) + uint parentprimid = 0; + List childrenprims = new List(); + if (link.ObjectData.Length > 1) { - foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + parentprimid = link.ObjectData[0].ObjectLocalID; + + for (int i = 1; i < link.ObjectData.Length; i++) { - handlerCopyInventoryItem = OnCopyInventoryItem; - if (handlerCopyInventoryItem != null) - { - handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, - datablock.OldItemID, datablock.NewFolderID, - Util.FieldToString(datablock.NewName)); - } + childrenprims.Add(link.ObjectData[i].ObjectLocalID); } } + LinkObjects handlerLinkObjects = OnLinkObjects; + if (handlerLinkObjects != null) + { + handlerLinkObjects(this, parentprimid, childrenprims); + } break; - case PacketType.MoveInventoryItem: - MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; + + case PacketType.ObjectDelink: + ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moveitem.AgentData.SessionID != SessionId || - moveitem.AgentData.AgentID != AgentId) + if (delink.AgentData.SessionID != SessionId || + delink.AgentData.AgentID != AgentId) break; } #endregion - if (OnMoveInventoryItem != null) + // It appears the prim at index 0 is not always the root prim (for + // instance, when one prim of a link set has been edited independently + // of the others). Therefore, we'll pass all the ids onto the delink + // method for it to decide which is the root. + List prims = new List(); + for (int i = 0; i < delink.ObjectData.Length; i++) { - handlerMoveInventoryItem = null; - InventoryItemBase itm = null; - List items = new List(); - foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) - { - itm = new InventoryItemBase(datablock.ItemID, AgentId); - itm.Folder = datablock.FolderID; - itm.Name = Util.FieldToString(datablock.NewName); - // weird, comes out as empty string - //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); - items.Add(itm); - } - handlerMoveInventoryItem = OnMoveInventoryItem; - if (handlerMoveInventoryItem != null) - { - handlerMoveInventoryItem(this, items); - } + prims.Add(delink.ObjectData[i].ObjectLocalID); } - break; - case PacketType.RemoveInventoryItem: - RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + DelinkObjects handlerDelinkObjects = OnDelinkObjects; + if (handlerDelinkObjects != null) { - if (removeItem.AgentData.SessionID != SessionId || - removeItem.AgentData.AgentID != AgentId) - break; + handlerDelinkObjects(prims); } - #endregion - if (OnRemoveInventoryItem != null) + break; + + case PacketType.ObjectAdd: + if (OnAddPrim != null) { - handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) + ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerRemoveInventoryItem(this, uuids); + if (addPacket.AgentData.SessionID != SessionId || + addPacket.AgentData.AgentID != AgentId) + break; } + #endregion + + PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); + // m_log.Info("[REZData]: " + addPacket.ToString()); + //BypassRaycast: 1 + //RayStart: <69.79469, 158.2652, 98.40343> + //RayEnd: <61.97724, 141.995, 92.58341> + //RayTargetID: 00000000-0000-0000-0000-000000000000 + + //Check to see if adding the prim is allowed; useful for any module wanting to restrict the + //object from rezing initially + AddNewPrim handlerAddPrim = OnAddPrim; + if (handlerAddPrim != null) + handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); } break; - case PacketType.RemoveInventoryFolder: - RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; + + case PacketType.ObjectShape: + ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeFolder.AgentData.SessionID != SessionId || - removeFolder.AgentData.AgentID != AgentId) + if (shapePacket.AgentData.SessionID != SessionId || + shapePacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryFolder != null) + UpdateShape handlerUpdatePrimShape = null; + for (int i = 0; i < shapePacket.ObjectData.Length; i++) { - handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) + handlerUpdatePrimShape = OnUpdatePrimShape; + if (handlerUpdatePrimShape != null) { - handlerRemoveInventoryFolder(this, uuids); + UpdateShapeArgs shapeData = new UpdateShapeArgs(); + shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; + shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; + shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; + shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; + shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; + shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; + shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; + shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; + shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; + shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; + shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; + shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; + shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; + shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; + shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; + shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; + shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; + shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; + shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; + + handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, + shapeData); } } break; - case PacketType.RemoveInventoryObjects: - RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; + + case PacketType.ObjectExtraParams: + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (removeObject.AgentData.SessionID != SessionId || - removeObject.AgentData.AgentID != AgentId) + if (extraPar.AgentData.SessionID != SessionId || + extraPar.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder(this, uuids); - } - } - if (OnRemoveInventoryItem != null) + ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams; + if (handlerUpdateExtraParams != null) { - handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) + for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) { - handlerRemoveInventoryItem(this, uuids); + handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, + extraPar.ObjectData[i].ParamType, + extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); } } break; - case PacketType.RequestTaskInventory: - RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (requesttask.AgentData.SessionID != SessionId || - requesttask.AgentData.AgentID != AgentId) + if (dupe.AgentData.SessionID != SessionId || + dupe.AgentData.AgentID != AgentId) break; } #endregion - handlerRequestTaskInventory = OnRequestTaskInventory; - if (handlerRequestTaskInventory != null) + ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + + ObjectDuplicate handlerObjectDuplicate = null; + + for (int i = 0; i < dupe.ObjectData.Length; i++) { - handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); + handlerObjectDuplicate = OnObjectDuplicate; + if (handlerObjectDuplicate != null) + { + handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, + dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, + AgentandGroupData.GroupID); + } } + break; - case PacketType.UpdateTaskInventory: - UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; + + case PacketType.RequestMultipleObjects: + RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (updatetask.AgentData.SessionID != SessionId || - updatetask.AgentData.AgentID != AgentId) - break; - } - #endregion - - if (OnUpdateTaskInventory != null) - { - if (updatetask.UpdateData.Key == 0) - { - handlerUpdateTaskInventory = OnUpdateTaskInventory; - if (handlerUpdateTaskInventory != null) - { - TaskInventoryItem newTaskItem = new TaskInventoryItem(); - newTaskItem.ItemID = updatetask.InventoryData.ItemID; - newTaskItem.ParentID = updatetask.InventoryData.FolderID; - newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; - newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; - newTaskItem.GroupID = updatetask.InventoryData.GroupID; - newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; - newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; - newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; - newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; - newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; - //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; - newTaskItem.Type = updatetask.InventoryData.Type; - newTaskItem.InvType = updatetask.InventoryData.InvType; - newTaskItem.Flags = updatetask.InventoryData.Flags; - //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; - newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); - newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); - newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; - handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, - newTaskItem, updatetask.UpdateData.LocalID); - } - } + if (incomingRequest.AgentData.SessionID != SessionId || + incomingRequest.AgentData.AgentID != AgentId) + break; } + #endregion - break; - - case PacketType.RemoveTaskInventory: + ObjectRequest handlerObjectRequest = null; - RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; + for (int i = 0; i < incomingRequest.ObjectData.Length; i++) + { + handlerObjectRequest = OnObjectRequest; + if (handlerObjectRequest != null) + { + handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); + } + } + break; + case PacketType.ObjectSelect: + ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeTask.AgentData.SessionID != SessionId || - removeTask.AgentData.AgentID != AgentId) + if (incomingselect.AgentData.SessionID != SessionId || + incomingselect.AgentData.AgentID != AgentId) break; } #endregion - handlerRemoveTaskItem = OnRemoveTaskItem; + ObjectSelect handlerObjectSelect = null; - if (handlerRemoveTaskItem != null) + for (int i = 0; i < incomingselect.ObjectData.Length; i++) { - handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); + handlerObjectSelect = OnObjectSelect; + if (handlerObjectSelect != null) + { + handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); + } } - break; - - case PacketType.MoveTaskInventory: - - MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; + case PacketType.ObjectDeselect: + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || - moveTaskInventoryPacket.AgentData.AgentID != AgentId) + if (incomingdeselect.AgentData.SessionID != SessionId || + incomingdeselect.AgentData.AgentID != AgentId) break; } #endregion - handlerMoveTaskItem = OnMoveTaskItem; + ObjectDeselect handlerObjectDeselect = null; - if (handlerMoveTaskItem != null) + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) { - handlerMoveTaskItem( - this, moveTaskInventoryPacket.AgentData.FolderID, - moveTaskInventoryPacket.InventoryData.LocalID, - moveTaskInventoryPacket.InventoryData.ItemID); + handlerObjectDeselect = OnObjectDeselect; + if (handlerObjectDeselect != null) + { + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); + } } - break; - - case PacketType.RezScript: - //m_log.Debug(Pack.ToString()); - RezScriptPacket rezScriptx = (RezScriptPacket)Pack; + case PacketType.ObjectPosition: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectPositionPacket position = (ObjectPositionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rezScriptx.AgentData.SessionID != SessionId || - rezScriptx.AgentData.AgentID != AgentId) + if (position.AgentData.SessionID != SessionId || + position.AgentData.AgentID != AgentId) break; } #endregion - handlerRezScript = OnRezScript; - InventoryItemBase item = new InventoryItemBase(); - item.ID = rezScriptx.InventoryBlock.ItemID; - item.Folder = rezScriptx.InventoryBlock.FolderID; - item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); - item.Owner = rezScriptx.InventoryBlock.OwnerID; - item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; - item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; - item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; - item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; - item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; - item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; - item.GroupID = rezScriptx.InventoryBlock.GroupID; - item.AssetType = rezScriptx.InventoryBlock.Type; - item.InvType = rezScriptx.InventoryBlock.InvType; - item.Flags = rezScriptx.InventoryBlock.Flags; - item.SaleType = rezScriptx.InventoryBlock.SaleType; - item.SalePrice = rezScriptx.InventoryBlock.SalePrice; - item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); - item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); - item.CreationDate = rezScriptx.InventoryBlock.CreationDate; - if (handlerRezScript != null) + for (int i = 0; i < position.ObjectData.Length; i++) { - handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; + if (handlerUpdateVector != null) + handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); } - break; - case PacketType.MapLayerRequest: - RequestMapLayer(); break; - case PacketType.MapBlockRequest: - MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; + case PacketType.ObjectScale: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectScalePacket scale = (ObjectScalePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (MapRequest.AgentData.SessionID != SessionId || - MapRequest.AgentData.AgentID != AgentId) + if (scale.AgentData.SessionID != SessionId || + scale.AgentData.AgentID != AgentId) break; } #endregion - handlerRequestMapBlocks = OnRequestMapBlocks; - if (handlerRequestMapBlocks != null) + for (int i = 0; i < scale.ObjectData.Length; i++) { - handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, - MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); + UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); } + break; - case PacketType.MapNameRequest: - MapNameRequestPacket map = (MapNameRequestPacket)Pack; + case PacketType.ObjectRotation: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (map.AgentData.SessionID != SessionId || - map.AgentData.AgentID != AgentId) + if (rotation.AgentData.SessionID != SessionId || + rotation.AgentData.AgentID != AgentId) break; } #endregion - string mapName = Util.UTF8.GetString(map.NameData.Name, 0, - map.NameData.Name.Length - 1); - handlerMapNameRequest = OnMapNameRequest; - if (handlerMapNameRequest != null) + for (int i = 0; i < rotation.ObjectData.Length; i++) { - handlerMapNameRequest(this, mapName); + UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); } + break; - case PacketType.TeleportLandmarkRequest: - TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; + case PacketType.ObjectFlagUpdate: + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (tpReq.Info.SessionID != SessionId || - tpReq.Info.AgentID != AgentId) + if (flags.AgentData.SessionID != SessionId || + flags.AgentData.AgentID != AgentId) break; } #endregion - UUID lmid = tpReq.Info.LandmarkID; - AssetLandmark lm; - if (lmid != UUID.Zero) - { - //AssetBase lma = m_assetCache.GetAsset(lmid, false); - AssetBase lma = m_assetService.Get(lmid.ToString()); - - if (lma == null) - { - // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - } + UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags; - try - { - lm = new AssetLandmark(lma); - } - catch (NullReferenceException) - { - // asset not found generates null ref inside the assetlandmark constructor. - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - break; - } + if (handlerUpdatePrimFlags != null) + { + byte[] data = Pack.ToBytes(); + // 46,47,48 are special positions within the packet + // This may change so perhaps we need a better way + // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) + bool UsePhysics = (data[46] != 0) ? true : false; + bool IsTemporary = (data[47] != 0) ? true : false; + bool IsPhantom = (data[48] != 0) ? true : false; + handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); } - else + break; + case PacketType.ObjectImage: + ObjectImagePacket imagePack = (ObjectImagePacket)Pack; + + UpdatePrimTexture handlerUpdatePrimTexture = null; + for (int i = 0; i < imagePack.ObjectData.Length; i++) { - // Teleport home request - handlerTeleportHomeRequest = OnTeleportHomeRequest; - if (handlerTeleportHomeRequest != null) + handlerUpdatePrimTexture = OnUpdatePrimTexture; + if (handlerUpdatePrimTexture != null) { - handlerTeleportHomeRequest(AgentId, this); + handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, + imagePack.ObjectData[i].TextureEntry, this); } - break; } + break; + case PacketType.ObjectGrab: + ObjectGrabPacket grab = (ObjectGrabPacket)Pack; - handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; - if (handlerTeleportLandmarkRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + if (grab.AgentData.SessionID != SessionId || + grab.AgentData.AgentID != AgentId) + break; } - else - { - //no event handler so cancel request - + #endregion - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.AgentID = tpReq.Info.AgentID; - tpCancel.Info.SessionID = tpReq.Info.SessionID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + GrabObject handlerGrabObject = OnGrabObject; + if (handlerGrabObject != null) + { + List touchArgs = new List(); + if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) + { + foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } + } + handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); } break; - - case PacketType.TeleportLocationRequest: - TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; - // m_log.Debug(tpLocReq.ToString()); + case PacketType.ObjectGrabUpdate: + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (tpLocReq.AgentData.SessionID != SessionId || - tpLocReq.AgentData.AgentID != AgentId) + if (grabUpdate.AgentData.SessionID != SessionId || + grabUpdate.AgentData.AgentID != AgentId) break; } #endregion - handlerTeleportLocationRequest = OnTeleportLocationRequest; - if (handlerTeleportLocationRequest != null) - { - handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, - tpLocReq.Info.LookAt, 16); - } - else + MoveObject handlerGrabUpdate = OnGrabUpdate; + + if (handlerGrabUpdate != null) { - //no event handler so cancel request - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; - tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + List touchArgs = new List(); + if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) + { + foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } + } + handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, + grabUpdate.ObjectData.GrabPosition, this, touchArgs); } break; + case PacketType.ObjectDeGrab: + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (deGrab.AgentData.SessionID != SessionId || + deGrab.AgentData.AgentID != AgentId) + break; + } #endregion - case PacketType.UUIDNameRequest: - UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; - - foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + DeGrabObject handlerDeGrabObject = OnDeGrabObject; + if (handlerDeGrabObject != null) { - handlerNameRequest = OnNameFromUUIDRequest; - if (handlerNameRequest != null) + List touchArgs = new List(); + if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) { - handlerNameRequest(UUIDBlock.ID, this); + foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } } + handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); } break; - - #region Parcel related packets - - case PacketType.RegionHandleRequest: - RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; - - handlerRegionHandleRequest = OnRegionHandleRequest; - if (handlerRegionHandleRequest != null) - { - handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); - } - break; - - case PacketType.ParcelInfoRequest: - ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; + case PacketType.ObjectSpinStart: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); + ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pirPack.AgentData.SessionID != SessionId || - pirPack.AgentData.AgentID != AgentId) + if (spinStart.AgentData.SessionID != SessionId || + spinStart.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelInfoRequest = OnParcelInfoRequest; - if (handlerParcelInfoRequest != null) + SpinStart handlerSpinStart = OnSpinStart; + if (handlerSpinStart != null) { - handlerParcelInfoRequest(this, pirPack.Data.ParcelID); + handlerSpinStart(spinStart.ObjectData.ObjectID, this); } break; - - case PacketType.ParcelAccessListRequest: - ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; + case PacketType.ObjectSpinUpdate: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); + ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (requestPacket.AgentData.SessionID != SessionId || - requestPacket.AgentData.AgentID != AgentId) + if (spinUpdate.AgentData.SessionID != SessionId || + spinUpdate.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelAccessListRequest = OnParcelAccessListRequest; + Vector3 axis; + float angle; + spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); + //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); - if (handlerParcelAccessListRequest != null) + SpinObject handlerSpinUpdate = OnSpinUpdate; + if (handlerSpinUpdate != null) { - handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, - requestPacket.Data.Flags, requestPacket.Data.SequenceID, - requestPacket.Data.LocalID, this); + handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); } break; - - case PacketType.ParcelAccessListUpdate: - ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; + case PacketType.ObjectSpinStop: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); + ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (updatePacket.AgentData.SessionID != SessionId || - updatePacket.AgentData.AgentID != AgentId) + if (spinStop.AgentData.SessionID != SessionId || + spinStop.AgentData.AgentID != AgentId) break; } #endregion - List entries = new List(); - foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = block.ID; - entry.Flags = (AccessList)block.Flags; - entry.Time = new DateTime(); - entries.Add(entry); - } - - handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; - if (handlerParcelAccessListUpdateRequest != null) + SpinStop handlerSpinStop = OnSpinStop; + if (handlerSpinStop != null) { - handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, - updatePacket.AgentData.SessionID, updatePacket.Data.Flags, - updatePacket.Data.LocalID, entries, this); + handlerSpinStop(spinStop.ObjectData.ObjectID, this); } break; - case PacketType.ParcelPropertiesRequest: - ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; + case PacketType.ObjectDescription: + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (propertiesRequest.AgentData.SessionID != SessionId || - propertiesRequest.AgentData.AgentID != AgentId) + if (objDes.AgentData.SessionID != SessionId || + objDes.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelPropertiesRequest = OnParcelPropertiesRequest; - if (handlerParcelPropertiesRequest != null) + GenericCall7 handlerObjectDescription = null; + + for (int i = 0; i < objDes.ObjectData.Length; i++) { - handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), - (int)Math.Round(propertiesRequest.ParcelData.South), - (int)Math.Round(propertiesRequest.ParcelData.East), - (int)Math.Round(propertiesRequest.ParcelData.North), - propertiesRequest.ParcelData.SequenceID, - propertiesRequest.ParcelData.SnapSelection, this); + handlerObjectDescription = OnObjectDescription; + if (handlerObjectDescription != null) + { + handlerObjectDescription(this, objDes.ObjectData[i].LocalID, + Util.FieldToString(objDes.ObjectData[i].Description)); + } } break; - case PacketType.ParcelDivide: - ParcelDividePacket landDivide = (ParcelDividePacket)Pack; - + case PacketType.ObjectName: + ObjectNamePacket objName = (ObjectNamePacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (landDivide.AgentData.SessionID != SessionId || - landDivide.AgentData.AgentID != AgentId) + if (objName.AgentData.SessionID != SessionId || + objName.AgentData.AgentID != AgentId) break; } #endregion - - handlerParcelDivideRequest = OnParcelDivideRequest; - if (handlerParcelDivideRequest != null) + + GenericCall7 handlerObjectName = null; + for (int i = 0; i < objName.ObjectData.Length; i++) { - handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), - (int)Math.Round(landDivide.ParcelData.South), - (int)Math.Round(landDivide.ParcelData.East), - (int)Math.Round(landDivide.ParcelData.North), this); + handlerObjectName = OnObjectName; + if (handlerObjectName != null) + { + handlerObjectName(this, objName.ObjectData[i].LocalID, + Util.FieldToString(objName.ObjectData[i].Name)); + } } break; - case PacketType.ParcelJoin: - ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; + case PacketType.ObjectPermissions: + if (OnObjectPermissions != null) + { + ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (newobjPerms.AgentData.SessionID != SessionId || + newobjPerms.AgentData.AgentID != AgentId) + break; + } + #endregion + + UUID AgentID = newobjPerms.AgentData.AgentID; + UUID SessionID = newobjPerms.AgentData.SessionID; + + ObjectPermissions handlerObjectPermissions = null; + + for (int i = 0; i < newobjPerms.ObjectData.Length; i++) + { + ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; + + byte field = permChanges.Field; + uint localID = permChanges.ObjectLocalID; + uint mask = permChanges.Mask; + byte set = permChanges.Set; + + handlerObjectPermissions = OnObjectPermissions; + + if (handlerObjectPermissions != null) + handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); + } + } + + // Here's our data, + // PermField contains the field the info goes into + // PermField determines which mask we're changing + // + // chmask is the mask of the change + // setTF is whether we're adding it or taking it away + // + // objLocalID is the localID of the object. + + // Unfortunately, we have to pass the event the packet because objData is an array + // That means multiple object perms may be updated in a single packet. + + break; + + case PacketType.Undo: + UndoPacket undoitem = (UndoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (landJoin.AgentData.SessionID != SessionId || - landJoin.AgentData.AgentID != AgentId) + if (undoitem.AgentData.SessionID != SessionId || + undoitem.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelJoinRequest = OnParcelJoinRequest; - - if (handlerParcelJoinRequest != null) + if (undoitem.ObjectData.Length > 0) { - handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), - (int)Math.Round(landJoin.ParcelData.South), - (int)Math.Round(landJoin.ParcelData.East), - (int)Math.Round(landJoin.ParcelData.North), this); + for (int i = 0; i < undoitem.ObjectData.Length; i++) + { + UUID objiD = undoitem.ObjectData[i].ObjectID; + AgentSit handlerOnUndo = OnUndo; + if (handlerOnUndo != null) + { + handlerOnUndo(this, objiD); + } + + } } break; - case PacketType.ParcelPropertiesUpdate: - ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; + case PacketType.ObjectDuplicateOnRay: + ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (parcelPropertiesPacket.AgentData.SessionID != SessionId || - parcelPropertiesPacket.AgentData.AgentID != AgentId) + if (dupeOnRay.AgentData.SessionID != SessionId || + dupeOnRay.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; + ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null; - if (handlerParcelPropertiesUpdateRequest != null) + for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) { - LandUpdateArgs args = new LandUpdateArgs(); - - args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; - args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; - args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); - args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; - args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; - args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; - args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; - args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); - args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); - args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); - args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; - args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; - args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; - args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; - args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; - args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; - args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; - handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); + handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; + if (handlerObjectDuplicateOnRay != null) + { + handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, + dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, + dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); + } } + break; - case PacketType.ParcelSelectObjects: - ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; + case PacketType.RequestObjectPropertiesFamily: + //This powers the little tooltip that appears when you move your mouse over an object + RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (selectPacket.AgentData.SessionID != SessionId || - selectPacket.AgentData.AgentID != AgentId) + if (packToolTip.AgentData.SessionID != SessionId || + packToolTip.AgentData.AgentID != AgentId) break; } #endregion - List returnIDs = new List(); - - foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in - selectPacket.ReturnIDs) - { - returnIDs.Add(rb.ReturnID); - } + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; - handlerParcelSelectObjects = OnParcelSelectObjects; + RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; - if (handlerParcelSelectObjects != null) + if (handlerRequestObjectPropertiesFamily != null) { - handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, - Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); + handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, + packObjBlock.ObjectID); } + break; - case PacketType.ParcelObjectOwnersRequest: - //m_log.Debug(Pack.ToString()); - ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + case PacketType.ObjectIncludeInSearch: + //This lets us set objects to appear in search (stuff like DataSnapshot, etc) + ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; + ObjectIncludeInSearch handlerObjectIncludeInSearch = null; #region Packet Session and User Check if (m_checkPackets) { - if (reqPacket.AgentData.SessionID != SessionId || - reqPacket.AgentData.AgentID != AgentId) + if (packInSearch.AgentData.SessionID != SessionId || + packInSearch.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; - - if (handlerParcelObjectOwnerRequest != null) + foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) { - handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); + bool inSearch = objData.IncludeInSearch; + uint localID = objData.ObjectLocalID; + + handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + + if (handlerObjectIncludeInSearch != null) + { + handlerObjectIncludeInSearch(this, inSearch, localID); + } } break; - case PacketType.ParcelGodForceOwner: - ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; + + case PacketType.ScriptAnswerYes: + ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (godForceOwnerPacket.AgentData.SessionID != SessionId || - godForceOwnerPacket.AgentData.AgentID != AgentId) + if (scriptAnswer.AgentData.SessionID != SessionId || + scriptAnswer.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelGodForceOwner = OnParcelGodForceOwner; - if (handlerParcelGodForceOwner != null) + ScriptAnswer handlerScriptAnswer = OnScriptAnswer; + if (handlerScriptAnswer != null) { - handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); + handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); } break; - case PacketType.ParcelRelease: - ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; + + case PacketType.ObjectClickAction: + ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (releasePacket.AgentData.SessionID != SessionId || - releasePacket.AgentData.AgentID != AgentId) + if (ocpacket.AgentData.SessionID != SessionId || + ocpacket.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelAbandonRequest = OnParcelAbandonRequest; - if (handlerParcelAbandonRequest != null) + GenericCall7 handlerObjectClickAction = OnObjectClickAction; + if (handlerObjectClickAction != null) { - handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); + foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) + { + byte action = odata.ClickAction; + uint localID = odata.ObjectLocalID; + handlerObjectClickAction(this, localID, action.ToString()); + } } break; - case PacketType.ParcelReclaim: - ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; + + case PacketType.ObjectMaterial: + ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (reclaimPacket.AgentData.SessionID != SessionId || - reclaimPacket.AgentData.AgentID != AgentId) + if (ompacket.AgentData.SessionID != SessionId || + ompacket.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelReclaim = OnParcelReclaim; - if (handlerParcelReclaim != null) + GenericCall7 handlerObjectMaterial = OnObjectMaterial; + if (handlerObjectMaterial != null) { - handlerParcelReclaim(reclaimPacket.Data.LocalID, this); + foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) + { + byte material = odata.Material; + uint localID = odata.ObjectLocalID; + handlerObjectMaterial(this, localID, material.ToString()); + } } break; - case PacketType.ParcelReturnObjects: + #endregion - ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; + #region Inventory/Asset/Other related packets + case PacketType.RequestImage: + RequestImagePacket imageRequest = (RequestImagePacket)Pack; + //m_log.Debug("image request: " + Pack.ToString()); + #region Packet Session and User Check if (m_checkPackets) { - if (parcelReturnObjects.AgentData.SessionID != SessionId || - parcelReturnObjects.AgentData.AgentID != AgentId) + if (imageRequest.AgentData.SessionID != SessionId || + imageRequest.AgentData.AgentID != AgentId) break; } #endregion - UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; - for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) - puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; + //handlerTextureRequest = null; - UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; + for (int i = 0; i < imageRequest.RequestImage.Length; i++) + { + if (OnRequestTexture != null) + { + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = imageRequest.RequestImage[i].Image; + args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + args.PacketNumber = imageRequest.RequestImage[i].Packet; + args.Priority = imageRequest.RequestImage[i].DownloadPriority; + args.requestSequence = imageRequest.Header.Sequence; - for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) - puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; + //handlerTextureRequest = OnRequestTexture; - handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; - if (handlerParcelReturnObjectsRequest != null) - { - handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); + //if (handlerTextureRequest != null) + //OnRequestTexture(this, args); + // in the end, we null this, so we have to check if it's null + if (m_imageManager != null) + { + m_imageManager.EnqueueReq(args); + } + } } break; - case PacketType.ParcelSetOtherCleanTime: - ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; + case PacketType.TransferRequest: + //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); - #region Packet Session and User Check - if (m_checkPackets) + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + //m_log.Debug("Transfer Request: " + transfer.ToString()); + // Validate inventory transfers + // Has to be done here, because AssetCache can't do it + // + + if (transfer.TransferInfo.SourceType == 3) { - if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || - parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + UUID taskID = new UUID(transfer.TransferInfo.Params, 48); + UUID itemID = new UUID(transfer.TransferInfo.Params, 64); + UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + if (!(((Scene)m_scene).Permissions.BypassPermissions())) + { + if (taskID != UUID.Zero) // Prim + { + SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + if (part == null) + break; - handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; - if (handlerParcelSetOtherCleanTime != null) - { - handlerParcelSetOtherCleanTime(this, - parcelSetOtherCleanTimePacket.ParcelData.LocalID, - parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); + if (part.OwnerID != AgentId) + break; + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + break; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); + if (ti == null) + break; + + if (ti.OwnerID != AgentId) + break; + + if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + break; + + if (ti.AssetID != requestID) + break; + } + else // Agent + { + IInventoryService invService = m_scene.RequestModuleInterface(); + InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); + assetRequestItem = invService.GetItem(assetRequestItem); + if (assetRequestItem == null) + { + assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); + if (assetRequestItem == null) + return; + } + + // At this point, we need to apply perms + // only to notecards and scripts. All + // other asset types are always available + // + if (assetRequestItem.AssetType == 10) + { + if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view script", false); + break; + } + } + else if (assetRequestItem.AssetType == 7) + { + if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view notecard", false); + break; + } + } + + if (assetRequestItem.AssetID != requestID) + break; + } + } } + + //m_assetCache.AddAssetRequest(this, transfer); + + MakeAssetRequest(transfer); + + /* RequestAsset = OnRequestAsset; + if (RequestAsset != null) + { + RequestAsset(this, transfer); + }*/ break; + case PacketType.AssetUploadRequest: + AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - case PacketType.LandStatRequest: - LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; + + // m_log.Debug("upload request " + request.ToString()); + // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); + UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); - #region Packet Session and User Check - if (m_checkPackets) + UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest; + + if (handlerAssetUploadRequest != null) { - if (lsrp.AgentData.SessionID != SessionId || - lsrp.AgentData.AgentID != AgentId) - break; + handlerAssetUploadRequest(this, temp, + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, + request.AssetBlock.Tempfile); } - #endregion + break; + case PacketType.RequestXfer: + RequestXferPacket xferReq = (RequestXferPacket)Pack; + + RequestXfer handlerRequestXfer = OnRequestXfer; - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + if (handlerRequestXfer != null) { - handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); + handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); } break; + case PacketType.SendXferPacket: + SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; - case PacketType.ParcelDwellRequest: - ParcelDwellRequestPacket dwellrq = - (ParcelDwellRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + XferReceive handlerXferReceive = OnXferReceive; + if (handlerXferReceive != null) { - if (dwellrq.AgentData.SessionID != SessionId || - dwellrq.AgentData.AgentID != AgentId) - break; + handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); } - #endregion - - handlerParcelDwellRequest = OnParcelDwellRequest; - if (handlerParcelDwellRequest != null) + break; + case PacketType.ConfirmXferPacket: + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; + + ConfirmXfer handlerConfirmXfer = OnConfirmXfer; + if (handlerConfirmXfer != null) { - handlerParcelDwellRequest(dwellrq.Data.LocalID, this); + handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); } break; + case PacketType.AbortXfer: + AbortXferPacket abortXfer = (AbortXferPacket)Pack; + AbortXfer handlerAbortXfer = OnAbortXfer; + if (handlerAbortXfer != null) + { + handlerAbortXfer(this, abortXfer.XferID.ID); + } - #endregion - - #region Estate Packets - - case PacketType.EstateOwnerMessage: - EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; - //m_log.Debug(messagePacket.ToString()); + break; + case PacketType.CreateInventoryFolder: + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (messagePacket.AgentData.SessionID != SessionId || - messagePacket.AgentData.AgentID != AgentId) + if (invFolder.AgentData.SessionID != SessionId || + invFolder.AgentData.AgentID != AgentId) break; } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder; + if (handlerCreateInventoryFolder != null) { - case "getinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); - } - break; - case "setregioninfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), - convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), - Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), - (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), - Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), - convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); - } - break; -// case "texturebase": -// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) -// { -// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) -// { -// string s = Utils.BytesToString(block.Parameter); -// string[] splitField = s.Split(' '); -// if (splitField.Length == 2) -// { -// UUID tempUUID = new UUID(splitField[1]); -// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); -// } -// } -// } -// break; - case "texturedetail": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 2) - { - Int16 corner = Convert.ToInt16(splitField[0]); - UUID textureUUID = new UUID(splitField[1]); - - OnSetEstateTerrainDetailTexture(this, corner, textureUUID); - } - } - } - - break; - case "textureheights": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 3) - { - Int16 corner = Convert.ToInt16(splitField[0]); - float lowValue = (float)Convert.ToDecimal(splitField[1]); - float highValue = (float)Convert.ToDecimal(splitField[2]); - - OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); - } - } - } - break; - case "texturecommit": - OnCommitEstateTerrainTextureRequest(this); - break; - case "setregionterrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length != 9) - { - m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); - } - else - { - try - { - string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float WaterHeight = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); - bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); - bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); - float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); - bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); - bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); - float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); - - OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); - - } - catch (Exception ex) - { - m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); - } - } - } - - break; - case "restart": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - float timeSeconds; - Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); - timeSeconds = (int)timeSeconds; - OnEstateRestartSimRequest(this, (int)timeSeconds); - - } - } - break; - case "estatechangecovenantid": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); - OnEstateChangeCovenantRequest(this, newCovenantID); - } - } - break; - case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); - - } - break; - case "simulatormessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "instantmessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length < 5) - break; - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "setregiondebug": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); - bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); - bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); + handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort)invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + break; + case PacketType.UpdateInventoryFolder: + if (OnUpdateInventoryFolder != null) + { + UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; - OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); - } - break; - case "teleporthomeuser": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UUID Prey; + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFolderx.AgentData.SessionID != SessionId || + invFolderx.AgentData.AgentID != AgentId) + break; + } + #endregion - UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); + UpdateInventoryFolder handlerUpdateInventoryFolder = null; - OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); - } - break; - case "teleporthomeallusers": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + for (int i = 0; i < invFolderx.FolderData.Length; i++) + { + handlerUpdateInventoryFolder = OnUpdateInventoryFolder; + if (handlerUpdateInventoryFolder != null) { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); + OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, + (ushort)invFolderx.FolderData[i].Type, + Util.FieldToString(invFolderx.FolderData[i].Name), + invFolderx.FolderData[i].ParentID); } - break; - case "colliders": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + } + } + break; + case PacketType.MoveInventoryFolder: + if (OnMoveInventoryFolder != null) + { + MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFoldery.AgentData.SessionID != SessionId || + invFoldery.AgentData.AgentID != AgentId) + break; + } + #endregion + + MoveInventoryFolder handlerMoveInventoryFolder = null; + + for (int i = 0; i < invFoldery.InventoryData.Length; i++) + { + handlerMoveInventoryFolder = OnMoveInventoryFolder; + if (handlerMoveInventoryFolder != null) { - handlerLandStatRequest(0, 1, 0, "", this); + OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, + invFoldery.InventoryData[i].ParentID); } + } + } + break; + case PacketType.CreateInventoryItem: + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createItem.AgentData.SessionID != SessionId || + createItem.AgentData.AgentID != AgentId) break; - case "scripts": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + } + #endregion + + CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem; + if (handlerCreateNewInventoryItem != null) + { + handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, + createItem.InventoryBlock.FolderID, + createItem.InventoryBlock.CallbackID, + Util.FieldToString(createItem.InventoryBlock.Description), + Util.FieldToString(createItem.InventoryBlock.Name), + createItem.InventoryBlock.InvType, + createItem.InventoryBlock.Type, + createItem.InventoryBlock.WearableType, + createItem.InventoryBlock.NextOwnerMask, + Util.UnixTimeSinceEpoch()); + } + break; + case PacketType.FetchInventory: + if (OnFetchInventory != null) + { + FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (FetchInventoryx.AgentData.SessionID != SessionId || + FetchInventoryx.AgentData.AgentID != AgentId) + break; + } + #endregion + + FetchInventory handlerFetchInventory = null; + + for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) + { + handlerFetchInventory = OnFetchInventory; + + if (handlerFetchInventory != null) { - handlerLandStatRequest(0, 0, 0, "", this); + OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, + FetchInventoryx.InventoryData[i].OwnerID); } + } + } + break; + case PacketType.FetchInventoryDescendents: + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (Fetch.AgentData.SessionID != SessionId || + Fetch.AgentData.AgentID != AgentId) break; - case "terrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length > 0) - { - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") - { - handlerBakeTerrain = OnBakeTerrain; - if (handlerBakeTerrain != null) - { - handlerBakeTerrain(this); - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") - { - if (messagePacket.ParamList.Length > 1) - { - handlerRequestTerrain = OnRequestTerrain; - if (handlerRequestTerrain != null) - { - handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") - { - if (messagePacket.ParamList.Length > 1) - { - handlerUploadTerrain = OnUploadTerrain; - if (handlerUploadTerrain != null) - { - handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } + } + #endregion - } + FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents; + if (handlerFetchInventoryDescendents != null) + { + handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); + } + break; + case PacketType.PurgeInventoryDescendents: + PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (Purge.AgentData.SessionID != SessionId || + Purge.AgentData.AgentID != AgentId) + break; + } + #endregion - } + PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; + if (handlerPurgeInventoryDescendents != null) + { + handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + } + break; + case PacketType.UpdateInventoryItem: + UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (inventoryItemUpdate.AgentData.SessionID != SessionId || + inventoryItemUpdate.AgentData.AgentID != AgentId) break; + } + #endregion - case "estatechangeinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + if (OnUpdateInventoryItem != null) + { + UpdateInventoryItem handlerUpdateInventoryItem = null; + for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + { + handlerUpdateInventoryItem = OnUpdateInventoryItem; + + if (handlerUpdateInventoryItem != null) { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + InventoryItemBase itemUpd = new InventoryItemBase(); + itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; + itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); + itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); + itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; + itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; + itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; + itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; + itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; + itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; + itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; + itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; + itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; + itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; + itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; - handlerEstateChangeInfo = OnEstateChangeInfo; - if (handlerEstateChangeInfo != null) - { - handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); - } + OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, + inventoryItemUpdate.InventoryData[i].ItemID, + itemUpd); } - break; + } + } + break; + case PacketType.CopyInventoryItem: + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; - default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + #region Packet Session and User Check + if (m_checkPackets) + { + if (copyitem.AgentData.SessionID != SessionId || + copyitem.AgentData.AgentID != AgentId) break; } - - //int parcelID, uint reportType, uint requestflags, string filter - - //lsrp.RequestData.ParcelLocalID; - //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts - //lsrp.RequestData.RequestFlags; - //lsrp.RequestData.Filter; + #endregion + CopyInventoryItem handlerCopyInventoryItem = null; + if (OnCopyInventoryItem != null) + { + foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + { + handlerCopyInventoryItem = OnCopyInventoryItem; + if (handlerCopyInventoryItem != null) + { + handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, + datablock.OldItemID, datablock.NewFolderID, + Util.FieldToString(datablock.NewName)); + } + } + } break; - - case PacketType.RequestRegionInfo: - RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; + case PacketType.MoveInventoryItem: + MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (mPacket.SessionID != SessionId || - mPacket.AgentID != AgentId) + if (moveitem.AgentData.SessionID != SessionId || + moveitem.AgentData.AgentID != AgentId) break; } #endregion - handlerRegionInfoRequest = OnRegionInfoRequest; - if (handlerRegionInfoRequest != null) + if (OnMoveInventoryItem != null) { - handlerRegionInfoRequest(this); + MoveInventoryItem handlerMoveInventoryItem = null; + InventoryItemBase itm = null; + List items = new List(); + foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) + { + itm = new InventoryItemBase(datablock.ItemID, AgentId); + itm.Folder = datablock.FolderID; + itm.Name = Util.FieldToString(datablock.NewName); + // weird, comes out as empty string + //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); + items.Add(itm); + } + handlerMoveInventoryItem = OnMoveInventoryItem; + if (handlerMoveInventoryItem != null) + { + handlerMoveInventoryItem(this, items); + } } break; - case PacketType.EstateCovenantRequest: - - //EstateCovenantRequestPacket.AgentDataBlock epack = - // ((EstateCovenantRequestPacket)Pack).AgentData; + case PacketType.RemoveInventoryItem: + RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; - handlerEstateCovenantRequest = OnEstateCovenantRequest; - if (handlerEstateCovenantRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerEstateCovenantRequest(this); + if (removeItem.AgentData.SessionID != SessionId || + removeItem.AgentData.AgentID != AgentId) + break; } - break; - #endregion - #region GodPackets - - case PacketType.RequestGodlikePowers: - RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; - RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; - UUID token = rblock.Token; - - RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + if (OnRemoveInventoryItem != null) + { + RemoveInventoryItem handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) + { + uuids.Add(datablock.ItemID); + } + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } - handlerReqGodlikePowers = OnRequestGodlikePowers; + } + break; + case PacketType.RemoveInventoryFolder: + RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; - if (handlerReqGodlikePowers != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); + if (removeFolder.AgentData.SessionID != SessionId || + removeFolder.AgentData.AgentID != AgentId) + break; } + #endregion - break; - case PacketType.GodKickUser: - GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - - if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) + if (OnRemoveInventoryFolder != null) { - handlerGodKickUser = OnGodKickUser; - if (handlerGodKickUser != null) + RemoveInventoryFolder handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) { - handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, - gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); } } - else - { - SendAgentAlertMessage("Kick request denied", false); - } - //KickUserPacket kupack = new KickUserPacket(); - //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; - - //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; - //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; - - //kupack.TargetBlock.TargetIP = (uint)0; - //kupack.TargetBlock.TargetPort = (ushort)0; - //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; - - //OutPacket(kupack, ThrottleOutPacketType.Task); break; - - #endregion - - #region Economy/Transaction Packets - - case PacketType.MoneyBalanceRequest: - MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; - + case PacketType.RemoveInventoryObjects: + RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moneybalancerequestpacket.AgentData.SessionID != SessionId || - moneybalancerequestpacket.AgentData.AgentID != AgentId) + if (removeObject.AgentData.SessionID != SessionId || + removeObject.AgentData.AgentID != AgentId) break; } #endregion - - handlerMoneyBalanceRequest = OnMoneyBalanceRequest; - - if (handlerMoneyBalanceRequest != null) + if (OnRemoveInventoryFolder != null) { - handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + RemoveInventoryFolder handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) + { + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); + } } + if (OnRemoveInventoryItem != null) + { + RemoveInventoryItem handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) + { + uuids.Add(datablock.ItemID); + } + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } + } break; - case PacketType.EconomyDataRequest: + case PacketType.RequestTaskInventory: + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; - - handlerEconomoyDataRequest = OnEconomyDataRequest; - if (handlerEconomoyDataRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerEconomoyDataRequest(AgentId); + if (requesttask.AgentData.SessionID != SessionId || + requesttask.AgentData.AgentID != AgentId) + break; } - break; - case PacketType.RequestPayPrice: - RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + #endregion - handlerRequestPayPrice = OnRequestPayPrice; - if (handlerRequestPayPrice != null) + RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory; + if (handlerRequestTaskInventory != null) { - handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); + handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); } break; - - case PacketType.ObjectSaleInfo: - ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; + case PacketType.UpdateTaskInventory: + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectSaleInfoPacket.AgentData.SessionID != SessionId || - objectSaleInfoPacket.AgentData.AgentID != AgentId) + if (updatetask.AgentData.SessionID != SessionId || + updatetask.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectSaleInfo = OnObjectSaleInfo; - if (handlerObjectSaleInfo != null) + if (OnUpdateTaskInventory != null) { - foreach (ObjectSaleInfoPacket.ObjectDataBlock d - in objectSaleInfoPacket.ObjectData) + if (updatetask.UpdateData.Key == 0) { - handlerObjectSaleInfo(this, - objectSaleInfoPacket.AgentData.AgentID, - objectSaleInfoPacket.AgentData.SessionID, - d.LocalID, - d.SaleType, - d.SalePrice); + UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory; + if (handlerUpdateTaskInventory != null) + { + TaskInventoryItem newTaskItem = new TaskInventoryItem(); + newTaskItem.ItemID = updatetask.InventoryData.ItemID; + newTaskItem.ParentID = updatetask.InventoryData.FolderID; + newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; + newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; + newTaskItem.GroupID = updatetask.InventoryData.GroupID; + newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; + newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; + newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; + newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; + newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; + newTaskItem.Type = updatetask.InventoryData.Type; + newTaskItem.InvType = updatetask.InventoryData.InvType; + newTaskItem.Flags = updatetask.InventoryData.Flags; + //newTaskItem.SaleType=updatetask.InventoryData.SaleType; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); + newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); + newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; + handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, + newTaskItem, updatetask.UpdateData.LocalID); + } } } + break; - case PacketType.ObjectBuy: - ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; + case PacketType.RemoveTaskInventory: + + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectBuyPacket.AgentData.SessionID != SessionId || - objectBuyPacket.AgentData.AgentID != AgentId) + if (removeTask.AgentData.SessionID != SessionId || + removeTask.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectBuy = OnObjectBuy; + RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem; - if (handlerObjectBuy != null) + if (handlerRemoveTaskItem != null) { - foreach (ObjectBuyPacket.ObjectDataBlock d - in objectBuyPacket.ObjectData) - { - handlerObjectBuy(this, - objectBuyPacket.AgentData.AgentID, - objectBuyPacket.AgentData.SessionID, - objectBuyPacket.AgentData.GroupID, - objectBuyPacket.AgentData.CategoryID, - d.ObjectLocalID, - d.SaleType, - d.SalePrice); - } + handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); } - break; - - #endregion - - #region Script Packets - case PacketType.GetScriptRunning: - GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; - - handlerGetScriptRunning = OnGetScriptRunning; - if (handlerGetScriptRunning != null) - { - handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); - } break; - case PacketType.SetScriptRunning: - SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; + case PacketType.MoveTaskInventory: + + MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (setScriptRunning.AgentData.SessionID != SessionId || - setScriptRunning.AgentData.AgentID != AgentId) + if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || + moveTaskInventoryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerSetScriptRunning = OnSetScriptRunning; - if (handlerSetScriptRunning != null) + MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem; + + if (handlerMoveTaskItem != null) { - handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); + handlerMoveTaskItem( + this, moveTaskInventoryPacket.AgentData.FolderID, + moveTaskInventoryPacket.InventoryData.LocalID, + moveTaskInventoryPacket.InventoryData.ItemID); } + break; - case PacketType.ScriptReset: - ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; + case PacketType.RezScript: + //m_log.Debug(Pack.ToString()); + RezScriptPacket rezScriptx = (RezScriptPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scriptResetPacket.AgentData.SessionID != SessionId || - scriptResetPacket.AgentData.AgentID != AgentId) + if (rezScriptx.AgentData.SessionID != SessionId || + rezScriptx.AgentData.AgentID != AgentId) break; } #endregion - handlerScriptReset = OnScriptReset; - if (handlerScriptReset != null) + RezScript handlerRezScript = OnRezScript; + InventoryItemBase item = new InventoryItemBase(); + item.ID = rezScriptx.InventoryBlock.ItemID; + item.Folder = rezScriptx.InventoryBlock.FolderID; + item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); + item.Owner = rezScriptx.InventoryBlock.OwnerID; + item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; + item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; + item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; + item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; + item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; + item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; + item.GroupID = rezScriptx.InventoryBlock.GroupID; + item.AssetType = rezScriptx.InventoryBlock.Type; + item.InvType = rezScriptx.InventoryBlock.InvType; + item.Flags = rezScriptx.InventoryBlock.Flags; + item.SaleType = rezScriptx.InventoryBlock.SaleType; + item.SalePrice = rezScriptx.InventoryBlock.SalePrice; + item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); + item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); + item.CreationDate = rezScriptx.InventoryBlock.CreationDate; + + if (handlerRezScript != null) { - handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); + handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); } break; - #endregion - - #region Gesture Managment - - case PacketType.ActivateGestures: - ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; + case PacketType.MapLayerRequest: + RequestMapLayer(); + break; + case PacketType.MapBlockRequest: + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGesturePacket.AgentData.SessionID != SessionId || - activateGesturePacket.AgentData.AgentID != AgentId) + if (MapRequest.AgentData.SessionID != SessionId || + MapRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerActivateGesture = OnActivateGesture; - if (handlerActivateGesture != null) + RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks; + if (handlerRequestMapBlocks != null) { - handlerActivateGesture(this, - activateGesturePacket.Data[0].AssetID, - activateGesturePacket.Data[0].ItemID); + handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); } - else m_log.Error("Null pointer for activateGesture"); - break; - - case PacketType.DeactivateGestures: - DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; + case PacketType.MapNameRequest: + MapNameRequestPacket map = (MapNameRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deactivateGesturePacket.AgentData.SessionID != SessionId || - deactivateGesturePacket.AgentData.AgentID != AgentId) + if (map.AgentData.SessionID != SessionId || + map.AgentData.AgentID != AgentId) break; } #endregion - handlerDeactivateGesture = OnDeactivateGesture; - if (handlerDeactivateGesture != null) + string mapName = Util.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + RequestMapName handlerMapNameRequest = OnMapNameRequest; + if (handlerMapNameRequest != null) { - handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); + handlerMapNameRequest(this, mapName); } break; - case PacketType.ObjectOwner: - ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; + case PacketType.TeleportLandmarkRequest: + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectOwnerPacket.AgentData.SessionID != SessionId || - objectOwnerPacket.AgentData.AgentID != AgentId) + if (tpReq.Info.SessionID != SessionId || + tpReq.Info.AgentID != AgentId) break; } #endregion - List localIDs = new List(); + UUID lmid = tpReq.Info.LandmarkID; + AssetLandmark lm; + if (lmid != UUID.Zero) + { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); + AssetBase lma = m_assetService.Get(lmid.ToString()); - foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) - localIDs.Add(d.ObjectLocalID); + if (lma == null) + { + // Failed to find landmark + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } - handlerObjectOwner = OnObjectOwner; - if (handlerObjectOwner != null) + try + { + lm = new AssetLandmark(lma); + } + catch (NullReferenceException) + { + // asset not found generates null ref inside the assetlandmark constructor. + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + break; + } + } + else { - handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); + // Teleport home request + UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest; + if (handlerTeleportHomeRequest != null) + { + handlerTeleportHomeRequest(AgentId, this); + } + break; } - break; - - #endregion - - - #region unimplemented handlers - - case PacketType.StartPingCheck: - // Send the client the ping response back - // Pass the same PingID in the matching packet - // Handled In the packet processing - //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); - break; - case PacketType.CompletePingCheck: - // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client - //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); - break; - - case PacketType.ViewerStats: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); - break; - case PacketType.MapItemRequest: - MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; + if (handlerTeleportLandmarkRequest != null) { - if (mirpk.AgentData.SessionID != SessionId || - mirpk.AgentData.AgentID != AgentId) - break; + handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); } - #endregion - - //m_log.Debug(mirpk.ToString()); - handlerMapItemRequest = OnMapItemRequest; - if (handlerMapItemRequest != null) + else { - handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, - mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, - mirpk.RequestData.RegionHandle); + //no event handler so cancel request + + + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); } break; - case PacketType.TransferAbort: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); - break; - case PacketType.MuteListRequest: - MuteListRequestPacket muteListRequest = - (MuteListRequestPacket)Pack; + case PacketType.TeleportLocationRequest: + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; + // m_log.Debug(tpLocReq.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (muteListRequest.AgentData.SessionID != SessionId || - muteListRequest.AgentData.AgentID != AgentId) + if (tpLocReq.AgentData.SessionID != SessionId || + tpLocReq.AgentData.AgentID != AgentId) break; } #endregion - handlerMuteListRequest = OnMuteListRequest; - if (handlerMuteListRequest != null) + TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; + if (handlerTeleportLocationRequest != null) { - handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); + handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, + tpLocReq.Info.LookAt, 16); } else { - SendUseCachedMuteList(); + //no event handler so cancel request + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; + tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); } break; - case PacketType.UseCircuitCode: - // Don't display this one, we handle it at a lower level - break; - case PacketType.AgentHeightWidth: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); + #endregion + + case PacketType.UUIDNameRequest: + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest; + if (handlerNameRequest != null) + { + handlerNameRequest(UUIDBlock.ID, this); + } + } break; - case PacketType.InventoryDescendents: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); + #region Parcel related packets + case PacketType.RegionHandleRequest: + RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; + + RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; + if (handlerRegionHandleRequest != null) + { + handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); + } break; - case PacketType.DirPlacesQuery: - DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; - //m_log.Debug(dirPlacesQueryPacket.ToString()); + + case PacketType.ParcelInfoRequest: + ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || - dirPlacesQueryPacket.AgentData.AgentID != AgentId) + if (pirPack.AgentData.SessionID != SessionId || + pirPack.AgentData.AgentID != AgentId) break; } #endregion - handlerDirPlacesQuery = OnDirPlacesQuery; - if (handlerDirPlacesQuery != null) + ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest; + if (handlerParcelInfoRequest != null) { - handlerDirPlacesQuery(this, - dirPlacesQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.QueryText), - (int)dirPlacesQueryPacket.QueryData.QueryFlags, - (int)dirPlacesQueryPacket.QueryData.Category, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.SimName), - dirPlacesQueryPacket.QueryData.QueryStart); + handlerParcelInfoRequest(this, pirPack.Data.ParcelID); } break; - case PacketType.DirFindQuery: - DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; + + case PacketType.ParcelAccessListRequest: + ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirFindQueryPacket.AgentData.SessionID != SessionId || - dirFindQueryPacket.AgentData.AgentID != AgentId) + if (requestPacket.AgentData.SessionID != SessionId || + requestPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerDirFindQuery = OnDirFindQuery; - if (handlerDirFindQuery != null) + ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest; + + if (handlerParcelAccessListRequest != null) { - handlerDirFindQuery(this, - dirFindQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirFindQueryPacket.QueryData.QueryText), - dirFindQueryPacket.QueryData.QueryFlags, - dirFindQueryPacket.QueryData.QueryStart); + handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, + requestPacket.Data.Flags, requestPacket.Data.SequenceID, + requestPacket.Data.LocalID, this); } break; - case PacketType.DirLandQuery: - DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; + + case PacketType.ParcelAccessListUpdate: + ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirLandQueryPacket.AgentData.SessionID != SessionId || - dirLandQueryPacket.AgentData.AgentID != AgentId) + if (updatePacket.AgentData.SessionID != SessionId || + updatePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerDirLandQuery = OnDirLandQuery; - if (handlerDirLandQuery != null) + List entries = new List(); + foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) { - handlerDirLandQuery(this, - dirLandQueryPacket.QueryData.QueryID, - dirLandQueryPacket.QueryData.QueryFlags, - dirLandQueryPacket.QueryData.SearchType, - dirLandQueryPacket.QueryData.Price, - dirLandQueryPacket.QueryData.Area, - dirLandQueryPacket.QueryData.QueryStart); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = block.ID; + entry.Flags = (AccessList)block.Flags; + entry.Time = new DateTime(); + entries.Add(entry); + } + + ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; + if (handlerParcelAccessListUpdateRequest != null) + { + handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, + updatePacket.AgentData.SessionID, updatePacket.Data.Flags, + updatePacket.Data.LocalID, entries, this); } break; - case PacketType.DirPopularQuery: - DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; + case PacketType.ParcelPropertiesRequest: + + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPopularQueryPacket.AgentData.SessionID != SessionId || - dirPopularQueryPacket.AgentData.AgentID != AgentId) + if (propertiesRequest.AgentData.SessionID != SessionId || + propertiesRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerDirPopularQuery = OnDirPopularQuery; - if (handlerDirPopularQuery != null) + ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest; + if (handlerParcelPropertiesRequest != null) { - handlerDirPopularQuery(this, - dirPopularQueryPacket.QueryData.QueryID, - dirPopularQueryPacket.QueryData.QueryFlags); + handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), + (int)Math.Round(propertiesRequest.ParcelData.South), + (int)Math.Round(propertiesRequest.ParcelData.East), + (int)Math.Round(propertiesRequest.ParcelData.North), + propertiesRequest.ParcelData.SequenceID, + propertiesRequest.ParcelData.SnapSelection, this); } break; - case PacketType.DirClassifiedQuery: - DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; + case PacketType.ParcelDivide: + ParcelDividePacket landDivide = (ParcelDividePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || - dirClassifiedQueryPacket.AgentData.AgentID != AgentId) + if (landDivide.AgentData.SessionID != SessionId || + landDivide.AgentData.AgentID != AgentId) break; } #endregion - handlerDirClassifiedQuery = OnDirClassifiedQuery; - if (handlerDirClassifiedQuery != null) + ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest; + if (handlerParcelDivideRequest != null) { - handlerDirClassifiedQuery(this, - dirClassifiedQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirClassifiedQueryPacket.QueryData.QueryText), - dirClassifiedQueryPacket.QueryData.QueryFlags, - dirClassifiedQueryPacket.QueryData.Category, - dirClassifiedQueryPacket.QueryData.QueryStart); + handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), + (int)Math.Round(landDivide.ParcelData.South), + (int)Math.Round(landDivide.ParcelData.East), + (int)Math.Round(landDivide.ParcelData.North), this); } break; - case PacketType.EventInfoRequest: - EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; + case PacketType.ParcelJoin: + ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventInfoRequestPacket.AgentData.SessionID != SessionId || - eventInfoRequestPacket.AgentData.AgentID != AgentId) + if (landJoin.AgentData.SessionID != SessionId || + landJoin.AgentData.AgentID != AgentId) break; } #endregion - if (OnEventInfoRequest != null) + ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest; + + if (handlerParcelJoinRequest != null) { - OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); + handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), + (int)Math.Round(landJoin.ParcelData.South), + (int)Math.Round(landJoin.ParcelData.East), + (int)Math.Round(landJoin.ParcelData.North), this); } break; - - #region Calling Card - - case PacketType.OfferCallingCard: - OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; + case PacketType.ParcelPropertiesUpdate: + ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (offerCallingCardPacket.AgentData.SessionID != SessionId || - offerCallingCardPacket.AgentData.AgentID != AgentId) + if (parcelPropertiesPacket.AgentData.SessionID != SessionId || + parcelPropertiesPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnOfferCallingCard != null) + ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; + + if (handlerParcelPropertiesUpdateRequest != null) { - OnOfferCallingCard(this, - offerCallingCardPacket.AgentBlock.DestID, - offerCallingCardPacket.AgentBlock.TransactionID); + LandUpdateArgs args = new LandUpdateArgs(); + + args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; + args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; + args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); + args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; + args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; + args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; + args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; + args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); + args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); + args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); + args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; + args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; + args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; + args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; + args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; + args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; + args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; + handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); } break; - - case PacketType.AcceptCallingCard: - AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; + case PacketType.ParcelSelectObjects: + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (acceptCallingCardPacket.AgentData.SessionID != SessionId || - acceptCallingCardPacket.AgentData.AgentID != AgentId) + if (selectPacket.AgentData.SessionID != SessionId || + selectPacket.AgentData.AgentID != AgentId) break; } #endregion - // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should - // contain exactly one entry - if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) + List returnIDs = new List(); + + foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in + selectPacket.ReturnIDs) { - OnAcceptCallingCard(this, - acceptCallingCardPacket.TransactionBlock.TransactionID, - acceptCallingCardPacket.FolderData[0].FolderID); + returnIDs.Add(rb.ReturnID); } - break; - case PacketType.DeclineCallingCard: - DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; + ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects; + + if (handlerParcelSelectObjects != null) + { + handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); + } + break; + case PacketType.ParcelObjectOwnersRequest: + //m_log.Debug(Pack.ToString()); + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (declineCallingCardPacket.AgentData.SessionID != SessionId || - declineCallingCardPacket.AgentData.AgentID != AgentId) + if (reqPacket.AgentData.SessionID != SessionId || + reqPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnDeclineCallingCard != null) + ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; + + if (handlerParcelObjectOwnerRequest != null) { - OnDeclineCallingCard(this, - declineCallingCardPacket.TransactionBlock.TransactionID); + handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); } break; - #endregion - - #region Groups - case PacketType.ActivateGroup: - ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; + case PacketType.ParcelGodForceOwner: + ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGroupPacket.AgentData.SessionID != SessionId || - activateGroupPacket.AgentData.AgentID != AgentId) + if (godForceOwnerPacket.AgentData.SessionID != SessionId || + godForceOwnerPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner; + if (handlerParcelGodForceOwner != null) { - m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); - m_GroupsModule.SendAgentGroupDataUpdate(this); + handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); } break; - - case PacketType.GroupTitlesRequest: - GroupTitlesRequestPacket groupTitlesRequest = - (GroupTitlesRequestPacket)Pack; + case PacketType.ParcelRelease: + ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupTitlesRequest.AgentData.SessionID != SessionId || - groupTitlesRequest.AgentData.AgentID != AgentId) + if (releasePacket.AgentData.SessionID != SessionId || + releasePacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest; + if (handlerParcelAbandonRequest != null) { - GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - - groupTitlesReply.AgentData = - new GroupTitlesReplyPacket.AgentDataBlock(); - - groupTitlesReply.AgentData.AgentID = AgentId; - groupTitlesReply.AgentData.GroupID = - groupTitlesRequest.AgentData.GroupID; - - groupTitlesReply.AgentData.RequestID = - groupTitlesRequest.AgentData.RequestID; - - List titles = - m_GroupsModule.GroupTitlesRequest(this, - groupTitlesRequest.AgentData.GroupID); - - groupTitlesReply.GroupData = - new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - - int i = 0; - foreach (GroupTitlesData d in titles) - { - groupTitlesReply.GroupData[i] = - new GroupTitlesReplyPacket.GroupDataBlock(); + handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); + } + break; + case PacketType.ParcelReclaim: + ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; - groupTitlesReply.GroupData[i].Title = - Utils.StringToBytes(d.Name); - groupTitlesReply.GroupData[i].RoleID = - d.UUID; - groupTitlesReply.GroupData[i].Selected = - d.Selected; - i++; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (reclaimPacket.AgentData.SessionID != SessionId || + reclaimPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + ParcelReclaim handlerParcelReclaim = OnParcelReclaim; + if (handlerParcelReclaim != null) + { + handlerParcelReclaim(reclaimPacket.Data.LocalID, this); } break; + case PacketType.ParcelReturnObjects: - case PacketType.GroupProfileRequest: - GroupProfileRequestPacket groupProfileRequest = - (GroupProfileRequestPacket)Pack; + + ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupProfileRequest.AgentData.SessionID != SessionId || - groupProfileRequest.AgentData.AgentID != AgentId) + if (parcelReturnObjects.AgentData.SessionID != SessionId || + parcelReturnObjects.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; + for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) + puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; - groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); - groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); - groupProfileReply.AgentData.AgentID = AgentId; + UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; - GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, - groupProfileRequest.GroupData.GroupID); + for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) + puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; - groupProfileReply.GroupData.GroupID = d.GroupID; - groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); - groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); - groupProfileReply.GroupData.ShowInList = d.ShowInList; - groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); - groupProfileReply.GroupData.PowersMask = d.PowersMask; - groupProfileReply.GroupData.InsigniaID = d.InsigniaID; - groupProfileReply.GroupData.FounderID = d.FounderID; - groupProfileReply.GroupData.MembershipFee = d.MembershipFee; - groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; - groupProfileReply.GroupData.Money = d.Money; - groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; - groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; - groupProfileReply.GroupData.AllowPublish = d.AllowPublish; - groupProfileReply.GroupData.MaturePublish = d.MaturePublish; - groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; + if (handlerParcelReturnObjectsRequest != null) + { + handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); - OutPacket(groupProfileReply, ThrottleOutPacketType.Task); } break; - case PacketType.GroupMembersRequest: - GroupMembersRequestPacket groupMembersRequestPacket = - (GroupMembersRequestPacket)Pack; + case PacketType.ParcelSetOtherCleanTime: + ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupMembersRequestPacket.AgentData.SessionID != SessionId || - groupMembersRequestPacket.AgentData.AgentID != AgentId) + if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || + parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; + if (handlerParcelSetOtherCleanTime != null) { - List members = - m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); - - int memberCount = members.Count; - - while (true) - { - int blockCount = members.Count; - if (blockCount > 40) - blockCount = 40; - - GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); - - groupMembersReply.AgentData = - new GroupMembersReplyPacket.AgentDataBlock(); - groupMembersReply.GroupData = - new GroupMembersReplyPacket.GroupDataBlock(); - groupMembersReply.MemberData = - new GroupMembersReplyPacket.MemberDataBlock[ - blockCount]; - - groupMembersReply.AgentData.AgentID = AgentId; - groupMembersReply.GroupData.GroupID = - groupMembersRequestPacket.GroupData.GroupID; - groupMembersReply.GroupData.RequestID = - groupMembersRequestPacket.GroupData.RequestID; - groupMembersReply.GroupData.MemberCount = memberCount; - - for (int i = 0 ; i < blockCount ; i++) - { - GroupMembersData m = members[0]; - members.RemoveAt(0); - - groupMembersReply.MemberData[i] = - new GroupMembersReplyPacket.MemberDataBlock(); - groupMembersReply.MemberData[i].AgentID = - m.AgentID; - groupMembersReply.MemberData[i].Contribution = - m.Contribution; - groupMembersReply.MemberData[i].OnlineStatus = - Utils.StringToBytes(m.OnlineStatus); - groupMembersReply.MemberData[i].AgentPowers = - m.AgentPowers; - groupMembersReply.MemberData[i].Title = - Utils.StringToBytes(m.Title); - groupMembersReply.MemberData[i].IsOwner = - m.IsOwner; - } - OutPacket(groupMembersReply, ThrottleOutPacketType.Task); - if (members.Count == 0) - break; - } + handlerParcelSetOtherCleanTime(this, + parcelSetOtherCleanTimePacket.ParcelData.LocalID, + parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); } break; - case PacketType.GroupRoleDataRequest: - GroupRoleDataRequestPacket groupRolesRequest = - (GroupRoleDataRequestPacket)Pack; + case PacketType.LandStatRequest: + LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRolesRequest.AgentData.SessionID != SessionId || - groupRolesRequest.AgentData.AgentID != AgentId) + if (lsrp.AgentData.SessionID != SessionId || + lsrp.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + GodLandStatRequest handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) { - GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); - - groupRolesReply.AgentData = - new GroupRoleDataReplyPacket.AgentDataBlock(); - - groupRolesReply.AgentData.AgentID = AgentId; - - groupRolesReply.GroupData = - new GroupRoleDataReplyPacket.GroupDataBlock(); - - groupRolesReply.GroupData.GroupID = - groupRolesRequest.GroupData.GroupID; - - groupRolesReply.GroupData.RequestID = - groupRolesRequest.GroupData.RequestID; - - List titles = - m_GroupsModule.GroupRoleDataRequest(this, - groupRolesRequest.GroupData.GroupID); - - groupRolesReply.GroupData.RoleCount = - titles.Count; - - groupRolesReply.RoleData = - new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; - - int i = 0; - foreach (GroupRolesData d in titles) - { - groupRolesReply.RoleData[i] = - new GroupRoleDataReplyPacket.RoleDataBlock(); + handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); + } + break; - groupRolesReply.RoleData[i].RoleID = - d.RoleID; - groupRolesReply.RoleData[i].Name = - Utils.StringToBytes(d.Name); - groupRolesReply.RoleData[i].Title = - Utils.StringToBytes(d.Title); - groupRolesReply.RoleData[i].Description = - Utils.StringToBytes(d.Description); - groupRolesReply.RoleData[i].Powers = - d.Powers; - groupRolesReply.RoleData[i].Members = - (uint)d.Members; + case PacketType.ParcelDwellRequest: + ParcelDwellRequestPacket dwellrq = + (ParcelDwellRequestPacket)Pack; - i++; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (dwellrq.AgentData.SessionID != SessionId || + dwellrq.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest; + if (handlerParcelDwellRequest != null) + { + handlerParcelDwellRequest(dwellrq.Data.LocalID, this); } break; - case PacketType.GroupRoleMembersRequest: - GroupRoleMembersRequestPacket groupRoleMembersRequest = - (GroupRoleMembersRequestPacket)Pack; + #endregion + + #region Estate Packets + + case PacketType.EstateOwnerMessage: + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; + //m_log.Debug(messagePacket.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (groupRoleMembersRequest.AgentData.SessionID != SessionId || - groupRoleMembersRequest.AgentData.AgentID != AgentId) + if (messagePacket.AgentData.SessionID != SessionId || + messagePacket.AgentData.AgentID != AgentId) + break; + } + #endregion + + switch (Utils.BytesToString(messagePacket.MethodData.Method)) + { + case "getinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); + } + break; + case "setregioninfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), + convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), + Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), + (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), + Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), + convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); + } + break; +// case "texturebase": +// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) +// { +// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) +// { +// string s = Utils.BytesToString(block.Parameter); +// string[] splitField = s.Split(' '); +// if (splitField.Length == 2) +// { +// UUID tempUUID = new UUID(splitField[1]); +// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); +// } +// } +// } +// break; + case "texturedetail": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 2) + { + Int16 corner = Convert.ToInt16(splitField[0]); + UUID textureUUID = new UUID(splitField[1]); + + OnSetEstateTerrainDetailTexture(this, corner, textureUUID); + } + } + } + break; - } - #endregion + case "textureheights": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 3) + { + Int16 corner = Convert.ToInt16(splitField[0]); + float lowValue = (float)Convert.ToDecimal(splitField[1]); + float highValue = (float)Convert.ToDecimal(splitField[2]); - if (m_GroupsModule != null) - { - List mappings = - m_GroupsModule.GroupRoleMembersRequest(this, - groupRoleMembersRequest.GroupData.GroupID); + OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); + } + } + } + break; + case "texturecommit": + OnCommitEstateTerrainTextureRequest(this); + break; + case "setregionterrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length != 9) + { + m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); + } + else + { + try + { + string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float WaterHeight = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); + bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); + bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); + float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); + bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); + bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); + float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); - int mappingsCount = mappings.Count; + OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); - while (mappings.Count > 0) - { - int pairs = mappings.Count; - if (pairs > 32) - pairs = 32; + } + catch (Exception ex) + { + m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); + } + } + } - GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); - groupRoleMembersReply.AgentData = - new GroupRoleMembersReplyPacket.AgentDataBlock(); - groupRoleMembersReply.AgentData.AgentID = - AgentId; - groupRoleMembersReply.AgentData.GroupID = - groupRoleMembersRequest.GroupData.GroupID; - groupRoleMembersReply.AgentData.RequestID = - groupRoleMembersRequest.GroupData.RequestID; + break; + case "restart": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + float timeSeconds; + Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); + timeSeconds = (int)timeSeconds; + OnEstateRestartSimRequest(this, (int)timeSeconds); - groupRoleMembersReply.AgentData.TotalPairs = - (uint)mappingsCount; + } + } + break; + case "estatechangecovenantid": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); + OnEstateChangeCovenantRequest(this, newCovenantID); + } + } + break; + case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); - groupRoleMembersReply.MemberData = - new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; + } + break; + case "simulatormessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "instantmessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length < 5) + break; + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "setregiondebug": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); + bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); + bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); - for (int i = 0 ; i < pairs ; i++) + OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); + } + break; + case "teleporthomeuser": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) { - GroupRoleMembersData d = mappings[0]; - mappings.RemoveAt(0); + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UUID Prey; - groupRoleMembersReply.MemberData[i] = - new GroupRoleMembersReplyPacket.MemberDataBlock(); + UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); - groupRoleMembersReply.MemberData[i].RoleID = - d.RoleID; - groupRoleMembersReply.MemberData[i].MemberID = - d.MemberID; + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + } + break; + case "teleporthomeallusers": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); + } + break; + case "colliders": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 1, 0, "", this); + } + break; + case "scripts": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 0, 0, "", this); } + break; + case "terrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length > 0) + { + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") + { + BakeTerrain handlerBakeTerrain = OnBakeTerrain; + if (handlerBakeTerrain != null) + { + handlerBakeTerrain(this); + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") + { + if (messagePacket.ParamList.Length > 1) + { + RequestTerrain handlerRequestTerrain = OnRequestTerrain; + if (handlerRequestTerrain != null) + { + handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") + { + if (messagePacket.ParamList.Length > 1) + { + RequestTerrain handlerUploadTerrain = OnUploadTerrain; + if (handlerUploadTerrain != null) + { + handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } - OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); - } - } - break; + } - case PacketType.CreateGroupRequest: - CreateGroupRequestPacket createGroupRequest = - (CreateGroupRequestPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (createGroupRequest.AgentData.SessionID != SessionId || - createGroupRequest.AgentData.AgentID != AgentId) + } break; - } - #endregion - if (m_GroupsModule != null) - { - m_GroupsModule.CreateGroup(this, - Utils.BytesToString(createGroupRequest.GroupData.Name), - Utils.BytesToString(createGroupRequest.GroupData.Charter), - createGroupRequest.GroupData.ShowInList, - createGroupRequest.GroupData.InsigniaID, - createGroupRequest.GroupData.MembershipFee, - createGroupRequest.GroupData.OpenEnrollment, - createGroupRequest.GroupData.AllowPublish, - createGroupRequest.GroupData.MaturePublish); - } - break; + case "estatechangeinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - case PacketType.UpdateGroupInfo: - UpdateGroupInfoPacket updateGroupInfo = - (UpdateGroupInfoPacket)Pack; + EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo; + if (handlerEstateChangeInfo != null) + { + handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); + } + } + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (updateGroupInfo.AgentData.SessionID != SessionId || - updateGroupInfo.AgentData.AgentID != AgentId) + default: + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); break; } - #endregion + + //int parcelID, uint reportType, uint requestflags, string filter - if (m_GroupsModule != null) - { - m_GroupsModule.UpdateGroupInfo(this, - updateGroupInfo.GroupData.GroupID, - Utils.BytesToString(updateGroupInfo.GroupData.Charter), - updateGroupInfo.GroupData.ShowInList, - updateGroupInfo.GroupData.InsigniaID, - updateGroupInfo.GroupData.MembershipFee, - updateGroupInfo.GroupData.OpenEnrollment, - updateGroupInfo.GroupData.AllowPublish, - updateGroupInfo.GroupData.MaturePublish); - } + //lsrp.RequestData.ParcelLocalID; + //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts + //lsrp.RequestData.RequestFlags; + //lsrp.RequestData.Filter; break; - case PacketType.SetGroupAcceptNotices: - SetGroupAcceptNoticesPacket setGroupAcceptNotices = - (SetGroupAcceptNoticesPacket)Pack; + case PacketType.RequestRegionInfo: + RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; #region Packet Session and User Check if (m_checkPackets) { - if (setGroupAcceptNotices.AgentData.SessionID != SessionId || - setGroupAcceptNotices.AgentData.AgentID != AgentId) + if (mPacket.SessionID != SessionId || + mPacket.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest; + if (handlerRegionInfoRequest != null) { - m_GroupsModule.SetGroupAcceptNotices(this, - setGroupAcceptNotices.Data.GroupID, - setGroupAcceptNotices.Data.AcceptNotices, - setGroupAcceptNotices.NewData.ListInProfile); + handlerRegionInfoRequest(this); } - break; + case PacketType.EstateCovenantRequest: - case PacketType.GroupTitleUpdate: - GroupTitleUpdatePacket groupTitleUpdate = - (GroupTitleUpdatePacket)Pack; + //EstateCovenantRequestPacket.AgentDataBlock epack = + // ((EstateCovenantRequestPacket)Pack).AgentData; - #region Packet Session and User Check - if (m_checkPackets) + EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest; + if (handlerEstateCovenantRequest != null) { - if (groupTitleUpdate.AgentData.SessionID != SessionId || - groupTitleUpdate.AgentData.AgentID != AgentId) - break; + handlerEstateCovenantRequest(this); } + break; + #endregion - if (m_GroupsModule != null) + #region GodPackets + + case PacketType.RequestGodlikePowers: + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + UUID token = rblock.Token; + + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + + RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers; + + if (handlerReqGodlikePowers != null) { - m_GroupsModule.GroupTitleUpdate(this, - groupTitleUpdate.AgentData.GroupID, - groupTitleUpdate.AgentData.TitleRoleID); + handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); } break; + case PacketType.GodKickUser: + GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - - case PacketType.ParcelDeedToGroup: - ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; - if (m_GroupsModule != null) + if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) { - handlerParcelDeedToGroup = OnParcelDeedToGroup; - if (handlerParcelDeedToGroup != null) + GodKickUser handlerGodKickUser = OnGodKickUser; + if (handlerGodKickUser != null) { - handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); - + handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, + gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); } } + else + { + SendAgentAlertMessage("Kick request denied", false); + } + //KickUserPacket kupack = new KickUserPacket(); + //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; + + //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; + //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; + + //kupack.TargetBlock.TargetIP = (uint)0; + //kupack.TargetBlock.TargetPort = (ushort)0; + //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; + //OutPacket(kupack, ThrottleOutPacketType.Task); break; + #endregion + + #region Economy/Transaction Packets - case PacketType.GroupNoticesListRequest: - GroupNoticesListRequestPacket groupNoticesListRequest = - (GroupNoticesListRequestPacket)Pack; + case PacketType.MoneyBalanceRequest: + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupNoticesListRequest.AgentData.SessionID != SessionId || - groupNoticesListRequest.AgentData.AgentID != AgentId) + if (moneybalancerequestpacket.AgentData.SessionID != SessionId || + moneybalancerequestpacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - GroupNoticeData[] gn = - m_GroupsModule.GroupNoticesListRequest(this, - groupNoticesListRequest.Data.GroupID); - - GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); - groupNoticesListReply.AgentData = - new GroupNoticesListReplyPacket.AgentDataBlock(); - groupNoticesListReply.AgentData.AgentID = AgentId; - groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; - - groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; - - int i = 0; - foreach (GroupNoticeData g in gn) - { - groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); - groupNoticesListReply.Data[i].NoticeID = - g.NoticeID; - groupNoticesListReply.Data[i].Timestamp = - g.Timestamp; - groupNoticesListReply.Data[i].FromName = - Utils.StringToBytes(g.FromName); - groupNoticesListReply.Data[i].Subject = - Utils.StringToBytes(g.Subject); - groupNoticesListReply.Data[i].HasAttachment = - g.HasAttachment; - groupNoticesListReply.Data[i].AssetType = - g.AssetType; - i++; - } + MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest; - OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); + if (handlerMoneyBalanceRequest != null) + { + handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); } break; - case PacketType.GroupNoticeRequest: - GroupNoticeRequestPacket groupNoticeRequest = - (GroupNoticeRequestPacket)Pack; + case PacketType.EconomyDataRequest: - #region Packet Session and User Check - if (m_checkPackets) + + EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; + if (handlerEconomoyDataRequest != null) { - if (groupNoticeRequest.AgentData.SessionID != SessionId || - groupNoticeRequest.AgentData.AgentID != AgentId) - break; + handlerEconomoyDataRequest(AgentId); } - #endregion + break; + case PacketType.RequestPayPrice: + RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; - if (m_GroupsModule != null) + RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice; + if (handlerRequestPayPrice != null) { - m_GroupsModule.GroupNoticeRequest(this, - groupNoticeRequest.Data.GroupNoticeID); + handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); } break; - case PacketType.GroupRoleUpdate: - GroupRoleUpdatePacket groupRoleUpdate = - (GroupRoleUpdatePacket)Pack; + case PacketType.ObjectSaleInfo: + ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRoleUpdate.AgentData.SessionID != SessionId || - groupRoleUpdate.AgentData.AgentID != AgentId) + if (objectSaleInfoPacket.AgentData.SessionID != SessionId || + objectSaleInfoPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo; + if (handlerObjectSaleInfo != null) { - foreach (GroupRoleUpdatePacket.RoleDataBlock d in - groupRoleUpdate.RoleData) + foreach (ObjectSaleInfoPacket.ObjectDataBlock d + in objectSaleInfoPacket.ObjectData) { - m_GroupsModule.GroupRoleUpdate(this, - groupRoleUpdate.AgentData.GroupID, - d.RoleID, - Utils.BytesToString(d.Name), - Utils.BytesToString(d.Description), - Utils.BytesToString(d.Title), - d.Powers, - d.UpdateType); + handlerObjectSaleInfo(this, + objectSaleInfoPacket.AgentData.AgentID, + objectSaleInfoPacket.AgentData.SessionID, + d.LocalID, + d.SaleType, + d.SalePrice); } - m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); } break; - case PacketType.GroupRoleChanges: - GroupRoleChangesPacket groupRoleChanges = - (GroupRoleChangesPacket)Pack; + case PacketType.ObjectBuy: + ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRoleChanges.AgentData.SessionID != SessionId || - groupRoleChanges.AgentData.AgentID != AgentId) + if (objectBuyPacket.AgentData.SessionID != SessionId || + objectBuyPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ObjectBuy handlerObjectBuy = OnObjectBuy; + + if (handlerObjectBuy != null) { - foreach (GroupRoleChangesPacket.RoleChangeBlock d in - groupRoleChanges.RoleChange) + foreach (ObjectBuyPacket.ObjectDataBlock d + in objectBuyPacket.ObjectData) { - m_GroupsModule.GroupRoleChanges(this, - groupRoleChanges.AgentData.GroupID, - d.RoleID, - d.MemberID, - d.Change); + handlerObjectBuy(this, + objectBuyPacket.AgentData.AgentID, + objectBuyPacket.AgentData.SessionID, + objectBuyPacket.AgentData.GroupID, + objectBuyPacket.AgentData.CategoryID, + d.ObjectLocalID, + d.SaleType, + d.SalePrice); } - m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); } break; - case PacketType.JoinGroupRequest: - JoinGroupRequestPacket joinGroupRequest = - (JoinGroupRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (joinGroupRequest.AgentData.SessionID != SessionId || - joinGroupRequest.AgentData.AgentID != AgentId) - break; - } #endregion - if (m_GroupsModule != null) + #region Script Packets + + case PacketType.GetScriptRunning: + GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; + + GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning; + if (handlerGetScriptRunning != null) { - m_GroupsModule.JoinGroupRequest(this, - joinGroupRequest.GroupData.GroupID); + handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); } break; - case PacketType.LeaveGroupRequest: - LeaveGroupRequestPacket leaveGroupRequest = - (LeaveGroupRequestPacket)Pack; + case PacketType.SetScriptRunning: + SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (leaveGroupRequest.AgentData.SessionID != SessionId || - leaveGroupRequest.AgentData.AgentID != AgentId) + if (setScriptRunning.AgentData.SessionID != SessionId || + setScriptRunning.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning; + if (handlerSetScriptRunning != null) { - m_GroupsModule.LeaveGroupRequest(this, - leaveGroupRequest.GroupData.GroupID); + handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); } break; - case PacketType.EjectGroupMemberRequest: - EjectGroupMemberRequestPacket ejectGroupMemberRequest = - (EjectGroupMemberRequestPacket)Pack; + case PacketType.ScriptReset: + ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || - ejectGroupMemberRequest.AgentData.AgentID != AgentId) + if (scriptResetPacket.AgentData.SessionID != SessionId || + scriptResetPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ScriptReset handlerScriptReset = OnScriptReset; + if (handlerScriptReset != null) { - foreach (EjectGroupMemberRequestPacket.EjectDataBlock e - in ejectGroupMemberRequest.EjectData) - { - m_GroupsModule.EjectGroupMemberRequest(this, - ejectGroupMemberRequest.GroupData.GroupID, - e.EjecteeID); - } + handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); } break; - case PacketType.InviteGroupRequest: - InviteGroupRequestPacket inviteGroupRequest = - (InviteGroupRequestPacket)Pack; + #endregion + + #region Gesture Managment + + case PacketType.ActivateGestures: + ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (inviteGroupRequest.AgentData.SessionID != SessionId || - inviteGroupRequest.AgentData.AgentID != AgentId) + if (activateGesturePacket.AgentData.SessionID != SessionId || + activateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ActivateGesture handlerActivateGesture = OnActivateGesture; + if (handlerActivateGesture != null) { - foreach (InviteGroupRequestPacket.InviteDataBlock b in - inviteGroupRequest.InviteData) - { - m_GroupsModule.InviteGroupRequest(this, - inviteGroupRequest.GroupData.GroupID, - b.InviteeID, - b.RoleID); - } + handlerActivateGesture(this, + activateGesturePacket.Data[0].AssetID, + activateGesturePacket.Data[0].ItemID); } + else m_log.Error("Null pointer for activateGesture"); + break; - #endregion - case PacketType.StartLure: - StartLurePacket startLureRequest = (StartLurePacket)Pack; + case PacketType.DeactivateGestures: + DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (startLureRequest.AgentData.SessionID != SessionId || - startLureRequest.AgentData.AgentID != AgentId) + if (deactivateGesturePacket.AgentData.SessionID != SessionId || + deactivateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerStartLure = OnStartLure; - if (handlerStartLure != null) - handlerStartLure(startLureRequest.Info.LureType, - Utils.BytesToString( - startLureRequest.Info.Message), - startLureRequest.TargetData[0].TargetID, - this); - break; - - case PacketType.TeleportLureRequest: - TeleportLureRequestPacket teleportLureRequest = - (TeleportLureRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture; + if (handlerDeactivateGesture != null) { - if (teleportLureRequest.Info.SessionID != SessionId || - teleportLureRequest.Info.AgentID != AgentId) - break; + handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); } - #endregion - - handlerTeleportLureRequest = OnTeleportLureRequest; - if (handlerTeleportLureRequest != null) - handlerTeleportLureRequest( - teleportLureRequest.Info.LureID, - teleportLureRequest.Info.TeleportFlags, - this); break; - - case PacketType.ClassifiedInfoRequest: - ClassifiedInfoRequestPacket classifiedInfoRequest = - (ClassifiedInfoRequestPacket)Pack; + case PacketType.ObjectOwner: + ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (classifiedInfoRequest.AgentData.SessionID != SessionId || - classifiedInfoRequest.AgentData.AgentID != AgentId) + if (objectOwnerPacket.AgentData.SessionID != SessionId || + objectOwnerPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerClassifiedInfoRequest = OnClassifiedInfoRequest; - if (handlerClassifiedInfoRequest != null) - handlerClassifiedInfoRequest( - classifiedInfoRequest.Data.ClassifiedID, - this); - break; + List localIDs = new List(); - case PacketType.ClassifiedInfoUpdate: - ClassifiedInfoUpdatePacket classifiedInfoUpdate = - (ClassifiedInfoUpdatePacket)Pack; + foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) + localIDs.Add(d.ObjectLocalID); - #region Packet Session and User Check - if (m_checkPackets) + ObjectOwner handlerObjectOwner = OnObjectOwner; + if (handlerObjectOwner != null) { - if (classifiedInfoUpdate.AgentData.SessionID != SessionId || - classifiedInfoUpdate.AgentData.AgentID != AgentId) - break; + handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); } + break; + #endregion - handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; - if (handlerClassifiedInfoUpdate != null) - handlerClassifiedInfoUpdate( - classifiedInfoUpdate.Data.ClassifiedID, - classifiedInfoUpdate.Data.Category, - Utils.BytesToString( - classifiedInfoUpdate.Data.Name), - Utils.BytesToString( - classifiedInfoUpdate.Data.Desc), - classifiedInfoUpdate.Data.ParcelID, - classifiedInfoUpdate.Data.ParentEstate, - classifiedInfoUpdate.Data.SnapshotID, - new Vector3( - classifiedInfoUpdate.Data.PosGlobal), - classifiedInfoUpdate.Data.ClassifiedFlags, - classifiedInfoUpdate.Data.PriceForListing, - this); - break; - case PacketType.ClassifiedDelete: - ClassifiedDeletePacket classifiedDelete = - (ClassifiedDeletePacket)Pack; + #region unimplemented handlers - #region Packet Session and User Check - if (m_checkPackets) - { - if (classifiedDelete.AgentData.SessionID != SessionId || - classifiedDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + case PacketType.StartPingCheck: + // Send the client the ping response back + // Pass the same PingID in the matching packet + // Handled In the packet processing + //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); + break; + case PacketType.CompletePingCheck: + // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client + //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); + break; - handlerClassifiedDelete = OnClassifiedDelete; - if (handlerClassifiedDelete != null) - handlerClassifiedDelete( - classifiedDelete.Data.ClassifiedID, - this); + case PacketType.ViewerStats: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); break; - case PacketType.ClassifiedGodDelete: - ClassifiedGodDeletePacket classifiedGodDelete = - (ClassifiedGodDeletePacket)Pack; + case PacketType.MapItemRequest: + MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (classifiedGodDelete.AgentData.SessionID != SessionId || - classifiedGodDelete.AgentData.AgentID != AgentId) + if (mirpk.AgentData.SessionID != SessionId || + mirpk.AgentData.AgentID != AgentId) break; } #endregion - handlerClassifiedGodDelete = OnClassifiedGodDelete; - if (handlerClassifiedGodDelete != null) - handlerClassifiedGodDelete( - classifiedGodDelete.Data.ClassifiedID, - this); + //m_log.Debug(mirpk.ToString()); + MapItemRequest handlerMapItemRequest = OnMapItemRequest; + if (handlerMapItemRequest != null) + { + handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, + mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, + mirpk.RequestData.RegionHandle); + + } break; - case PacketType.EventGodDelete: - EventGodDeletePacket eventGodDelete = - (EventGodDeletePacket)Pack; + case PacketType.TransferAbort: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); + break; + case PacketType.MuteListRequest: + MuteListRequestPacket muteListRequest = + (MuteListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventGodDelete.AgentData.SessionID != SessionId || - eventGodDelete.AgentData.AgentID != AgentId) + if (muteListRequest.AgentData.SessionID != SessionId || + muteListRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerEventGodDelete = OnEventGodDelete; - if (handlerEventGodDelete != null) - handlerEventGodDelete( - eventGodDelete.EventData.EventID, - eventGodDelete.QueryData.QueryID, - Utils.BytesToString( - eventGodDelete.QueryData.QueryText), - eventGodDelete.QueryData.QueryFlags, - eventGodDelete.QueryData.QueryStart, - this); - break; - - case PacketType.EventNotificationAddRequest: - EventNotificationAddRequestPacket eventNotificationAdd = - (EventNotificationAddRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + MuteListRequest handlerMuteListRequest = OnMuteListRequest; + if (handlerMuteListRequest != null) { - if (eventNotificationAdd.AgentData.SessionID != SessionId || - eventNotificationAdd.AgentData.AgentID != AgentId) - break; + handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); } - #endregion + else + { + SendUseCachedMuteList(); + } + break; + case PacketType.UseCircuitCode: + // Don't display this one, we handle it at a lower level + break; - handlerEventNotificationAddRequest = OnEventNotificationAddRequest; - if (handlerEventNotificationAddRequest != null) - handlerEventNotificationAddRequest( - eventNotificationAdd.EventData.EventID, this); + case PacketType.AgentHeightWidth: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); break; - case PacketType.EventNotificationRemoveRequest: - EventNotificationRemoveRequestPacket eventNotificationRemove = - (EventNotificationRemoveRequestPacket)Pack; + case PacketType.InventoryDescendents: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); + + break; + case PacketType.DirPlacesQuery: + DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; + //m_log.Debug(dirPlacesQueryPacket.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (eventNotificationRemove.AgentData.SessionID != SessionId || - eventNotificationRemove.AgentData.AgentID != AgentId) + if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || + dirPlacesQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; - if (handlerEventNotificationRemoveRequest != null) - handlerEventNotificationRemoveRequest( - eventNotificationRemove.EventData.EventID, this); + DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery; + if (handlerDirPlacesQuery != null) + { + handlerDirPlacesQuery(this, + dirPlacesQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.QueryText), + (int)dirPlacesQueryPacket.QueryData.QueryFlags, + (int)dirPlacesQueryPacket.QueryData.Category, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.SimName), + dirPlacesQueryPacket.QueryData.QueryStart); + } break; - - case PacketType.RetrieveInstantMessages: - RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; + case PacketType.DirFindQuery: + DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rimpInstantMessagePack.AgentData.SessionID != SessionId || - rimpInstantMessagePack.AgentData.AgentID != AgentId) + if (dirFindQueryPacket.AgentData.SessionID != SessionId || + dirFindQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerRetrieveInstantMessages = OnRetrieveInstantMessages; - if (handlerRetrieveInstantMessages != null) - handlerRetrieveInstantMessages(this); + DirFindQuery handlerDirFindQuery = OnDirFindQuery; + if (handlerDirFindQuery != null) + { + handlerDirFindQuery(this, + dirFindQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirFindQueryPacket.QueryData.QueryText), + dirFindQueryPacket.QueryData.QueryFlags, + dirFindQueryPacket.QueryData.QueryStart); + } break; - - case PacketType.PickDelete: - PickDeletePacket pickDelete = - (PickDeletePacket)Pack; + case PacketType.DirLandQuery: + DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickDelete.AgentData.SessionID != SessionId || - pickDelete.AgentData.AgentID != AgentId) + if (dirLandQueryPacket.AgentData.SessionID != SessionId || + dirLandQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickDelete = OnPickDelete; - if (handlerPickDelete != null) - handlerPickDelete(this, pickDelete.Data.PickID); + DirLandQuery handlerDirLandQuery = OnDirLandQuery; + if (handlerDirLandQuery != null) + { + handlerDirLandQuery(this, + dirLandQueryPacket.QueryData.QueryID, + dirLandQueryPacket.QueryData.QueryFlags, + dirLandQueryPacket.QueryData.SearchType, + dirLandQueryPacket.QueryData.Price, + dirLandQueryPacket.QueryData.Area, + dirLandQueryPacket.QueryData.QueryStart); + } break; - case PacketType.PickGodDelete: - PickGodDeletePacket pickGodDelete = - (PickGodDeletePacket)Pack; + case PacketType.DirPopularQuery: + DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickGodDelete.AgentData.SessionID != SessionId || - pickGodDelete.AgentData.AgentID != AgentId) + if (dirPopularQueryPacket.AgentData.SessionID != SessionId || + dirPopularQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickGodDelete = OnPickGodDelete; - if (handlerPickGodDelete != null) - handlerPickGodDelete(this, - pickGodDelete.AgentData.AgentID, - pickGodDelete.Data.PickID, - pickGodDelete.Data.QueryID); + DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery; + if (handlerDirPopularQuery != null) + { + handlerDirPopularQuery(this, + dirPopularQueryPacket.QueryData.QueryID, + dirPopularQueryPacket.QueryData.QueryFlags); + } break; - case PacketType.PickInfoUpdate: - PickInfoUpdatePacket pickInfoUpdate = - (PickInfoUpdatePacket)Pack; + case PacketType.DirClassifiedQuery: + DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickInfoUpdate.AgentData.SessionID != SessionId || - pickInfoUpdate.AgentData.AgentID != AgentId) + if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || + dirClassifiedQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickInfoUpdate = OnPickInfoUpdate; - if (handlerPickInfoUpdate != null) - handlerPickInfoUpdate(this, - pickInfoUpdate.Data.PickID, - pickInfoUpdate.Data.CreatorID, - pickInfoUpdate.Data.TopPick, - Utils.BytesToString(pickInfoUpdate.Data.Name), - Utils.BytesToString(pickInfoUpdate.Data.Desc), - pickInfoUpdate.Data.SnapshotID, - pickInfoUpdate.Data.SortOrder, - pickInfoUpdate.Data.Enabled); + DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery; + if (handlerDirClassifiedQuery != null) + { + handlerDirClassifiedQuery(this, + dirClassifiedQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirClassifiedQueryPacket.QueryData.QueryText), + dirClassifiedQueryPacket.QueryData.QueryFlags, + dirClassifiedQueryPacket.QueryData.Category, + dirClassifiedQueryPacket.QueryData.QueryStart); + } break; - case PacketType.AvatarNotesUpdate: - AvatarNotesUpdatePacket avatarNotesUpdate = - (AvatarNotesUpdatePacket)Pack; + case PacketType.EventInfoRequest: + EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avatarNotesUpdate.AgentData.SessionID != SessionId || - avatarNotesUpdate.AgentData.AgentID != AgentId) + if (eventInfoRequestPacket.AgentData.SessionID != SessionId || + eventInfoRequestPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerAvatarNotesUpdate = OnAvatarNotesUpdate; - if (handlerAvatarNotesUpdate != null) - handlerAvatarNotesUpdate(this, - avatarNotesUpdate.Data.TargetID, - Utils.BytesToString(avatarNotesUpdate.Data.Notes)); - break; - -// case PacketType.AvatarInterestsUpdate: -// AvatarInterestsUpdatePacket avatarInterestUpdate = -// (AvatarInterestsUpdatePacket)Pack; -// -// break; - - case PacketType.PlacesQuery: - PlacesQueryPacket placesQueryPacket = - (PlacesQueryPacket)Pack; - - handlerPlacesQuery = OnPlacesQuery; - - if (handlerPlacesQuery != null) - handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, - placesQueryPacket.TransactionData.TransactionID, - Utils.BytesToString( - placesQueryPacket.QueryData.QueryText), - placesQueryPacket.QueryData.QueryFlags, - (byte)placesQueryPacket.QueryData.Category, - Utils.BytesToString( - placesQueryPacket.QueryData.SimName), - this); - break; - default: - m_log.Warn("[CLIENT]: unhandled packet " + Pack); + if (OnEventInfoRequest != null) + { + OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); + } break; - #endregion - } - - PacketPool.Instance.ReturnPacket(Pack); - - } - - private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) - { - PrimitiveBaseShape shape = new PrimitiveBaseShape(); - - shape.PCode = addPacket.ObjectData.PCode; - shape.State = addPacket.ObjectData.State; - shape.PathBegin = addPacket.ObjectData.PathBegin; - shape.PathEnd = addPacket.ObjectData.PathEnd; - shape.PathScaleX = addPacket.ObjectData.PathScaleX; - shape.PathScaleY = addPacket.ObjectData.PathScaleY; - shape.PathShearX = addPacket.ObjectData.PathShearX; - shape.PathShearY = addPacket.ObjectData.PathShearY; - shape.PathSkew = addPacket.ObjectData.PathSkew; - shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; - shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; - shape.Scale = addPacket.ObjectData.Scale; - shape.PathCurve = addPacket.ObjectData.PathCurve; - shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; - shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; - shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; - shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; - shape.PathTaperX = addPacket.ObjectData.PathTaperX; - shape.PathTaperY = addPacket.ObjectData.PathTaperY; - shape.PathTwist = addPacket.ObjectData.PathTwist; - shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); - shape.TextureEntry = ntex.GetBytes(); - //shape.Textures = ntex; - return shape; - } - - /// - /// Send the client an Estate message blue box pop-down with a single OK button - /// - /// - /// - /// - /// - public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) - { - if (!ChildAgentStatus()) - SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); - - //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); - } - - public void SendLogoutPacket() - { - // I know this is a bit of a hack, however there are times when you don't - // want to send this, but still need to do the rest of the shutdown process - // this method gets called from the packet server.. which makes it practically - // impossible to do any other way. - - if (m_SendLogoutPacketWhenClosing) - { - LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); - // TODO: don't create new blocks if recycling an old packet - logReply.AgentData.AgentID = AgentId; - logReply.AgentData.SessionID = SessionId; - logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; - logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); - logReply.InventoryData[0].ItemID = UUID.Zero; - - OutPacket(logReply, ThrottleOutPacketType.Task); - } - } + #region Calling Card - public void SendHealth(float health) - { - HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); - healthpacket.HealthData.Health = health; - OutPacket(healthpacket, ThrottleOutPacketType.Task); - } + case PacketType.OfferCallingCard: + OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; - public void SendAgentOnline(UUID[] agentIDs) - { - OnlineNotificationPacket onp = new OnlineNotificationPacket(); - OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) - { - OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - onpb[i] = onpbl; - } - onp.AgentBlock = onpb; - onp.Header.Reliable = true; - OutPacket(onp, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (offerCallingCardPacket.AgentData.SessionID != SessionId || + offerCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAgentOffline(UUID[] agentIDs) - { - OfflineNotificationPacket offp = new OfflineNotificationPacket(); - OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) - { - OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - offpb[i] = onpbl; - } - offp.AgentBlock = offpb; - offp.Header.Reliable = true; - OutPacket(offp, ThrottleOutPacketType.Task); - } + if (OnOfferCallingCard != null) + { + OnOfferCallingCard(this, + offerCallingCardPacket.AgentBlock.DestID, + offerCallingCardPacket.AgentBlock.TransactionID); + } + break; - public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, - Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) - { - AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); - avatarSitResponse.SitObject.ID = TargetID; - if (CameraAtOffset != Vector3.Zero) - { - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; - } - avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; - avatarSitResponse.SitTransform.AutoPilot = autopilot; - avatarSitResponse.SitTransform.SitPosition = OffsetPos; - avatarSitResponse.SitTransform.SitRotation = SitOrientation; + case PacketType.AcceptCallingCard: + AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; - OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (acceptCallingCardPacket.AgentData.SessionID != SessionId || + acceptCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAdminResponse(UUID Token, uint AdminLevel) - { - GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); - GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); - GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); + // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should + // contain exactly one entry + if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) + { + OnAcceptCallingCard(this, + acceptCallingCardPacket.TransactionBlock.TransactionID, + acceptCallingCardPacket.FolderData[0].FolderID); + } + break; - adb.AgentID = AgentId; - adb.SessionID = SessionId; // More security - gdb.GodLevel = (byte)AdminLevel; - gdb.Token = Token; - //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; - respondPacket.GrantData = gdb; - respondPacket.AgentData = adb; - OutPacket(respondPacket, ThrottleOutPacketType.Task); - } + case PacketType.DeclineCallingCard: + DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; - public void SendGroupMembership(GroupMembershipData[] GroupMembership) - { - m_groupPowers.Clear(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (declineCallingCardPacket.AgentData.SessionID != SessionId || + declineCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); - AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; - for (int i = 0; i < GroupMembership.Length; i++) - { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + if (OnDeclineCallingCard != null) + { + OnDeclineCallingCard(this, + declineCallingCardPacket.TransactionBlock.TransactionID); + } + break; + #endregion - AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); - Group.AcceptNotices = GroupMembership[i].AcceptNotices; - Group.Contribution = GroupMembership[i].Contribution; - Group.GroupID = GroupMembership[i].GroupID; - Group.GroupInsigniaID = GroupMembership[i].GroupPicture; - Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); - Group.GroupPowers = GroupMembership[i].GroupPowers; - Groups[i] = Group; - + #region Groups + case PacketType.ActivateGroup: + ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; - } - Groupupdate.GroupData = Groups; - Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); - Groupupdate.AgentData.AgentID = AgentId; - OutPacket(Groupupdate, ThrottleOutPacketType.Task); + #region Packet Session and User Check + if (m_checkPackets) + { + if (activateGroupPacket.AgentData.SessionID != SessionId || + activateGroupPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - try - { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - eq.GroupMembership(Groupupdate, this.AgentId); - } - } - catch (Exception ex) - { - m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending group membership data via UDP"); - OutPacket(Groupupdate, ThrottleOutPacketType.Task); - } - } + if (m_GroupsModule != null) + { + m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); + m_GroupsModule.SendAgentGroupDataUpdate(this); + } + break; + case PacketType.GroupTitlesRequest: + GroupTitlesRequestPacket groupTitlesRequest = + (GroupTitlesRequestPacket)Pack; - public void SendGroupNameReply(UUID groupLLUID, string GroupName) - { - UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); - UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; - UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); - uidnamebloc.ID = groupLLUID; - uidnamebloc.GroupName = Utils.StringToBytes(GroupName); - uidnameblock[0] = uidnamebloc; - pack.UUIDNameBlock = uidnameblock; - OutPacket(pack, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitlesRequest.AgentData.SessionID != SessionId || + groupTitlesRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) - { - LandStatReplyPacket lsrp = new LandStatReplyPacket(); - // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); - LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; - //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - // lsrepdb. - lsrp.RequestData.ReportType = reportType; - lsrp.RequestData.RequestFlags = requestFlags; - lsrp.RequestData.TotalObjectCount = resultCount; - for (int i = 0; i < lsrpia.Length; i++) - { - LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - lsrepdb.LocationX = lsrpia[i].LocationX; - lsrepdb.LocationY = lsrpia[i].LocationY; - lsrepdb.LocationZ = lsrpia[i].LocationZ; - lsrepdb.Score = lsrpia[i].Score; - lsrepdb.TaskID = lsrpia[i].TaskID; - lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; - lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); - lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); - lsrepdba[i] = lsrepdb; - } - lsrp.ReportData = lsrepdba; - OutPacket(lsrp, ThrottleOutPacketType.Task); - } + if (m_GroupsModule != null) + { + GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) - { - ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); - scriptRunningReply.Script.ObjectID = objectID; - scriptRunningReply.Script.ItemID = itemID; - scriptRunningReply.Script.Running = running; + groupTitlesReply.AgentData = + new GroupTitlesReplyPacket.AgentDataBlock(); - OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); - } + groupTitlesReply.AgentData.AgentID = AgentId; + groupTitlesReply.AgentData.GroupID = + groupTitlesRequest.AgentData.GroupID; - public void SendAsset(AssetRequestToClient req) - { - //m_log.Debug("sending asset " + req.RequestAssetID); - TransferInfoPacket Transfer = new TransferInfoPacket(); - Transfer.TransferInfo.ChannelType = 2; - Transfer.TransferInfo.Status = 0; - Transfer.TransferInfo.TargetType = 0; - if (req.AssetRequestSource == 2) - { - Transfer.TransferInfo.Params = new byte[20]; - Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - int assType = req.AssetInf.Type; - Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); - } - else if (req.AssetRequestSource == 3) - { - Transfer.TransferInfo.Params = req.Params; - // Transfer.TransferInfo.Params = new byte[100]; - //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); - } - Transfer.TransferInfo.Size = req.AssetInf.Data.Length; - Transfer.TransferInfo.TransferID = req.TransferRequestID; - Transfer.Header.Zerocoded = true; - OutPacket(Transfer, ThrottleOutPacketType.Asset); + groupTitlesReply.AgentData.RequestID = + groupTitlesRequest.AgentData.RequestID; - if (req.NumPackets == 1) - { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 0; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; - TransferPacket.TransferData.Data = req.AssetInf.Data; - TransferPacket.TransferData.Status = 1; - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - } - else - { - int processedLength = 0; - int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; - int packetNumber = 0; + List titles = + m_GroupsModule.GroupTitlesRequest(this, + groupTitlesRequest.AgentData.GroupID); - while (processedLength < req.AssetInf.Data.Length) - { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = packetNumber; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; + groupTitlesReply.GroupData = + new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); - byte[] chunk = new byte[chunkSize]; - Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); + int i = 0; + foreach (GroupTitlesData d in titles) + { + groupTitlesReply.GroupData[i] = + new GroupTitlesReplyPacket.GroupDataBlock(); - TransferPacket.TransferData.Data = chunk; + groupTitlesReply.GroupData[i].Title = + Utils.StringToBytes(d.Name); + groupTitlesReply.GroupData[i].RoleID = + d.UUID; + groupTitlesReply.GroupData[i].Selected = + d.Selected; + i++; + } - // 0 indicates more packets to come, 1 indicates last packet - if (req.AssetInf.Data.Length - processedLength > maxChunkSize) + OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + } + break; + + case PacketType.GroupProfileRequest: + GroupProfileRequestPacket groupProfileRequest = + (GroupProfileRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - TransferPacket.TransferData.Status = 0; + if (groupProfileRequest.AgentData.SessionID != SessionId || + groupProfileRequest.AgentData.AgentID != AgentId) + break; } - else + #endregion + + if (m_GroupsModule != null) { - TransferPacket.TransferData.Status = 1; + GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + + groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); + groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); + groupProfileReply.AgentData.AgentID = AgentId; + + GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, + groupProfileRequest.GroupData.GroupID); + + groupProfileReply.GroupData.GroupID = d.GroupID; + groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); + groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); + groupProfileReply.GroupData.ShowInList = d.ShowInList; + groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); + groupProfileReply.GroupData.PowersMask = d.PowersMask; + groupProfileReply.GroupData.InsigniaID = d.InsigniaID; + groupProfileReply.GroupData.FounderID = d.FounderID; + groupProfileReply.GroupData.MembershipFee = d.MembershipFee; + groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; + groupProfileReply.GroupData.Money = d.Money; + groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; + groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; + groupProfileReply.GroupData.AllowPublish = d.AllowPublish; + groupProfileReply.GroupData.MaturePublish = d.MaturePublish; + groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + + OutPacket(groupProfileReply, ThrottleOutPacketType.Task); } - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + break; - processedLength += chunkSize; - packetNumber++; - } - } - } + case PacketType.GroupMembersRequest: + GroupMembersRequestPacket groupMembersRequestPacket = + (GroupMembersRequestPacket)Pack; - public void SendTexture(AssetBase TextureAsset) - { + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupMembersRequestPacket.AgentData.SessionID != SessionId || + groupMembersRequestPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - } + if (m_GroupsModule != null) + { + List members = + m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); - public ClientInfo GetClientInfo() - { - ClientInfo info = m_PacketHandler.GetClientInfo(); + int memberCount = members.Count; - info.userEP = m_userEndPoint; - info.proxyEP = m_proxyEndPoint; - info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); + while (true) + { + int blockCount = members.Count; + if (blockCount > 40) + blockCount = 40; - return info; - } + GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); - public EndPoint GetClientEP() - { - return m_userEndPoint; - } + groupMembersReply.AgentData = + new GroupMembersReplyPacket.AgentDataBlock(); + groupMembersReply.GroupData = + new GroupMembersReplyPacket.GroupDataBlock(); + groupMembersReply.MemberData = + new GroupMembersReplyPacket.MemberDataBlock[ + blockCount]; - public void SetClientInfo(ClientInfo info) - { - m_PacketHandler.SetClientInfo(info); - } + groupMembersReply.AgentData.AgentID = AgentId; + groupMembersReply.GroupData.GroupID = + groupMembersRequestPacket.GroupData.GroupID; + groupMembersReply.GroupData.RequestID = + groupMembersRequestPacket.GroupData.RequestID; + groupMembersReply.GroupData.MemberCount = memberCount; - #region Media Parcel Members + for (int i = 0 ; i < blockCount ; i++) + { + GroupMembersData m = members[0]; + members.RemoveAt(0); - public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) - { - ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); - commandMessagePacket.CommandBlock.Flags = flags; - commandMessagePacket.CommandBlock.Command =(uint) command; - commandMessagePacket.CommandBlock.Time = time; + groupMembersReply.MemberData[i] = + new GroupMembersReplyPacket.MemberDataBlock(); + groupMembersReply.MemberData[i].AgentID = + m.AgentID; + groupMembersReply.MemberData[i].Contribution = + m.Contribution; + groupMembersReply.MemberData[i].OnlineStatus = + Utils.StringToBytes(m.OnlineStatus); + groupMembersReply.MemberData[i].AgentPowers = + m.AgentPowers; + groupMembersReply.MemberData[i].Title = + Utils.StringToBytes(m.Title); + groupMembersReply.MemberData[i].IsOwner = + m.IsOwner; + } + OutPacket(groupMembersReply, ThrottleOutPacketType.Task); + if (members.Count == 0) + break; + } + } + break; - OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); - } + case PacketType.GroupRoleDataRequest: + GroupRoleDataRequestPacket groupRolesRequest = + (GroupRoleDataRequestPacket)Pack; - public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, - byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, - byte mediaLoop) - { - ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); - updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); - updatePacket.DataBlock.MediaID = mediaTextureID; - updatePacket.DataBlock.MediaAutoScale = autoScale; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRolesRequest.AgentData.SessionID != SessionId || + groupRolesRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); - updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); - updatePacket.DataBlockExtended.MediaWidth = mediaWidth; - updatePacket.DataBlockExtended.MediaHeight = mediaHeight; - updatePacket.DataBlockExtended.MediaLoop = mediaLoop; + if (m_GroupsModule != null) + { + GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); - OutPacket(updatePacket, ThrottleOutPacketType.Unknown); - } + groupRolesReply.AgentData = + new GroupRoleDataReplyPacket.AgentDataBlock(); - #endregion + groupRolesReply.AgentData.AgentID = AgentId; + groupRolesReply.GroupData = + new GroupRoleDataReplyPacket.GroupDataBlock(); - #region Camera + groupRolesReply.GroupData.GroupID = + groupRolesRequest.GroupData.GroupID; - public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) - { - SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; - uint idx = 0; - foreach (KeyValuePair pair in parameters) - { - SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); - block.Type = pair.Key; - block.Value = pair.Value; + groupRolesReply.GroupData.RequestID = + groupRolesRequest.GroupData.RequestID; - camPropBlock[idx++] = block; - } - packet.CameraProperty = camPropBlock; - OutPacket(packet, ThrottleOutPacketType.Task); - } + List titles = + m_GroupsModule.GroupRoleDataRequest(this, + groupRolesRequest.GroupData.GroupID); + + groupRolesReply.GroupData.RoleCount = + titles.Count; + + groupRolesReply.RoleData = + new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; + + int i = 0; + foreach (GroupRolesData d in titles) + { + groupRolesReply.RoleData[i] = + new GroupRoleDataReplyPacket.RoleDataBlock(); + + groupRolesReply.RoleData[i].RoleID = + d.RoleID; + groupRolesReply.RoleData[i].Name = + Utils.StringToBytes(d.Name); + groupRolesReply.RoleData[i].Title = + Utils.StringToBytes(d.Title); + groupRolesReply.RoleData[i].Description = + Utils.StringToBytes(d.Description); + groupRolesReply.RoleData[i].Powers = + d.Powers; + groupRolesReply.RoleData[i].Members = + (uint)d.Members; + + i++; + } + + OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + } + break; - public void SendClearFollowCamProperties (UUID objectID) - { - ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupRoleMembersRequest: + GroupRoleMembersRequestPacket groupRoleMembersRequest = + (GroupRoleMembersRequestPacket)Pack; - #endregion + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleMembersRequest.AgentData.SessionID != SessionId || + groupRoleMembersRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendRegionHandle(UUID regionID, ulong handle) { - RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); - reply.ReplyBlock.RegionID = regionID; - reply.ReplyBlock.RegionHandle = handle; - OutPacket(reply, ThrottleOutPacketType.Land); - } + if (m_GroupsModule != null) + { + List mappings = + m_GroupsModule.GroupRoleMembersRequest(this, + groupRoleMembersRequest.GroupData.GroupID); - public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) - { - ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); - reply.AgentData.AgentID = m_agentId; - reply.Data.ParcelID = parcelID; - reply.Data.OwnerID = land.OwnerID; - reply.Data.Name = Utils.StringToBytes(land.Name); - reply.Data.Desc = Utils.StringToBytes(land.Description); - reply.Data.ActualArea = land.Area; - reply.Data.BillableArea = land.Area; // TODO: what is this? + int mappingsCount = mappings.Count; - // Bit 0: Mature, bit 7: on sale, other bits: no idea - reply.Data.Flags = (byte)( - ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + - ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + while (mappings.Count > 0) + { + int pairs = mappings.Count; + if (pairs > 32) + pairs = 32; - Vector3 pos = land.UserLocation; - if (pos.Equals(Vector3.Zero)) - { - pos = (land.AABBMax + land.AABBMin) * 0.5f; - } - reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; - reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; - reply.Data.GlobalZ = pos.Z; - reply.Data.SimName = Utils.StringToBytes(info.RegionName); - reply.Data.SnapshotID = land.SnapshotID; - reply.Data.Dwell = land.Dwell; - reply.Data.SalePrice = land.SalePrice; - reply.Data.AuctionID = (int)land.AuctionID; + GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); + groupRoleMembersReply.AgentData = + new GroupRoleMembersReplyPacket.AgentDataBlock(); + groupRoleMembersReply.AgentData.AgentID = + AgentId; + groupRoleMembersReply.AgentData.GroupID = + groupRoleMembersRequest.GroupData.GroupID; + groupRoleMembersReply.AgentData.RequestID = + groupRoleMembersRequest.GroupData.RequestID; - OutPacket(reply, ThrottleOutPacketType.Land); - } + groupRoleMembersReply.AgentData.TotalPairs = + (uint)mappingsCount; - public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) - { - ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); + groupRoleMembersReply.MemberData = + new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; - packet.Data.ObjectName = Utils.StringToBytes(objName); - packet.Data.SimName = Utils.StringToBytes(simName); - packet.Data.SimPosition = pos; - packet.Data.LookAt = lookAt; + for (int i = 0 ; i < pairs ; i++) + { + GroupRoleMembersData d = mappings[0]; + mappings.RemoveAt(0); - OutPacket(packet, ThrottleOutPacketType.Task); - } + groupRoleMembersReply.MemberData[i] = + new GroupRoleMembersReplyPacket.MemberDataBlock(); - public void SetClientOption(string option, string value) - { - switch (option) - { - case "ReliableIsImportant": - bool val; + groupRoleMembersReply.MemberData[i].RoleID = + d.RoleID; + groupRoleMembersReply.MemberData[i].MemberID = + d.MemberID; + } - if (bool.TryParse(value, out val)) - m_PacketHandler.ReliableIsImportant = val; - break; - default: - break; - } - } + OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); + } + } + break; - public string GetClientOption(string option) - { - switch (option) - { - case "ReliableIsImportant": - return m_PacketHandler.ReliableIsImportant.ToString(); + case PacketType.CreateGroupRequest: + CreateGroupRequestPacket createGroupRequest = + (CreateGroupRequestPacket)Pack; - default: + #region Packet Session and User Check + if (m_checkPackets) + { + if (createGroupRequest.AgentData.SessionID != SessionId || + createGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.CreateGroup(this, + Utils.BytesToString(createGroupRequest.GroupData.Name), + Utils.BytesToString(createGroupRequest.GroupData.Charter), + createGroupRequest.GroupData.ShowInList, + createGroupRequest.GroupData.InsigniaID, + createGroupRequest.GroupData.MembershipFee, + createGroupRequest.GroupData.OpenEnrollment, + createGroupRequest.GroupData.AllowPublish, + createGroupRequest.GroupData.MaturePublish); + } break; - } - return string.Empty; - } - public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) - { - DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + case PacketType.UpdateGroupInfo: + UpdateGroupInfoPacket updateGroupInfo = + (UpdateGroupInfoPacket)Pack; - packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (updateGroupInfo.AgentData.SessionID != SessionId || + updateGroupInfo.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; - packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + if (m_GroupsModule != null) + { + m_GroupsModule.UpdateGroupInfo(this, + updateGroupInfo.GroupData.GroupID, + Utils.BytesToString(updateGroupInfo.GroupData.Charter), + updateGroupInfo.GroupData.ShowInList, + updateGroupInfo.GroupData.InsigniaID, + updateGroupInfo.GroupData.MembershipFee, + updateGroupInfo.GroupData.OpenEnrollment, + updateGroupInfo.GroupData.AllowPublish, + updateGroupInfo.GroupData.MaturePublish); + } - packet.QueryReplies = - new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; + break; - packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ - data.Length]; + case PacketType.SetGroupAcceptNotices: + SetGroupAcceptNoticesPacket setGroupAcceptNotices = + (SetGroupAcceptNoticesPacket)Pack; - packet.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (setGroupAcceptNotices.AgentData.SessionID != SessionId || + setGroupAcceptNotices.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryData[0].QueryID = queryID; + if (m_GroupsModule != null) + { + m_GroupsModule.SetGroupAcceptNotices(this, + setGroupAcceptNotices.Data.GroupID, + setGroupAcceptNotices.Data.AcceptNotices, + setGroupAcceptNotices.NewData.ListInProfile); + } - int i = 0; - foreach (DirPlacesReplyData d in data) - { - packet.QueryReplies[i] = - new DirPlacesReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].Dwell = d.dwell; - packet.StatusData[i].Status = d.Status; - i++; - } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupTitleUpdate: + GroupTitleUpdatePacket groupTitleUpdate = + (GroupTitleUpdatePacket)Pack; - public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) - { - DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitleUpdate.AgentData.SessionID != SessionId || + groupTitleUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + m_GroupsModule.GroupTitleUpdate(this, + groupTitleUpdate.AgentData.GroupID, + groupTitleUpdate.AgentData.TitleRoleID); + } - packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + break; - packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ - data.Length]; - int i = 0; - foreach (DirPeopleReplyData d in data) - { - packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].AgentID = d.agentID; - packet.QueryReplies[i].FirstName = - Utils.StringToBytes(d.firstName); - packet.QueryReplies[i].LastName = - Utils.StringToBytes(d.lastName); - packet.QueryReplies[i].Group = - Utils.StringToBytes(d.group); - packet.QueryReplies[i].Online = d.online; - packet.QueryReplies[i].Reputation = d.reputation; - i++; - } + case PacketType.ParcelDeedToGroup: + ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; + if (m_GroupsModule != null) + { + ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; + if (handlerParcelDeedToGroup != null) + { + handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); - OutPacket(packet, ThrottleOutPacketType.Task); - } + } + } - public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) - { - DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); + break; - packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; - packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.GroupNoticesListRequest: + GroupNoticesListRequestPacket groupNoticesListRequest = + (GroupNoticesListRequestPacket)Pack; - packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticesListRequest.AgentData.SessionID != SessionId || + groupNoticesListRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ - data.Length]; + if (m_GroupsModule != null) + { + GroupNoticeData[] gn = + m_GroupsModule.GroupNoticesListRequest(this, + groupNoticesListRequest.Data.GroupID); - int i = 0; - foreach (DirEventsReplyData d in data) - { - packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].OwnerID = d.ownerID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].EventID = d.eventID; - packet.QueryReplies[i].Date = - Utils.StringToBytes(d.date); - packet.QueryReplies[i].UnixTime = d.unixTime; - packet.QueryReplies[i].EventFlags = d.eventFlags; - packet.StatusData[i].Status = d.Status; - i++; - } + GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); + groupNoticesListReply.AgentData = + new GroupNoticesListReplyPacket.AgentDataBlock(); + groupNoticesListReply.AgentData.AgentID = AgentId; + groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; - OutPacket(packet, ThrottleOutPacketType.Task); - } + groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; - public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) - { - DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); + int i = 0; + foreach (GroupNoticeData g in gn) + { + groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); + groupNoticesListReply.Data[i].NoticeID = + g.NoticeID; + groupNoticesListReply.Data[i].Timestamp = + g.Timestamp; + groupNoticesListReply.Data[i].FromName = + Utils.StringToBytes(g.FromName); + groupNoticesListReply.Data[i].Subject = + Utils.StringToBytes(g.Subject); + groupNoticesListReply.Data[i].HasAttachment = + g.HasAttachment; + groupNoticesListReply.Data[i].AssetType = + g.AssetType; + i++; + } - packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); + } - packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + break; + case PacketType.GroupNoticeRequest: + GroupNoticeRequestPacket groupNoticeRequest = + (GroupNoticeRequestPacket)Pack; - packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticeRequest.AgentData.SessionID != SessionId || + groupNoticeRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - int i = 0; - foreach (DirGroupsReplyData d in data) - { - packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].GroupID = d.groupID; - packet.QueryReplies[i].GroupName = - Utils.StringToBytes(d.groupName); - packet.QueryReplies[i].Members = d.members; - packet.QueryReplies[i].SearchOrder = d.searchOrder; - i++; - } + if (m_GroupsModule != null) + { + m_GroupsModule.GroupNoticeRequest(this, + groupNoticeRequest.Data.GroupNoticeID); + } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupRoleUpdate: + GroupRoleUpdatePacket groupRoleUpdate = + (GroupRoleUpdatePacket)Pack; - public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) - { - DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleUpdate.AgentData.SessionID != SessionId || + groupRoleUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + foreach (GroupRoleUpdatePacket.RoleDataBlock d in + groupRoleUpdate.RoleData) + { + m_GroupsModule.GroupRoleUpdate(this, + groupRoleUpdate.AgentData.GroupID, + d.RoleID, + Utils.BytesToString(d.Name), + Utils.BytesToString(d.Description), + Utils.BytesToString(d.Title), + d.Powers, + d.UpdateType); + } + m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); + } + break; - packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.GroupRoleChanges: + GroupRoleChangesPacket groupRoleChanges = + (GroupRoleChangesPacket)Pack; - packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ - data.Length]; - packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleChanges.AgentData.SessionID != SessionId || + groupRoleChanges.AgentData.AgentID != AgentId) + break; + } + #endregion - int i = 0; - foreach (DirClassifiedReplyData d in data) - { - packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ClassifiedID = d.classifiedID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; - packet.QueryReplies[i].CreationDate = d.creationDate; - packet.QueryReplies[i].ExpirationDate = d.expirationDate; - packet.QueryReplies[i].PriceForListing = d.price; - packet.StatusData[i].Status = d.Status; - i++; - } + if (m_GroupsModule != null) + { + foreach (GroupRoleChangesPacket.RoleChangeBlock d in + groupRoleChanges.RoleChange) + { + m_GroupsModule.GroupRoleChanges(this, + groupRoleChanges.AgentData.GroupID, + d.RoleID, + d.MemberID, + d.Change); + } + m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); + } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.JoinGroupRequest: + JoinGroupRequestPacket joinGroupRequest = + (JoinGroupRequestPacket)Pack; - public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) - { - DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (joinGroupRequest.AgentData.SessionID != SessionId || + joinGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + m_GroupsModule.JoinGroupRequest(this, + joinGroupRequest.GroupData.GroupID); + } + break; - packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.LeaveGroupRequest: + LeaveGroupRequestPacket leaveGroupRequest = + (LeaveGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (leaveGroupRequest.AgentData.SessionID != SessionId || + leaveGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.LeaveGroupRequest(this, + leaveGroupRequest.GroupData.GroupID); + } + break; + + case PacketType.EjectGroupMemberRequest: + EjectGroupMemberRequestPacket ejectGroupMemberRequest = + (EjectGroupMemberRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || + ejectGroupMemberRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ - data.Length]; + if (m_GroupsModule != null) + { + foreach (EjectGroupMemberRequestPacket.EjectDataBlock e + in ejectGroupMemberRequest.EjectData) + { + m_GroupsModule.EjectGroupMemberRequest(this, + ejectGroupMemberRequest.GroupData.GroupID, + e.EjecteeID); + } + } + break; - int i = 0; - foreach (DirLandReplyData d in data) - { - packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].SalePrice = d.salePrice; - packet.QueryReplies[i].ActualArea = d.actualArea; - i++; - } + case PacketType.InviteGroupRequest: + InviteGroupRequestPacket inviteGroupRequest = + (InviteGroupRequestPacket)Pack; - OutPacket(packet, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (inviteGroupRequest.AgentData.SessionID != SessionId || + inviteGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) - { - DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); + if (m_GroupsModule != null) + { + foreach (InviteGroupRequestPacket.InviteDataBlock b in + inviteGroupRequest.InviteData) + { + m_GroupsModule.InviteGroupRequest(this, + inviteGroupRequest.GroupData.GroupID, + b.InviteeID, + b.RoleID); + } + } + break; - packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + #endregion + case PacketType.StartLure: + StartLurePacket startLureRequest = (StartLurePacket)Pack; - packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + #region Packet Session and User Check + if (m_checkPackets) + { + if (startLureRequest.AgentData.SessionID != SessionId || + startLureRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ - data.Length]; + StartLure handlerStartLure = OnStartLure; + if (handlerStartLure != null) + handlerStartLure(startLureRequest.Info.LureType, + Utils.BytesToString( + startLureRequest.Info.Message), + startLureRequest.TargetData[0].TargetID, + this); + break; - int i = 0; - foreach (DirPopularReplyData d in data) - { - packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Dwell = d.dwell; - i++; - } + case PacketType.TeleportLureRequest: + TeleportLureRequestPacket teleportLureRequest = + (TeleportLureRequestPacket)Pack; - OutPacket(packet, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (teleportLureRequest.Info.SessionID != SessionId || + teleportLureRequest.Info.AgentID != AgentId) + break; + } + #endregion - public void SendEventInfoReply(EventData data) - { - EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); + TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest; + if (handlerTeleportLureRequest != null) + handlerTeleportLureRequest( + teleportLureRequest.Info.LureID, + teleportLureRequest.Info.TeleportFlags, + this); + break; - packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + case PacketType.ClassifiedInfoRequest: + ClassifiedInfoRequestPacket classifiedInfoRequest = + (ClassifiedInfoRequestPacket)Pack; - packet.EventData = new EventInfoReplyPacket.EventDataBlock(); - packet.EventData.EventID = data.eventID; - packet.EventData.Creator = Utils.StringToBytes(data.creator); - packet.EventData.Name = Utils.StringToBytes(data.name); - packet.EventData.Category = Utils.StringToBytes(data.category); - packet.EventData.Desc = Utils.StringToBytes(data.description); - packet.EventData.Date = Utils.StringToBytes(data.date); - packet.EventData.DateUTC = data.dateUTC; - packet.EventData.Duration = data.duration; - packet.EventData.Cover = data.cover; - packet.EventData.Amount = data.amount; - packet.EventData.SimName = Utils.StringToBytes(data.simName); - packet.EventData.GlobalPos = new Vector3d(data.globalPos); - packet.EventData.EventFlags = data.eventFlags; + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoRequest.AgentData.SessionID != SessionId || + classifiedInfoRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(packet, ThrottleOutPacketType.Task); - } + ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest; + if (handlerClassifiedInfoRequest != null) + handlerClassifiedInfoRequest( + classifiedInfoRequest.Data.ClassifiedID, + this); + break; - public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) - { - MapItemReplyPacket mirplk = new MapItemReplyPacket(); - mirplk.AgentData.AgentID = AgentId; - mirplk.RequestData.ItemType = mapitemtype; - mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; - for (int i = 0; i < replies.Length; i++) - { - MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); - mrdata.X = replies[i].x; - mrdata.Y = replies[i].y; - mrdata.ID = replies[i].id; - mrdata.Extra = replies[i].Extra; - mrdata.Extra2 = replies[i].Extra2; - mrdata.Name = Utils.StringToBytes(replies[i].name); - mirplk.Data[i] = mrdata; - } - //m_log.Debug(mirplk.ToString()); - OutPacket(mirplk, ThrottleOutPacketType.Task); + case PacketType.ClassifiedInfoUpdate: + ClassifiedInfoUpdatePacket classifiedInfoUpdate = + (ClassifiedInfoUpdatePacket)Pack; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoUpdate.AgentData.SessionID != SessionId || + classifiedInfoUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendOfferCallingCard(UUID srcID, UUID transactionID) - { - // a bit special, as this uses AgentID to store the source instead - // of the destination. The destination (the receiver) goes into destID - OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); - p.AgentData.AgentID = srcID; - p.AgentData.SessionID = UUID.Zero; - p.AgentBlock.DestID = AgentId; - p.AgentBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); - } + ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; + if (handlerClassifiedInfoUpdate != null) + handlerClassifiedInfoUpdate( + classifiedInfoUpdate.Data.ClassifiedID, + classifiedInfoUpdate.Data.Category, + Utils.BytesToString( + classifiedInfoUpdate.Data.Name), + Utils.BytesToString( + classifiedInfoUpdate.Data.Desc), + classifiedInfoUpdate.Data.ParcelID, + classifiedInfoUpdate.Data.ParentEstate, + classifiedInfoUpdate.Data.SnapshotID, + new Vector3( + classifiedInfoUpdate.Data.PosGlobal), + classifiedInfoUpdate.Data.ClassifiedFlags, + classifiedInfoUpdate.Data.PriceForListing, + this); + break; - public void SendAcceptCallingCard(UUID transactionID) - { - AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; - p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); - p.FolderData[0].FolderID = UUID.Zero; - OutPacket(p, ThrottleOutPacketType.Task); - } + case PacketType.ClassifiedDelete: + ClassifiedDeletePacket classifiedDelete = + (ClassifiedDeletePacket)Pack; - public void SendDeclineCallingCard(UUID transactionID) - { - DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.TransactionBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedDelete.AgentData.SessionID != SessionId || + classifiedDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendTerminateFriend(UUID exFriendID) - { - TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = SessionId; - p.ExBlock.OtherID = exFriendID; - OutPacket(p, ThrottleOutPacketType.Task); - } + ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete; + if (handlerClassifiedDelete != null) + handlerClassifiedDelete( + classifiedDelete.Data.ClassifiedID, + this); + break; - public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) - { - AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); + case PacketType.ClassifiedGodDelete: + ClassifiedGodDeletePacket classifiedGodDelete = + (ClassifiedGodDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedGodDelete.AgentData.SessionID != SessionId || + classifiedGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; - p.AgentData.AvatarID = avatarID; + ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; + if (handlerClassifiedGodDelete != null) + handlerClassifiedGodDelete( + classifiedGodDelete.Data.ClassifiedID, + this); + break; - p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; - int i = 0; - foreach (GroupMembershipData m in data) - { - p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); - p.GroupData[i].GroupPowers = m.GroupPowers; - p.GroupData[i].AcceptNotices = m.AcceptNotices; - p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); - p.GroupData[i].GroupID = m.GroupID; - p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); - p.GroupData[i].GroupInsigniaID = m.GroupPicture; - i++; - } + case PacketType.EventGodDelete: + EventGodDeletePacket eventGodDelete = + (EventGodDeletePacket)Pack; - p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); - p.NewGroupData.ListInProfile = true; + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventGodDelete.AgentData.SessionID != SessionId || + eventGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(p, ThrottleOutPacketType.Task); - } + EventGodDelete handlerEventGodDelete = OnEventGodDelete; + if (handlerEventGodDelete != null) + handlerEventGodDelete( + eventGodDelete.EventData.EventID, + eventGodDelete.QueryData.QueryID, + Utils.BytesToString( + eventGodDelete.QueryData.QueryText), + eventGodDelete.QueryData.QueryFlags, + eventGodDelete.QueryData.QueryStart, + this); + break; - public void SendJoinGroupReply(UUID groupID, bool success) - { - JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); + case PacketType.EventNotificationAddRequest: + EventNotificationAddRequestPacket eventNotificationAdd = + (EventNotificationAddRequestPacket)Pack; - p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationAdd.AgentData.SessionID != SessionId || + eventNotificationAdd.AgentData.AgentID != AgentId) + break; + } + #endregion - p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest; + if (handlerEventNotificationAddRequest != null) + handlerEventNotificationAddRequest( + eventNotificationAdd.EventData.EventID, this); + break; - OutPacket(p, ThrottleOutPacketType.Task); - } + case PacketType.EventNotificationRemoveRequest: + EventNotificationRemoveRequestPacket eventNotificationRemove = + (EventNotificationRemoveRequestPacket)Pack; - public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) - { - EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationRemove.AgentData.SessionID != SessionId || + eventNotificationRemove.AgentData.AgentID != AgentId) + break; + } + #endregion - p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = agentID; + EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; + if (handlerEventNotificationRemoveRequest != null) + handlerEventNotificationRemoveRequest( + eventNotificationRemove.EventData.EventID, this); + break; - p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; + case PacketType.RetrieveInstantMessages: + RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; - p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); - p.EjectData.Success = success; + #region Packet Session and User Check + if (m_checkPackets) + { + if (rimpInstantMessagePack.AgentData.SessionID != SessionId || + rimpInstantMessagePack.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(p, ThrottleOutPacketType.Task); - } + RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages; + if (handlerRetrieveInstantMessages != null) + handlerRetrieveInstantMessages(this); + break; - public void SendLeaveGroupReply(UUID groupID, bool success) - { - LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); + case PacketType.PickDelete: + PickDeletePacket pickDelete = + (PickDeletePacket)Pack; - p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickDelete.AgentData.SessionID != SessionId || + pickDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + PickDelete handlerPickDelete = OnPickDelete; + if (handlerPickDelete != null) + handlerPickDelete(this, pickDelete.Data.PickID); + break; + case PacketType.PickGodDelete: + PickGodDeletePacket pickGodDelete = + (PickGodDeletePacket)Pack; - OutPacket(p, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickGodDelete.AgentData.SessionID != SessionId || + pickGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) - { - if (classifiedID.Length != name.Length) - return; + PickGodDelete handlerPickGodDelete = OnPickGodDelete; + if (handlerPickGodDelete != null) + handlerPickGodDelete(this, + pickGodDelete.AgentData.AgentID, + pickGodDelete.Data.PickID, + pickGodDelete.Data.QueryID); + break; + case PacketType.PickInfoUpdate: + PickInfoUpdatePacket pickInfoUpdate = + (PickInfoUpdatePacket)Pack; - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickInfoUpdate.AgentData.SessionID != SessionId || + pickInfoUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; + PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate; + if (handlerPickInfoUpdate != null) + handlerPickInfoUpdate(this, + pickInfoUpdate.Data.PickID, + pickInfoUpdate.Data.CreatorID, + pickInfoUpdate.Data.TopPick, + Utils.BytesToString(pickInfoUpdate.Data.Name), + Utils.BytesToString(pickInfoUpdate.Data.Desc), + pickInfoUpdate.Data.SnapshotID, + pickInfoUpdate.Data.SortOrder, + pickInfoUpdate.Data.Enabled); + break; + case PacketType.AvatarNotesUpdate: + AvatarNotesUpdatePacket avatarNotesUpdate = + (AvatarNotesUpdatePacket)Pack; - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; - int i; - for (i = 0 ; i < classifiedID.Length ; i++) - { - ac.Data[i].ClassifiedID = classifiedID[i]; - ac.Data[i].Name = Utils.StringToBytes(name[i]); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarNotesUpdate.AgentData.SessionID != SessionId || + avatarNotesUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(ac, ThrottleOutPacketType.Task); - } + AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate; + if (handlerAvatarNotesUpdate != null) + handlerAvatarNotesUpdate(this, + avatarNotesUpdate.Data.TargetID, + Utils.BytesToString(avatarNotesUpdate.Data.Notes)); + break; - public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) - { - ClassifiedInfoReplyPacket cr = - (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ClassifiedInfoReply); +// case PacketType.AvatarInterestsUpdate: +// AvatarInterestsUpdatePacket avatarInterestUpdate = +// (AvatarInterestsUpdatePacket)Pack; +// +// break; - cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); - cr.AgentData.AgentID = AgentId; + case PacketType.PlacesQuery: + PlacesQueryPacket placesQueryPacket = + (PlacesQueryPacket)Pack; - cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); - cr.Data.ClassifiedID = classifiedID; - cr.Data.CreatorID = creatorID; - cr.Data.CreationDate = creationDate; - cr.Data.ExpirationDate = expirationDate; - cr.Data.Category = category; - cr.Data.Name = Utils.StringToBytes(name); - cr.Data.Desc = Utils.StringToBytes(description); - cr.Data.ParcelID = parcelID; - cr.Data.ParentEstate = parentEstate; - cr.Data.SnapshotID = snapshotID; - cr.Data.SimName = Utils.StringToBytes(simName); - cr.Data.PosGlobal = new Vector3d(globalPos); - cr.Data.ParcelName = Utils.StringToBytes(parcelName); - cr.Data.ClassifiedFlags = classifiedFlags; - cr.Data.PriceForListing = price; + PlacesQuery handlerPlacesQuery = OnPlacesQuery; - OutPacket(cr, ThrottleOutPacketType.Task); - } + if (handlerPlacesQuery != null) + handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, + placesQueryPacket.TransactionData.TransactionID, + Utils.BytesToString( + placesQueryPacket.QueryData.QueryText), + placesQueryPacket.QueryData.QueryFlags, + (byte)placesQueryPacket.QueryData.Category, + Utils.BytesToString( + placesQueryPacket.QueryData.SimName), + this); + break; + default: + m_log.Warn("[CLIENT]: unhandled packet " + Pack); + break; - public void SendAgentDropGroup(UUID groupID) - { - AgentDropGroupPacket dg = - (AgentDropGroupPacket)PacketPool.Instance.GetPacket( - PacketType.AgentDropGroup); + #endregion + } - dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); - dg.AgentData.AgentID = AgentId; - dg.AgentData.GroupID = groupID; + PacketPool.Instance.ReturnPacket(Pack); - OutPacket(dg, ThrottleOutPacketType.Task); } - public void SendAvatarNotesReply(UUID targetID, string text) + private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) { - AvatarNotesReplyPacket an = - (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarNotesReply); + PrimitiveBaseShape shape = new PrimitiveBaseShape(); - an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); - an.AgentData.AgentID = AgentId; + shape.PCode = addPacket.ObjectData.PCode; + shape.State = addPacket.ObjectData.State; + shape.PathBegin = addPacket.ObjectData.PathBegin; + shape.PathEnd = addPacket.ObjectData.PathEnd; + shape.PathScaleX = addPacket.ObjectData.PathScaleX; + shape.PathScaleY = addPacket.ObjectData.PathScaleY; + shape.PathShearX = addPacket.ObjectData.PathShearX; + shape.PathShearY = addPacket.ObjectData.PathShearY; + shape.PathSkew = addPacket.ObjectData.PathSkew; + shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; + shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; + shape.Scale = addPacket.ObjectData.Scale; + shape.PathCurve = addPacket.ObjectData.PathCurve; + shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; + shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; + shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; + shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; + shape.PathTaperX = addPacket.ObjectData.PathTaperX; + shape.PathTaperY = addPacket.ObjectData.PathTaperY; + shape.PathTwist = addPacket.ObjectData.PathTwist; + shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); + shape.TextureEntry = ntex.GetBytes(); + //shape.Textures = ntex; + return shape; + } + + public ClientInfo GetClientInfo() + { + ClientInfo info = m_udpClient.GetClientInfo(); - an.Data = new AvatarNotesReplyPacket.DataBlock(); - an.Data.TargetID = targetID; - an.Data.Notes = Utils.StringToBytes(text); + info.userEP = m_userEndPoint; + info.proxyEP = null; + info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); - OutPacket(an, ThrottleOutPacketType.Task); + return info; } - public void SendAvatarPicksReply(UUID targetID, Dictionary picks) + public EndPoint GetClientEP() { - AvatarPicksReplyPacket ap = - (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarPicksReply); + return m_userEndPoint; + } - ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); - ap.AgentData.AgentID = AgentId; - ap.AgentData.TargetID = targetID; + public void SetClientInfo(ClientInfo info) + { + m_udpClient.SetClientInfo(info); + } - ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; + #region Media Parcel Members - int i = 0; - foreach (KeyValuePair pick in picks) - { - ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); - ap.Data[i].PickID = pick.Key; - ap.Data[i].PickName = Utils.StringToBytes(pick.Value); - i++; - } + public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) + { + ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); + commandMessagePacket.CommandBlock.Flags = flags; + commandMessagePacket.CommandBlock.Command =(uint) command; + commandMessagePacket.CommandBlock.Time = time; - OutPacket(ap, ThrottleOutPacketType.Task); + OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); } - public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, + byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, + byte mediaLoop) { - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); - - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; - - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; + ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); + updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); + updatePacket.DataBlock.MediaID = mediaTextureID; + updatePacket.DataBlock.MediaAutoScale = autoScale; - int i = 0; - foreach (KeyValuePair classified in classifieds) - { - ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); - ac.Data[i].ClassifiedID = classified.Key; - ac.Data[i].Name = Utils.StringToBytes(classified.Value); - i++; - } + updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); + updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); + updatePacket.DataBlockExtended.MediaWidth = mediaWidth; + updatePacket.DataBlockExtended.MediaHeight = mediaHeight; + updatePacket.DataBlockExtended.MediaLoop = mediaLoop; - OutPacket(ac, ThrottleOutPacketType.Task); + OutPacket(updatePacket, ThrottleOutPacketType.Unknown); } - public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) - { - ParcelDwellReplyPacket pd = - (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ParcelDwellReply); + #endregion - pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); - pd.AgentData.AgentID = AgentId; + #region Camera - pd.Data = new ParcelDwellReplyPacket.DataBlock(); - pd.Data.LocalID = localID; - pd.Data.ParcelID = parcelID; - pd.Data.Dwell = dwell; + public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) + { + SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; + uint idx = 0; + foreach (KeyValuePair pair in parameters) + { + SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); + block.Type = pair.Key; + block.Value = pair.Value; - OutPacket(pd, ThrottleOutPacketType.Land); + camPropBlock[idx++] = block; + } + packet.CameraProperty = camPropBlock; + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendUserInfoReply(bool imViaEmail, bool visible, string email) + public void SendClearFollowCamProperties (UUID objectID) { - UserInfoReplyPacket ur = - (UserInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.UserInfoReply); - - string Visible = "hidden"; - if (visible) - Visible = "default"; + ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + OutPacket(packet, ThrottleOutPacketType.Task); + } - ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); - ur.AgentData.AgentID = AgentId; + #endregion - ur.UserData = new UserInfoReplyPacket.UserDataBlock(); - ur.UserData.IMViaEMail = imViaEmail; - ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); - ur.UserData.EMail = Utils.StringToBytes(email); + public void SetClientOption(string option, string value) + { + switch (option) + { + default: + break; + } + } - OutPacket(ur, ThrottleOutPacketType.Task); + public string GetClientOption(string option) + { + switch (option) + { + default: + break; + } + return string.Empty; } public void KillEndDone() { - KillPacket kp = new KillPacket(); - OutPacket(kp, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + m_udpClient.Shutdown(); } #region IClientCore @@ -10767,13 +10324,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - protected virtual void RegisterInterfaces() - { - RegisterInterface(this); - RegisterInterface(this); - RegisterInterface(this); - } - public bool TryGet(out T iface) { if (m_clientInterfaces.ContainsKey(typeof(T))) @@ -10821,78 +10371,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void SendCreateGroupReply(UUID groupID, bool success, string message) - { - CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); - - createGroupReply.AgentData = - new CreateGroupReplyPacket.AgentDataBlock(); - createGroupReply.ReplyData = - new CreateGroupReplyPacket.ReplyDataBlock(); - - createGroupReply.AgentData.AgentID = AgentId; - createGroupReply.ReplyData.GroupID = groupID; - - createGroupReply.ReplyData.Success = success; - createGroupReply.ReplyData.Message = Utils.StringToBytes(message); - OutPacket(createGroupReply, ThrottleOutPacketType.Task); - } - - public void SendUseCachedMuteList() - { - UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); - - useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); - useCachedMuteList.AgentData.AgentID = AgentId; - - OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); - } - - public void SendMuteListUpdate(string filename) - { - MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); - - muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); - muteListUpdate.MuteData.AgentID = AgentId; - muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); - - OutPacket(muteListUpdate, ThrottleOutPacketType.Task); - } - - public void SendPickInfoReply(UUID pickID,UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) - { - PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); - - pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); - pickInfoReply.AgentData.AgentID = AgentId; - - pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); - pickInfoReply.Data.PickID = pickID; - pickInfoReply.Data.CreatorID = creatorID; - pickInfoReply.Data.TopPick = topPick; - pickInfoReply.Data.ParcelID = parcelID; - pickInfoReply.Data.Name = Utils.StringToBytes(name); - pickInfoReply.Data.Desc = Utils.StringToBytes(desc); - pickInfoReply.Data.SnapshotID = snapshotID; - pickInfoReply.Data.User = Utils.StringToBytes(user); - pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); - pickInfoReply.Data.SimName = Utils.StringToBytes(simName); - pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); - pickInfoReply.Data.SortOrder = sortOrder; - pickInfoReply.Data.Enabled = enabled; - - OutPacket(pickInfoReply, ThrottleOutPacketType.Task); - } - public string Report() { - LLPacketHandler handler = (LLPacketHandler) m_PacketHandler; - return handler.PacketQueue.GetStats(); + return m_udpClient.GetStats(); } public string XReport(string uptime, string version) { - return ""; + return String.Empty; } public void MakeAssetRequest(TransferRequestPacket transferRequest) @@ -10981,7 +10467,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return numPackets; } - #region IClientIPEndpoint Members public IPAddress EndPoint diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index facfb9d..5219df7 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs @@ -172,7 +172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_lastloopprocessed = DateTime.Now.Ticks; // This can happen during Close() - if (m_client == null || m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null) + if (m_client == null) return false; while ((imagereq = GetHighestPriorityImage()) != null) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index e98a360..f30df4d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -39,7 +39,12 @@ using Timer=System.Timers.Timer; namespace OpenSim.Region.ClientStack.LindenUDP { - public class LLPacketHandler : ILLPacketHandler + public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); + public delegate void PacketDrop(Packet pack, Object id); + public delegate void QueueEmpty(ThrottleOutPacketType queue); + public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType); + + public class LLPacketHandler { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs index 70d94e7..f08b7be 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // private static readonly log4net.ILog m_log // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - protected readonly ILLClientStackNetworkHandler m_networkHandler; + protected readonly LLUDPServer m_networkHandler; protected IScene m_scene; /// @@ -50,7 +50,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private ClientStackUserSettings m_userSettings; - public LLPacketServer(ILLClientStackNetworkHandler networkHandler, ClientStackUserSettings userSettings) + public LLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings) { m_userSettings = userSettings; m_networkHandler = networkHandler; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index c779b08..7964c50 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -26,616 +26,727 @@ */ using System; -using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Reflection; +using System.Threading; using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; +using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { - /// - /// This class handles the initial UDP circuit setup with a client and passes on subsequent packets to the LLPacketServer - /// - public class LLUDPServer : ILLClientStackNetworkHandler, IClientNetworkServer + public class LLUDPServerShim : IClientNetworkServer { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The client circuits established with this UDP server. If a client exists here we can also assume that - /// it is populated in clientCircuits_reverse and proxyCircuits (if relevant) - /// - protected Dictionary clientCircuits = new Dictionary(); - public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable()); - protected Dictionary proxyCircuits = new Dictionary(); - - private Socket m_socket; - protected IPEndPoint ServerIncoming; - protected byte[] RecvBuffer = new byte[4096]; - protected byte[] ZeroBuffer = new byte[8192]; - - /// - /// This is an endpoint that is reused where we don't need to protect the information from potentially - /// being stomped on by other threads. - /// - protected EndPoint reusedEpSender = new IPEndPoint(IPAddress.Any, 0); - - protected int proxyPortOffset; - - protected AsyncCallback ReceivedData; - protected LLPacketServer m_packetServer; - protected Location m_location; - - protected uint listenPort; - protected bool Allow_Alternate_Port; - protected IPAddress listenIP = IPAddress.Parse("0.0.0.0"); - protected IScene m_localScene; - protected int m_clientSocketReceiveBuffer = 0; + LLUDPServer m_udpServer; - /// - /// Manages authentication for agent circuits - /// - protected AgentCircuitManager m_circuitManager; - - public IScene LocalScene + public LLUDPServerShim() { - set - { - m_localScene = value; - m_packetServer.LocalScene = m_localScene; - - m_location = new Location(m_localScene.RegionInfo.RegionHandle); - } } - public ulong RegionHandle + public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) { - get { return m_location.RegionHandle; } + m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); } - Socket IClientNetworkServer.Server + public void NetworkStop() { - get { return m_socket; } + m_udpServer.Stop(); } - public bool HandlesRegion(Location x) + public void AddScene(IScene scene) { - //return x.RegionHandle == m_location.RegionHandle; - return x == m_location; + m_udpServer.AddScene(scene); } - public void AddScene(IScene x) + public bool HandlesRegion(Location x) { - LocalScene = x; + return m_udpServer.HandlesRegion(x); } public void Start() { - ServerListener(); + m_udpServer.Start(); } public void Stop() { - m_socket.Close(); + m_udpServer.Stop(); } + } + + public class LLUDPServer : UDPBase + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public LLUDPServer() + /// Handlers for incoming packets + //PacketEventDictionary packetEvents = new PacketEventDictionary(); + /// Incoming packets that are awaiting handling + private OpenMetaverse.BlockingQueue packetInbox = new OpenMetaverse.BlockingQueue(); + /// + private UDPClientCollection clients = new UDPClientCollection(); + /// Bandwidth throttle for this UDP server + private TokenBucket m_throttle; + /// Bandwidth throttle rates for this UDP server + private ThrottleRates m_throttleRates; + /// Manages authentication for agent circuits + private AgentCircuitManager m_circuitManager; + /// Reference to the scene this UDP server is attached to + private IScene m_scene; + /// The X/Y coordinates of the scene this UDP server is attached to + private Location m_location; + /// The measured resolution of Environment.TickCount + private float m_tickCountResolution; + + /// The measured resolution of Environment.TickCount + public float TickCountResolution { get { return m_tickCountResolution; } } + public Socket Server { get { return null; } } + + public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) + : base((int)port) { + #region Environment.TickCount Measurement + + // Measure the resolution of Environment.TickCount + m_tickCountResolution = 0f; + for (int i = 0; i < 5; i++) + { + int start = Environment.TickCount; + int now = start; + while (now == start) + now = Environment.TickCount; + m_tickCountResolution += (float)(now - start) * 0.2f; + } + m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms"); + + #endregion Environment.TickCount Measurement + + m_circuitManager = circuitManager; + + // TODO: Config support for throttling the entire connection + m_throttle = new TokenBucket(null, 0, 0); + m_throttleRates = new ThrottleRates(configSource); } - public LLUDPServer( - IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource, - AgentCircuitManager authenticateClass) + public new void Start() { - Initialise(_listenIP, ref port, proxyPortOffset, allow_alternate_port, configSource, authenticateClass); + if (m_scene == null) + throw new InvalidOperationException("Cannot LLUDPServer.Start() without an IScene reference"); + + base.Start(); + + // Start the incoming packet processing thread + Thread incomingThread = new Thread(IncomingPacketHandler); + incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")"; + incomingThread.Start(); + + Thread outgoingThread = new Thread(OutgoingPacketHandler); + outgoingThread.Name = "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")"; + outgoingThread.Start(); } - /// - /// Initialize the server - /// - /// - /// - /// - /// - /// - /// - /// - public void Initialise( - IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, - AgentCircuitManager circuitManager) + public new void Stop() { - ClientStackUserSettings userSettings = new ClientStackUserSettings(); - - IConfig config = configSource.Configs["ClientStack.LindenUDP"]; + base.Stop(); + } - if (config != null) + public void AddScene(IScene scene) + { + if (m_scene == null) { - if (config.Contains("client_throttle_max_bps")) - { - int maxBPS = config.GetInt("client_throttle_max_bps", 1500000); - userSettings.TotalThrottleSettings = new ThrottleSettings(0, maxBPS, - maxBPS > 28000 ? maxBPS : 28000); - } - - if (config.Contains("client_throttle_multiplier")) - userSettings.ClientThrottleMultipler = config.GetFloat("client_throttle_multiplier"); - if (config.Contains("client_socket_rcvbuf_size")) - m_clientSocketReceiveBuffer = config.GetInt("client_socket_rcvbuf_size"); - } - - m_log.DebugFormat("[CLIENT]: client_throttle_multiplier = {0}", userSettings.ClientThrottleMultipler); - m_log.DebugFormat("[CLIENT]: client_socket_rcvbuf_size = {0}", (m_clientSocketReceiveBuffer != 0 ? - m_clientSocketReceiveBuffer.ToString() : "OS default")); - - proxyPortOffset = proxyPortOffsetParm; - listenPort = (uint) (port + proxyPortOffsetParm); - listenIP = _listenIP; - Allow_Alternate_Port = allow_alternate_port; - m_circuitManager = circuitManager; - CreatePacketServer(userSettings); - - // Return new port - // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered. - // So the option allow_alternate_ports="true" was added to default.xml - port = (uint)(listenPort - proxyPortOffsetParm); + m_scene = scene; + m_location = new Location(m_scene.RegionInfo.RegionHandle); + } + else + { + m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); + } } - protected virtual void CreatePacketServer(ClientStackUserSettings userSettings) + public bool HandlesRegion(Location x) { - new LLPacketServer(this, userSettings); + return x == m_location; } - /// - /// This method is called every time that we receive new UDP data. - /// - /// - protected virtual void OnReceivedData(IAsyncResult result) + public void RemoveClient(IClientAPI client) { - Packet packet = null; - int numBytes = 1; - EndPoint epSender = new IPEndPoint(IPAddress.Any, 0); - EndPoint epProxy = null; + m_scene.ClientManager.Remove(client.CircuitCode); + client.Close(false); - try + LLUDPClient udpClient; + if (clients.TryGetValue(client.AgentId, out udpClient)) { - if (EndReceive(out numBytes, result, ref epSender)) - { - // Make sure we are getting zeroes when running off the - // end of grab / degrab packets from old clients - Array.Clear(RecvBuffer, numBytes, RecvBuffer.Length - numBytes); - - int packetEnd = numBytes - 1; - if (proxyPortOffset != 0) packetEnd -= 6; - - try - { - packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer); - } - catch (MalformedDataException e) - { - m_log.DebugFormat("[CLIENT]: Dropped Malformed Packet due to MalformedDataException: {0}", e.StackTrace); - } - catch (IndexOutOfRangeException e) - { - m_log.DebugFormat("[CLIENT]: Dropped Malformed Packet due to IndexOutOfRangeException: {0}", e.StackTrace); - } - catch (Exception e) - { - m_log.Debug("[CLIENT]: " + e); - } - } - - - if (proxyPortOffset != 0) - { - // If we've received a use circuit packet, then we need to decode an endpoint proxy, if one exists, - // before allowing the RecvBuffer to be overwritten by the next packet. - if (packet != null && packet.Type == PacketType.UseCircuitCode) - { - epProxy = epSender; - } - - // Now decode the message from the proxy server - epSender = ProxyCodec.DecodeProxyMessage(RecvBuffer, ref numBytes); - } + m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + client.Name); + udpClient.Shutdown(); + clients.Remove(client.AgentId, udpClient.RemoteEndPoint); } - catch (Exception ex) + else { - m_log.ErrorFormat("[CLIENT]: Exception thrown during EndReceive(): {0}", ex); + m_log.Warn("[LLUDPSERVER]: Failed to remove LLUDPClient for " + client.Name); } + } - BeginRobustReceive(); + public void RemoveClient(LLUDPClient udpClient) + { + IClientAPI client; + + if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client)) + RemoveClient(client); + else + m_log.Warn("[LLUDPSERVER]: Failed to lookup IClientAPI for LLUDPClient " + udpClient.AgentID); + } - if (packet != null) + public void SetClientPaused(UUID agentID, bool paused) + { + LLUDPClient client; + if (clients.TryGetValue(agentID, out client)) { - if (packet.Type == PacketType.UseCircuitCode) - AddNewClient((UseCircuitCodePacket)packet, epSender, epProxy); - else - ProcessInPacket(packet, epSender); + client.IsPaused = paused; + } + else + { + m_log.Warn("[LLUDPSERVER]: Attempted to pause/unpause unknown agent " + agentID); } } - - /// - /// Process a successfully received packet. - /// - /// - /// - protected virtual void ProcessInPacket(Packet packet, EndPoint epSender) + + public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) { - try + if (allowSplitting && packet.HasVariableBlocks) { - // do we already have a circuit for this endpoint - uint circuit; - bool ret; - - lock (clientCircuits) - { - ret = clientCircuits.TryGetValue(epSender, out circuit); - } + byte[][] datas = packet.ToBytesMultiple(); + int packetCount = datas.Length; - if (ret) - { - //if so then send packet to the packetserver - //m_log.DebugFormat( - // "[UDPSERVER]: For circuit {0} {1} got packet {2}", circuit, epSender, packet.Type); + if (packetCount > 1) + m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); - m_packetServer.InPacket(circuit, packet); + for (int i = 0; i < packetCount; i++) + { + byte[] data = datas[i]; + clients.ForEach( + delegate(LLUDPClient client) + { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); } } - catch (Exception e) + else { - m_log.Error("[CLIENT]: Exception in processing packet - ignoring: ", e); + byte[] data = packet.ToBytes(); + clients.ForEach( + delegate(LLUDPClient client) + { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); } } - - /// - /// Begin an asynchronous receive of the next bit of raw data - /// - protected virtual void BeginReceive() + + public void SendPacket(UUID agentID, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { - m_socket.BeginReceiveFrom( - RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref reusedEpSender, ReceivedData, null); + LLUDPClient client; + if (clients.TryGetValue(agentID, out client)) + SendPacket(client, packet, category, allowSplitting); + else + m_log.Warn("[LLUDPSERVER]: Attempted to send a packet to unknown agentID " + agentID); } - /// - /// Begin a robust asynchronous receive of the next bit of raw data. Robust means that SocketExceptions are - /// automatically dealt with until the next set of valid UDP data is received. - /// - private void BeginRobustReceive() + public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { - bool done = false; - - while (!done) + if (allowSplitting && packet.HasVariableBlocks) { - try + byte[][] datas = packet.ToBytesMultiple(); + int packetCount = datas.Length; + + if (packetCount > 1) + m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); + + for (int i = 0; i < packetCount; i++) { - BeginReceive(); - done = true; + byte[] data = datas[i]; + SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); } - catch (SocketException e) - { - // ENDLESS LOOP ON PURPOSE! - // Reset connection and get next UDP packet off the buffer - // If the UDP packet is part of the same stream, this will happen several hundreds of times before - // the next set of UDP data is for a valid client. + } + else + { + byte[] data = packet.ToBytes(); + SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); + } + } - try - { - CloseCircuit(e); - } - catch (Exception e2) - { - m_log.ErrorFormat( - "[CLIENT]: Exception thrown when trying to close the circuit for {0} - {1}", reusedEpSender, - e2); - } - } - catch (ObjectDisposedException) - { - m_log.Info( - "[UDPSERVER]: UDP Object disposed. No need to worry about this if you're restarting the simulator."); + public void SendPacketData(LLUDPClient client, byte[] data, int dataLength, PacketType type, bool doZerocode, ThrottleOutPacketType category) + { + // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. + // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting + // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here + // to accomodate for both common scenarios and provide ample room for ACK appending in both + int bufferSize = (dataLength > 180) ? Packet.MTU : 200; + + UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize); - done = true; + // Zerocode if needed + if (doZerocode) + { + try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); } + catch (IndexOutOfRangeException) + { + // The packet grew larger than the bufferSize while zerocoding. + // Remove the MSG_ZEROCODED flag and send the unencoded data + // instead + m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding. Removing MSG_ZEROCODED flag"); + data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); + Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); } - catch (Exception ex) + } + else + { + Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); + } + buffer.DataLength = dataLength; + + #region Queue or Send + + // Look up the UDPClient this is going to + OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category); + + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) + SendPacketFinal(outgoingPacket); + + #endregion Queue or Send + } + + public void SendAcks(LLUDPClient client) + { + uint ack; + + if (client.PendingAcks.Dequeue(out ack)) + { + List blocks = new List(); + PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); + block.ID = ack; + blocks.Add(block); + + while (client.PendingAcks.Dequeue(out ack)) { - m_log.ErrorFormat("[CLIENT]: Exception thrown during BeginReceive(): {0}", ex); + block = new PacketAckPacket.PacketsBlock(); + block.ID = ack; + blocks.Add(block); } + + PacketAckPacket packet = new PacketAckPacket(); + packet.Header.Reliable = false; + packet.Packets = blocks.ToArray(); + + SendPacket(client, packet, ThrottleOutPacketType.Unknown, true); } } - /// - /// Close a client circuit. This is done in response to an exception on receive, and should not be called - /// normally. - /// - /// The exception that caused the close. Can be null if there was no exception - private void CloseCircuit(Exception e) + public void ResendUnacked(LLUDPClient client) { - uint circuit; - lock (clientCircuits) + if (client.NeedAcks.Count > 0) { - if (clientCircuits.TryGetValue(reusedEpSender, out circuit)) + List expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO); + + if (expiredPackets != null) { - m_packetServer.CloseCircuit(circuit); - - if (e != null) - m_log.ErrorFormat( - "[CLIENT]: Closed circuit {0} {1} due to exception {2}", circuit, reusedEpSender, e); + // Resend packets + for (int i = 0; i < expiredPackets.Count; i++) + { + OutgoingPacket outgoingPacket = expiredPackets[i]; + + // FIXME: Make this an .ini setting + if (outgoingPacket.ResendCount < 3) + { + //Logger.Debug(String.Format("Resending packet #{0} (attempt {1}), {2}ms have passed", + // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount)); + + // Set the resent flag + outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); + outgoingPacket.Category = ThrottleOutPacketType.Resend; + + // The TickCount will be set to the current time when the packet + // is actually sent out again + outgoingPacket.TickCount = 0; + + Interlocked.Increment(ref outgoingPacket.ResendCount); + //Interlocked.Increment(ref Stats.ResentPackets); + + // Queue or (re)send the packet + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) + SendPacketFinal(outgoingPacket); + } + else + { + m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts", + outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount); + + lock (client.NeedAcks.SyncRoot) + client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber); + + //Interlocked.Increment(ref Stats.DroppedPackets); + + // Disconnect an agent if no packets are received for some time + //FIXME: Make 60 an .ini setting + if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) + { + m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.RemoteEndPoint); + + RemoveClient(client); + return; + } + } + } } } } - - /// - /// Finish the process of asynchronously receiving the next bit of raw data - /// - /// The number of bytes received. Will return 0 if no bytes were recieved - /// - /// The sender of the data - /// - protected virtual bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender) + + public void Flush() + { + } + + protected override void PacketReceived(UDPPacketBuffer buffer) { - bool hasReceivedOkay = false; - numBytes = 0; - + // Debugging/Profiling + //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; } + //catch (Exception) { } + + LLUDPClient client = null; + Packet packet = null; + int packetEnd = buffer.DataLength - 1; + IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; + + #region Decoding + try { - numBytes = m_socket.EndReceiveFrom(result, ref epSender); - hasReceivedOkay = true; + packet = Packet.BuildPacket(buffer.Data, ref packetEnd, + // Only allocate a buffer for zerodecoding if the packet is zerocoded + ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } - catch (SocketException e) + catch (MalformedDataException) { - // TODO : Actually only handle those states that we have control over, re-throw everything else, - // TODO: implement cases as we encounter them. - //m_log.Error("[CLIENT]: Connection Error! - " + e.ToString()); - switch (e.SocketErrorCode) - { - case SocketError.AlreadyInProgress: - return hasReceivedOkay; + m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet:\n{0}", + Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); + } + + // Fail-safe check + if (packet == null) + { + m_log.Warn("[LLUDPSERVER]: Couldn't build a message from the incoming data"); + return; + } - case SocketError.NetworkReset: - case SocketError.ConnectionReset: - case SocketError.OperationAborted: - break; + //Stats.RecvBytes += (ulong)buffer.DataLength; + //++Stats.RecvPackets; - default: - throw; + #endregion Decoding + + #region UseCircuitCode Handling + + if (packet.Type == PacketType.UseCircuitCode) + { + UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet; + IClientAPI newuser; + uint circuitCode = useCircuitCode.CircuitCode.Code; + + // Check if the client is already established + if (!m_scene.ClientManager.TryGetClient(circuitCode, out newuser)) + { + AddNewClient(useCircuitCode, (IPEndPoint)buffer.RemoteEndPoint); } } - catch (ObjectDisposedException e) + + // Determine which agent this packet came from + if (!clients.TryGetValue(address, out client)) { - m_log.DebugFormat("[CLIENT]: ObjectDisposedException: Object {0} disposed.", e.ObjectName); - // Uhh, what object, and why? this needs better handling. + m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address); + return; } - - return hasReceivedOkay; - } - /// - /// Add a new client circuit. - /// - /// - /// - /// - protected virtual void AddNewClient(UseCircuitCodePacket useCircuit, EndPoint epSender, EndPoint epProxy) - { - //Slave regions don't accept new clients - if (m_localScene.RegionStatus != RegionStatus.SlaveScene) + #endregion UseCircuitCode Handling + + //if (packet.Header.Resent) + // Interlocked.Increment(ref Stats.ReceivedResends); + + #region ACK Receiving + + int now = Environment.TickCount; + client.TickLastPacketReceived = now; + + // Handle appended ACKs + if (packet.Header.AppendedAcks && packet.Header.AckList != null) { - AuthenticateResponse sessionInfo; - bool isNewCircuit = false; - - if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) + lock (client.NeedAcks.SyncRoot) { - m_log.WarnFormat( - "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", - useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, epSender); - - return; + for (int i = 0; i < packet.Header.AckList.Length; i++) + AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); } - - lock (clientCircuits) + } + + // Handle PacketAck packets + if (packet.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)packet; + + lock (client.NeedAcks.SyncRoot) { - if (!clientCircuits.ContainsKey(epSender)) - { - clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); - isNewCircuit = true; - } + for (int i = 0; i < ackPacket.Packets.Length; i++) + AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); } + } - if (isNewCircuit) - { - // This doesn't need locking as it's synchronized data - clientCircuits_reverse[useCircuit.CircuitCode.Code] = epSender; + #endregion ACK Receiving - lock (proxyCircuits) - { - proxyCircuits[useCircuit.CircuitCode.Code] = epProxy; - } - - m_packetServer.AddNewClient(epSender, useCircuit, sessionInfo, epProxy); - - //m_log.DebugFormat( - // "[CONNECTION SUCCESS]: Incoming client {0} (circuit code {1}) received and authenticated for {2}", - // useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, m_localScene.RegionInfo.RegionName); - } + #region ACK Sending + + if (packet.Header.Reliable) + client.PendingAcks.Enqueue((uint)packet.Header.Sequence); + + // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, + // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove + // 2*MTU bytes from the value and send ACKs, and finally add the local value back to + // client.BytesSinceLastACK. Lockless thread safety + int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); + bytesSinceLastACK += buffer.DataLength; + if (bytesSinceLastACK > Packet.MTU * 2) + { + bytesSinceLastACK -= Packet.MTU * 2; + SendAcks(client); + } + Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); + + #endregion ACK Sending + + #region Incoming Packet Accounting + + // Check the archive of received reliable packet IDs to see whether we already received this packet + if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence)) + { + if (packet.Header.Resent) + m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); + else + m_log.Warn("[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type); + + // Avoid firing a callback twice for the same packet + return; } - - // Ack the UseCircuitCode packet - PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); - // TODO: don't create new blocks if recycling an old packet - ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; - ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); - ack_it.Packets[0].ID = useCircuit.Header.Sequence; - // ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) is just a failsafe to ensure that we don't overflow. - ack_it.Header.Sequence = ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) + 1; - ack_it.Header.Reliable = false; - byte[] ackmsg = ack_it.ToBytes(); + #endregion Incoming Packet Accounting - // Need some extra space in case we need to add proxy - // information to the message later - byte[] msg = new byte[4096]; - Buffer.BlockCopy(ackmsg, 0, msg, 0, ackmsg.Length); + // Don't bother clogging up the queue with PacketAck packets that are already handled here + if (packet.Type != PacketType.PacketAck) + { + // Inbox insertion + IncomingPacket incomingPacket; + incomingPacket.Client = client; + incomingPacket.Packet = packet; - SendPacketTo(msg, ackmsg.Length, SocketFlags.None, useCircuit.CircuitCode.Code); + packetInbox.Enqueue(incomingPacket); + } + } - PacketPool.Instance.ReturnPacket(useCircuit); + protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) + { } - public void ServerListener() + private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) { - uint newPort = listenPort; - m_log.Info("[UDPSERVER]: Opening UDP socket on " + listenIP + " " + newPort + "."); + UUID agentID = useCircuitCode.CircuitCode.ID; + UUID sessionID = useCircuitCode.CircuitCode.SessionID; + uint circuitCode = useCircuitCode.CircuitCode.Code; - ServerIncoming = new IPEndPoint(listenIP, (int)newPort); - m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - if (0 != m_clientSocketReceiveBuffer) - m_socket.ReceiveBufferSize = m_clientSocketReceiveBuffer; - m_socket.Bind(ServerIncoming); - // Add flags to the UDP socket to prevent "Socket forcibly closed by host" - // uint IOC_IN = 0x80000000; - // uint IOC_VENDOR = 0x18000000; - // uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; - // TODO: this apparently works in .NET but not in Mono, need to sort out the right flags here. - // m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); + sessionInfo = m_circuitManager.AuthenticateSession(sessionID, agentID, circuitCode); + return sessionInfo.Authorised; + } - listenPort = newPort; + private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) + { + //Slave regions don't accept new clients + if (m_scene.RegionStatus != RegionStatus.SlaveScene) + { + AuthenticateResponse sessionInfo; + bool isNewCircuit = !clients.ContainsKey(remoteEndPoint); - m_log.Info("[UDPSERVER]: UDP socket bound, getting ready to listen"); + if (!IsClientAuthorized(useCircuitCode, out sessionInfo)) + { + m_log.WarnFormat( + "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", + useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint); + return; + } - ReceivedData = OnReceivedData; - BeginReceive(); + if (isNewCircuit) + { + UUID agentID = useCircuitCode.CircuitCode.ID; + UUID sessionID = useCircuitCode.CircuitCode.SessionID; + uint circuitCode = useCircuitCode.CircuitCode.Code; - m_log.Info("[UDPSERVER]: Listening on port " + newPort); + AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo); + } + } } - public virtual void RegisterPacketServer(LLPacketServer server) + private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) { - m_packetServer = server; + // Create the LLUDPClient + LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); + clients.Add(agentID, client.RemoteEndPoint, client); + + // Create the IClientAPI + IClientAPI clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); + clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; + clientApi.OnLogout += LogoutHandler; + clientApi.OnConnectionClosed += RemoveClient; + + // Give LLUDPClient a reference to IClientAPI + client.ClientAPI = clientApi; + + // Start the IClientAPI + m_scene.ClientManager.Add(circuitCode, clientApi); + clientApi.Start(); } - public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) - //EndPoint packetSender) + private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) { - // find the endpoint for this circuit - EndPoint sendto; - try - { - sendto = (EndPoint)clientCircuits_reverse[circuitcode]; - } - catch + OutgoingPacket ackedPacket; + if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend) { - // Exceptions here mean there is no circuit - m_log.Warn("[CLIENT]: Circuit not found, not sending packet"); - return; + // Calculate the round-trip time for this packet and its ACK + int rtt = currentTime - ackedPacket.TickCount; + if (rtt > 0) + client.UpdateRoundTrip(rtt); } + } + + private void IncomingPacketHandler() + { + IncomingPacket incomingPacket = new IncomingPacket(); + Packet packet = null; + LLUDPClient client = null; - if (sendto != null) + while (base.IsRunning) { - //we found the endpoint so send the packet to it - if (proxyPortOffset != 0) - { - //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString()); - ProxyCodec.EncodeProxyMessage(buffer, ref size, sendto); - m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]); - } - else + // Reset packet to null for the check below + packet = null; + + if (packetInbox.Dequeue(100, ref incomingPacket)) { - //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString()); - try - { - m_socket.SendTo(buffer, size, flags, sendto); - } - catch (SocketException SockE) - { - m_log.ErrorFormat("[UDPSERVER]: Caught Socket Error in the send buffer!. {0}",SockE.ToString()); - } + packet = incomingPacket.Packet; + client = incomingPacket.Client; + + if (packet != null && client != null) + client.ClientAPI.ProcessInPacket(packet); } } + + if (packetInbox.Count > 0) + m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); + packetInbox.Clear(); } - public virtual void RemoveClientCircuit(uint circuitcode) + private void OutgoingPacketHandler() { - EndPoint sendto; - if (clientCircuits_reverse.Contains(circuitcode)) + int now = Environment.TickCount; + int elapsedMS = 0; + int elapsed100MS = 0; + + while (base.IsRunning) { - sendto = (EndPoint)clientCircuits_reverse[circuitcode]; + bool resendUnacked = false; + bool sendAcks = false; + bool packetSent = false; - clientCircuits_reverse.Remove(circuitcode); + elapsedMS += Environment.TickCount - now; - lock (clientCircuits) + // Check for packets that need to be resent every 100ms + if (elapsedMS >= 100) { - if (sendto != null) - { - clientCircuits.Remove(sendto); - } - else - { - m_log.DebugFormat( - "[CLIENT]: endpoint for circuit code {0} in RemoveClientCircuit() was unexpectedly null!", circuitcode); - } + resendUnacked = true; + elapsedMS -= 100; + ++elapsed100MS; } - lock (proxyCircuits) + // Check for ACKs that need to be sent out every 500ms + if (elapsed100MS >= 5) { - proxyCircuits.Remove(circuitcode); + sendAcks = true; + elapsed100MS = 0; } + + clients.ForEach( + delegate(LLUDPClient client) + { + if (client.DequeueOutgoing()) + packetSent = true; + if (resendUnacked) + ResendUnacked(client); + if (sendAcks) + SendAcks(client); + } + ); + + if (!packetSent) + Thread.Sleep(20); } } - public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP) + private void LogoutHandler(IClientAPI client) { - //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient"); + client.SendLogoutPacket(); + RemoveClient(client); + } + + internal void SendPacketFinal(OutgoingPacket outgoingPacket) + { + UDPPacketBuffer buffer = outgoingPacket.Buffer; + byte flags = buffer.Data[0]; + bool isResend = (flags & Helpers.MSG_RESENT) != 0; + bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; + LLUDPClient client = outgoingPacket.Client; + + // Keep track of when this packet was sent out (right now) + outgoingPacket.TickCount = Environment.TickCount; - UseCircuitCodePacket useCircuit = new UseCircuitCodePacket(); - useCircuit.CircuitCode.Code = circuit.circuitcode; - useCircuit.CircuitCode.ID = circuit.AgentID; - useCircuit.CircuitCode.SessionID = circuit.SessionID; - - AuthenticateResponse sessionInfo; - - if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) + #region ACK Appending + + int dataLength = buffer.DataLength; + + // Keep appending ACKs until there is no room left in the packet or there are + // no more ACKs to append + uint ackCount = 0; + uint ack; + while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) { - m_log.WarnFormat( - "[CLIENT]: Restore request denied to avatar {0} connecting with unauthorized circuit code {1}", - useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code); - - return; + Utils.UIntToBytesBig(ack, buffer.Data, dataLength); + dataLength += 4; + ++ackCount; } - lock (clientCircuits) + if (ackCount > 0) { - if (!clientCircuits.ContainsKey(userEP)) - clientCircuits.Add(userEP, useCircuit.CircuitCode.Code); - else - m_log.Error("[CLIENT]: clientCircuits already contains entry for user " + useCircuit.CircuitCode.Code + ". NOT adding."); + // Set the last byte of the packet equal to the number of appended ACKs + buffer.Data[dataLength++] = (byte)ackCount; + // Set the appended ACKs flag on this packet + buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); } - // This data structure is synchronized, so we don't need the lock - if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) - clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP); - else - m_log.Error("[CLIENT]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code + ". NOT adding."); + buffer.DataLength = dataLength; - lock (proxyCircuits) + #endregion ACK Appending + + if (!isResend) { - if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) - { - proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); - } - else + // Not a resend, assign a new sequence number + uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); + Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); + outgoingPacket.SequenceNumber = sequenceNumber; + + if (isReliable) { - // re-set proxy endpoint - proxyCircuits.Remove(useCircuit.CircuitCode.Code); - proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); + // Add this packet to the list of ACK responses we are waiting on from the server + client.NeedAcks.Add(outgoingPacket); } } - m_packetServer.AddNewClient(userEP, useCircuit, sessionInfo, proxyEP); + // Put the UDP payload on the wire + AsyncBeginSend(buffer); } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs index c45d11f..066b19d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs @@ -25,8 +25,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; +using System.Collections.Generic; +using System.Net; using OpenMetaverse; +using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; + namespace OpenSim.Region.ClientStack.LindenUDP { public class LLUtil diff --git a/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs index cde155b..7d0757f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests TestClient testClient = new TestClient(agent, scene); - ILLPacketHandler packetHandler + LLPacketHandler packetHandler = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings()); packetHandler.InPacket(new AgentAnimationPacket()); diff --git a/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs index 1fba847..e995d65 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs @@ -37,7 +37,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// protected Dictionary m_packetsReceived = new Dictionary(); - public TestLLPacketServer(ILLClientStackNetworkHandler networkHandler, ClientStackUserSettings userSettings) + public TestLLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings) : base(networkHandler, userSettings) {} -- cgit v1.1 From e7c877407f2a72a9519eb53debca5aeef20cded9 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 02:38:00 -0700 Subject: * Continued work on the new LLUDP implementation. Appears to be functioning, although not everything is reimplemented yet * Replaced logic in ThreadTracker with a call to System.Diagnostics that does the same thing * Added Util.StringToBytes256() and Util.StringToBytes1024() to clamp output at byte[256] and byte[1024], respectively * Fixed formatting for a MySQLAssetData error logging line --- .../Region/ClientStack/LindenUDP/IncomingPacket.cs | 42 + .../LindenUDP/IncomingPacketHistoryCollection.cs | 73 ++ OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | 33 +- OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs | 71 -- .../Region/ClientStack/LindenUDP/LLClientView.cs | 284 +++---- .../ClientStack/LindenUDP/LLPacketHandler.cs | 875 --------------------- .../Region/ClientStack/LindenUDP/LLPacketQueue.cs | 742 ----------------- .../Region/ClientStack/LindenUDP/LLPacketServer.cs | 206 ----- OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs | 49 -- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 370 +++++++++ .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 185 +++++ .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 138 +++- OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs | 56 -- .../Region/ClientStack/LindenUDP/OutgoingPacket.cs | 56 ++ .../Region/ClientStack/LindenUDP/ThrottleRates.cs | 76 ++ .../LindenUDP/UnackedPacketCollection.cs | 114 +++ 16 files changed, 1141 insertions(+), 2229 deletions(-) create mode 100644 OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs create mode 100644 OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs new file mode 100644 index 0000000..dc0d62a --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using OpenMetaverse; +using OpenMetaverse.Packets; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public struct IncomingPacket + { + /// Client this packet came from + public LLUDPClient Client; + /// Packet data that has been received + public Packet Packet; + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs new file mode 100644 index 0000000..1f73a1d --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + /// + /// A circular buffer and hashset for tracking incoming packet sequence + /// numbers + /// + public sealed class IncomingPacketHistoryCollection + { + private readonly uint[] m_items; + private HashSet m_hashSet; + private int m_first; + private int m_next; + private int m_capacity; + + public IncomingPacketHistoryCollection(int capacity) + { + this.m_capacity = capacity; + m_items = new uint[capacity]; + m_hashSet = new HashSet(); + } + + public bool TryEnqueue(uint ack) + { + lock (m_hashSet) + { + if (m_hashSet.Add(ack)) + { + m_items[m_next] = ack; + m_next = (m_next + 1) % m_capacity; + if (m_next == m_first) + { + m_hashSet.Remove(m_items[m_first]); + m_first = (m_first + 1) % m_capacity; + } + + return true; + } + } + + return false; + } + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 000f455..2f1face 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs @@ -76,27 +76,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_currentPacket <= m_stopPacket) { - bool SendMore = true; + int count = 0; + bool sendMore = true; + if (!m_sentInfo || (m_currentPacket == 0)) { - if (SendFirstPacket(client)) - { - SendMore = false; - } + sendMore = !SendFirstPacket(client); + m_sentInfo = true; - m_currentPacket++; + ++m_currentPacket; + ++count; } if (m_currentPacket < 2) { m_currentPacket = 2; } - - int count = 0; - while (SendMore && count < maxpack && m_currentPacket <= m_stopPacket) + + while (sendMore && count < maxpack && m_currentPacket <= m_stopPacket) { - count++; - SendMore = SendPacket(client); - m_currentPacket++; + sendMore = SendPacket(client); + ++m_currentPacket; + ++count; } if (m_currentPacket > m_stopPacket) @@ -196,15 +196,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentPacket = StartPacket; } - - if (m_imageManager != null && m_imageManager.Client != null) - { - if (m_imageManager.Client.IsThrottleEmpty(ThrottleOutPacketType.Texture)) - { - //m_log.Debug("No textures queued, sending one packet to kickstart it"); - SendPacket(m_imageManager.Client); - } - } } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs deleted file mode 100644 index a80c1f0..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenMetaverse.Packets; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - /// - /// When packetqueue dequeues this packet in the outgoing stream, it thread aborts - /// Ensures that the thread abort happens from within the client thread - /// regardless of where the close method is called - /// - class KillPacket : Packet - { - public override int Length - { - get { return 0; } - } - - public override void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd) - { - } - - public override void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer) - { - } - - public override byte[] ToBytes() - { - return new byte[0]; - } - - public override byte[][] ToBytesMultiple() - { - return new byte[][] { new byte[0] }; - } - - public KillPacket() - { - Type = PacketType.UseCircuitCode; - Header = new Header(); - Header.Frequency = OpenMetaverse.PacketFrequency.Low; - Header.ID = 65531; - Header.Reliable = true; - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 31cd53f..767020f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -70,28 +70,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP private readonly LLUDPServer m_udpServer; private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; - private readonly UUID m_secureSessionId = UUID.Zero; + private readonly UUID m_secureSessionId; private readonly UUID m_agentId; private readonly uint m_circuitCode; - private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL + private readonly byte[] m_channelVersion = Utils.EmptyBytes; private readonly Dictionary m_defaultAnimations = new Dictionary(); private readonly IGroupsModule m_GroupsModule; - private int m_debugPacketLevel; private int m_cachedTextureSerial; - private Timer m_clientPingTimer; private Timer m_avatarTerseUpdateTimer; private List m_avatarTerseUpdates = new List(); private Timer m_primTerseUpdateTimer; private List m_primTerseUpdates = new List(); private Timer m_primFullUpdateTimer; private List m_primFullUpdates = new List(); - private bool m_clientBlocked; - private int m_probesWithNoIngressPackets; private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - private int m_inPacketsChecked; private AgentUpdateArgs lastarg; private bool m_IsActive = true; @@ -170,58 +165,72 @@ namespace OpenSim.Region.ClientStack.LindenUDP RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); - m_GroupsModule = scene.RequestModuleInterface(); - - m_moneyBalance = 1000; - - m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); - + InitDefaultAnimations(); m_scene = scene; - //m_assetCache = assetCache; - m_assetService = m_scene.RequestModuleInterface(); - - m_udpServer = udpServer; - m_udpClient = udpClient; - + m_GroupsModule = scene.RequestModuleInterface(); + m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); + m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); m_agentId = agentId; m_sessionId = sessionId; + m_secureSessionId = sessionInfo.LoginInfo.SecureSession; m_circuitCode = circuitCode; - m_userEndPoint = remoteEP; - m_firstName = sessionInfo.LoginInfo.First; m_lastName = sessionInfo.LoginInfo.Last; m_startpos = sessionInfo.LoginInfo.StartPos; + m_moneyBalance = 1000; - if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) - { - m_secureSessionId = sessionInfo.LoginInfo.SecureSession; - } - - // While working on this, the BlockingQueue had me fooled for a bit. - // The Blocking queue causes the thread to stop until there's something - // in it to process. It's an on-purpose threadlock though because - // without it, the clientloop will suck up all sim resources. - - //m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings); - //m_PacketHandler.SynchronizeClient = SynchronizeClient; - //m_PacketHandler.OnPacketStats += PopulateStats; - //m_PacketHandler.OnQueueEmpty += HandleQueueEmpty; + m_udpServer = udpServer; + m_udpClient = udpClient; + m_udpClient.OnQueueEmpty += HandleQueueEmpty; + // FIXME: Implement this + //m_udpClient.OnPacketStats += PopulateStats; RegisterLocalPacketHandlers(); - m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); } - public void SetDebugPacketLevel(int newDebugPacketLevel) + public void SetDebugPacketLevel(int newDebug) { - m_debugPacketLevel = newDebugPacketLevel; } #region Client Methods + /// + /// Close down the client view. This *must* be the last method called, since the last # + /// statement of CloseCleanup() aborts the thread. + /// + /// + public void Close(bool shutdownCircuit) + { + m_log.DebugFormat( + "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", + shutdownCircuit, Name, m_scene.RegionInfo.RegionName); + + if (m_imageManager != null) + m_imageManager.Close(); + + if (m_udpServer != null) + m_udpServer.Flush(); + + // raise an event on the packet server to Shutdown the circuit + // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup + // here otherwise we'll end up calling it twice. + // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks + // horribly tangly. Hopefully it should be possible to greatly simplify it. + if (shutdownCircuit) + { + if (OnConnectionClosed != null) + OnConnectionClosed(this); + } + else + { + CloseCleanup(shutdownCircuit); + } + } + private void CloseCleanup(bool shutdownCircuit) { m_scene.RemoveClient(AgentId); @@ -236,9 +245,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP Thread.Sleep(2000); // Shut down timers. Thread Context of this method is murky. Lock all timers - if (m_clientPingTimer.Enabled) - lock (m_clientPingTimer) - m_clientPingTimer.Stop(); if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -271,43 +277,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP // of the client thread regardless of where Close() is called. KillEndDone(); } - - Terminate(); - } - /// - /// Close down the client view. This *must* be the last method called, since the last # - /// statement of CloseCleanup() aborts the thread. - /// - /// - public void Close(bool shutdownCircuit) - { - m_clientPingTimer.Enabled = false; + IsActive = false; - m_log.DebugFormat( - "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", - shutdownCircuit, Name, m_scene.RegionInfo.RegionName); + m_avatarTerseUpdateTimer.Close(); + m_primTerseUpdateTimer.Close(); + m_primFullUpdateTimer.Close(); - if (m_imageManager != null) - m_imageManager.Close(); + //m_udpServer.OnPacketStats -= PopulateStats; + m_udpClient.Shutdown(); - if (m_udpServer != null) - m_udpServer.Flush(); + // wait for thread stoped + // m_clientThread.Join(); - // raise an event on the packet server to Shutdown the circuit - // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup - // here otherwise we'll end up calling it twice. - // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks - // horribly tangly. Hopefully it should be possible to greatly simplify it. - if (shutdownCircuit) - { - if (OnConnectionClosed != null) - OnConnectionClosed(this); - } - else - { - CloseCleanup(shutdownCircuit); - } + // delete circuit code + //m_networkServer.CloseClient(this); } public void Kick(string message) @@ -329,10 +313,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Stop() { // Shut down timers. Thread Context is Murky, lock all timers! - if (m_clientPingTimer.Enabled) - lock (m_clientPingTimer) - m_clientPingTimer.Stop(); - if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -346,25 +326,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdateTimer.Stop(); } - private void Terminate() - { - IsActive = false; - - m_clientPingTimer.Close(); - m_avatarTerseUpdateTimer.Close(); - m_primTerseUpdateTimer.Close(); - m_primFullUpdateTimer.Close(); - - //m_udpServer.OnPacketStats -= PopulateStats; - m_udpClient.Shutdown(); - - // wait for thread stoped - // m_clientThread.Join(); - - // delete circuit code - //m_networkServer.CloseClient(this); - } - #endregion Client Methods #region Packet Handling @@ -452,7 +413,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return result; } - protected void DebugPacket(string direction, Packet packet) + /*protected void DebugPacket(string direction, Packet packet) { string info; @@ -478,7 +439,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); - } + }*/ #endregion Packet Handling @@ -490,8 +451,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected virtual void InitNewClient() { - //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); m_avatarTerseUpdateTimer.AutoReset = false; @@ -511,11 +470,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_clientThread = new Thread(RunUserSession); - m_clientThread.Name = "ClientThread"; - m_clientThread.IsBackground = true; - m_clientThread.Start(); - ThreadTracker.Add(m_clientThread); + // This sets up all the timers + InitNewClient(); } /// @@ -523,14 +479,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected void RunUserSession() { - //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) - //otherwise it will override this and use the system default - Culture.SetCurrentCulture(); - try { - // This sets up all the timers - InitNewClient(); + } catch (Exception e) { @@ -1373,8 +1324,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendStartPingCheck(byte seq) { StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); - pc.PingID.PingID = seq; pc.Header.Reliable = false; + + OutgoingPacket oldestPacket = m_udpClient.NeedAcks.GetOldest(); + + pc.PingID.PingID = seq; + pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; + OutPacket(pc, ThrottleOutPacketType.Unknown); } @@ -1450,12 +1406,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP descend.ItemData[i].AssetID = item.AssetID; descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; descend.ItemData[i].BaseMask = item.BasePermissions; - descend.ItemData[i].Description = LLUtil.StringToPacketBytes(item.Description); + descend.ItemData[i].Description = Util.StringToBytes256(item.Description); descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; descend.ItemData[i].OwnerMask = item.CurrentPermissions; descend.ItemData[i].FolderID = item.Folder; descend.ItemData[i].InvType = (sbyte)item.InvType; - descend.ItemData[i].Name = LLUtil.StringToPacketBytes(item.Name); + descend.ItemData[i].Name = Util.StringToBytes256(item.Name); descend.ItemData[i].NextOwnerMask = item.NextPermissions; descend.ItemData[i].OwnerID = item.Owner; descend.ItemData[i].Type = (sbyte)item.AssetType; @@ -1536,7 +1492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); descend.FolderData[i].FolderID = folder.ID; - descend.FolderData[i].Name = LLUtil.StringToPacketBytes(folder.Name); + descend.FolderData[i].Name = Util.StringToBytes256(folder.Name); descend.FolderData[i].ParentID = folder.ParentID; descend.FolderData[i].Type = (sbyte)folder.Type; @@ -1651,11 +1607,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; inventoryReply.InventoryData[0].CreationDate = item.CreationDate; - inventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(item.Description); + inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description); inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; inventoryReply.InventoryData[0].FolderID = item.Folder; inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; - inventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(item.Name); + inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name); inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; inventoryReply.InventoryData[0].OwnerID = item.Owner; inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; @@ -1780,7 +1736,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; folderBlock.Type = -1; - folderBlock.Name = LLUtil.StringToPacketBytes(folder.Name); + folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; } @@ -1798,11 +1754,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP itemBlock.AssetID = item.AssetID; itemBlock.CreatorID = item.CreatorIdAsUuid; itemBlock.BaseMask = item.BasePermissions; - itemBlock.Description = LLUtil.StringToPacketBytes(item.Description); + itemBlock.Description = Util.StringToBytes256(item.Description); itemBlock.EveryoneMask = item.EveryOnePermissions; itemBlock.FolderID = item.Folder; itemBlock.InvType = (sbyte)item.InvType; - itemBlock.Name = LLUtil.StringToPacketBytes(item.Name); + itemBlock.Name = Util.StringToBytes256(item.Name); itemBlock.NextOwnerMask = item.NextPermissions; itemBlock.OwnerID = item.Owner; itemBlock.OwnerMask = item.CurrentPermissions; @@ -1862,11 +1818,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid; bulkUpdate.ItemData[0].BaseMask = item.BasePermissions; bulkUpdate.ItemData[0].CreationDate = item.CreationDate; - bulkUpdate.ItemData[0].Description = LLUtil.StringToPacketBytes(item.Description); + bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description); bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions; bulkUpdate.ItemData[0].FolderID = item.Folder; bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType; - bulkUpdate.ItemData[0].Name = LLUtil.StringToPacketBytes(item.Name); + bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name); bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions; bulkUpdate.ItemData[0].OwnerID = item.Owner; bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; @@ -1909,11 +1865,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP InventoryReply.InventoryData[0].AssetID = Item.AssetID; InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid; InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions; - InventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(Item.Description); + InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description); InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions; InventoryReply.InventoryData[0].FolderID = Item.Folder; InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType; - InventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(Item.Name); + InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name); InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions; InventoryReply.InventoryData[0].OwnerID = Item.Owner; InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; @@ -2080,7 +2036,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// /// - protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) + public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) { AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); alertPack.AgentData.AgentID = AgentId; @@ -3533,7 +3489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP objectData.FullID = objectID; objectData.OwnerID = ownerID; - objectData.Text = LLUtil.StringToPacketBytes(text); + objectData.Text = Util.StringToBytes256(text); objectData.TextColor[0] = color[0]; objectData.TextColor[1] = color[1]; objectData.TextColor[2] = color[2]; @@ -3911,8 +3867,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP objPropDB.SalePrice = SalePrice; objPropDB.Category = Category; objPropDB.LastOwnerID = LastOwnerID; - objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); - objPropDB.Description = LLUtil.StringToPacketBytes(Description); + objPropDB.Name = Util.StringToBytes256(ObjectName); + objPropDB.Description = Util.StringToBytes256(Description); objPropFamilyPack.ObjectData = objPropDB; objPropFamilyPack.Header.Zerocoded = true; OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); @@ -3946,11 +3902,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP proper.ObjectData[0].OwnerID = UUID.Zero; else proper.ObjectData[0].OwnerID = OwnerUUID; - proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); + proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle); proper.ObjectData[0].TextureID = TextureID; - proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); - proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); - proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); + proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle); + proper.ObjectData[0].Name = Util.StringToBytes256(ItemName); + proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription); proper.ObjectData[0].OwnerMask = OwnerMask; proper.ObjectData[0].NextOwnerMask = NextOwnerMask; proper.ObjectData[0].GroupMask = GroupMask; @@ -4191,11 +4147,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; updatePacket.ParcelData.MediaID = landData.MediaID; - updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); - updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); - updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); + updatePacket.ParcelData.MediaURL = Util.StringToBytes256(landData.MediaURL); + updatePacket.ParcelData.MusicURL = Util.StringToBytes256(landData.MusicURL); + updatePacket.ParcelData.Name = Util.StringToBytes256(landData.Name); updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; - updatePacket.ParcelData.OtherCount = 0; //unemplemented + updatePacket.ParcelData.OtherCount = 0; //TODO: Unimplemented updatePacket.ParcelData.OtherPrims = landData.OtherPrims; updatePacket.ParcelData.OwnerID = landData.OwnerID; updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; @@ -4203,22 +4159,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; updatePacket.ParcelData.PassHours = landData.PassHours; updatePacket.ParcelData.PassPrice = landData.PassPrice; - updatePacket.ParcelData.PublicCount = 0; //unemplemented + updatePacket.ParcelData.PublicCount = 0; //TODO: Unimplemented - updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > - 0); - updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > - 0); - updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) > - 0); - updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) > - 0); + updatePacket.ParcelData.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0; + updatePacket.ParcelData.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0; + updatePacket.ParcelData.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0; + updatePacket.ParcelData.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0; updatePacket.ParcelData.RentPrice = 0; updatePacket.ParcelData.RequestResult = request_result; updatePacket.ParcelData.SalePrice = landData.SalePrice; updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; - updatePacket.ParcelData.SelfCount = 0; //unemplemented + updatePacket.ParcelData.SelfCount = 0; //TODO: Unimplemented updatePacket.ParcelData.SequenceID = sequence_id; if (landData.SimwideArea > 0) { @@ -5265,18 +5217,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpClient.SetThrottles(throttles); } + /// + /// Get the current throttles for this client as a packed byte array + /// + /// Unused + /// public byte[] GetThrottlesPacked(float multiplier) { return m_udpClient.GetThrottlesPacked(); } - public bool IsThrottleEmpty(ThrottleOutPacketType category) - { - return m_udpClient.IsThrottleEmpty(category); - } - /// - /// Unused + /// Cruft? /// public virtual void InPacket(object NewPack) { @@ -6231,14 +6183,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP break; case PacketType.AgentPause: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = true; + m_udpClient.IsPaused = true; break; case PacketType.AgentResume: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = false; - SendStartPingCheck(0); + m_udpClient.IsPaused = false; + SendStartPingCheck(m_udpClient.CurrentPingSequence++); break; @@ -8904,14 +8854,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region unimplemented handlers case PacketType.StartPingCheck: - // Send the client the ping response back - // Pass the same PingID in the matching packet - // Handled In the packet processing - //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); + StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; + CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); + pingComplete.PingID.PingID = pingStart.PingID.PingID; + m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); break; + case PacketType.CompletePingCheck: - // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client - //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); + // TODO: Do stats tracking or something with these? break; case PacketType.ViewerStats: @@ -10209,14 +10159,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP return info; } - public EndPoint GetClientEP() + public void SetClientInfo(ClientInfo info) { - return m_userEndPoint; + m_udpClient.SetClientInfo(info); } - public void SetClientInfo(ClientInfo info) + public EndPoint GetClientEP() { - m_udpClient.SetClientInfo(info); + return m_userEndPoint; } #region Media Parcel Members diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs deleted file mode 100644 index f30df4d..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Net.Sockets; -using System.Threading; -using System.Timers; -using OpenMetaverse; -using OpenMetaverse.Packets; -using log4net; -using OpenSim.Framework; -using Timer=System.Timers.Timer; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); - public delegate void PacketDrop(Packet pack, Object id); - public delegate void QueueEmpty(ThrottleOutPacketType queue); - public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType); - - public class LLPacketHandler - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - //private int m_resentCount; - - // Packet queues - // - LLPacketQueue m_PacketQueue; - - public LLPacketQueue PacketQueue - { - get { return m_PacketQueue; } - } - - // Timer to run stats and acks on - // - private Timer m_AckTimer = new Timer(250); - - // A list of the packets we haven't acked yet - // - private List m_PendingAcks = new List(); - private Dictionary m_PendingAcksMap = new Dictionary(); - - private Dictionary m_NeedAck = - new Dictionary(); - - /// - /// The number of milliseconds that can pass before a packet that needs an ack is resent. - /// - private uint m_ResendTimeout = 4000; - - public uint ResendTimeout - { - get { return m_ResendTimeout; } - set { m_ResendTimeout = value; } - } - - private int m_MaxReliableResends = 3; - - public int MaxReliableResends - { - get { return m_MaxReliableResends; } - set { m_MaxReliableResends = value; } - } - - // Track duplicated packets. This uses a Dictionary. Both insertion - // and lookup are common operations and need to take advantage of - // the hashing. Expiration is less common and can be allowed the - // time for a linear scan. - // - private List m_alreadySeenList = new List(); - private Dictionarym_alreadySeenTracker = new Dictionary(); - private int m_alreadySeenWindow = 30000; - private int m_lastAlreadySeenCheck = Environment.TickCount & Int32.MaxValue; - - // private Dictionary m_DupeTracker = - // new Dictionary(); - // private uint m_DupeTrackerWindow = 30; - // private int m_DupeTrackerLastCheck = Environment.TickCount; - - // Values for the SimStatsReporter - // - private int m_PacketsReceived = 0; - private int m_PacketsReceivedReported = 0; - private int m_PacketsSent = 0; - private int m_PacketsSentReported = 0; - private int m_UnackedBytes = 0; - - private int m_LastResend = 0; - - public int PacketsReceived - { - get { return m_PacketsReceived; } - } - - public int PacketsReceivedReported - { - get { return m_PacketsReceivedReported; } - } - - // The client we are working for - // - private IClientAPI m_Client; - - // Some events - // - public event PacketStats OnPacketStats; - public event PacketDrop OnPacketDrop; - public event QueueEmpty OnQueueEmpty; - - - //private SynchronizeClientHandler m_SynchronizeClient = null; - - public SynchronizeClientHandler SynchronizeClient - { - set { /* m_SynchronizeClient = value; */ } - } - - // Packet sequencing - // - private uint m_Sequence = 0; - private object m_SequenceLock = new object(); - private const int MAX_SEQUENCE = 0xFFFFFF; - - // Packet dropping - // - List m_ImportantPackets = new List(); - private bool m_ReliableIsImportant = false; - - public bool ReliableIsImportant - { - get { return m_ReliableIsImportant; } - set { m_ReliableIsImportant = value; } - } - - private int m_DropSafeTimeout; - - LLPacketServer m_PacketServer; - private byte[] m_ZeroOutBuffer = new byte[4096]; - - //////////////////////////////////////////////////////////////////// - - // Constructors - // - public LLPacketHandler(IClientAPI client, LLPacketServer server, ClientStackUserSettings userSettings) - { - m_Client = client; - m_PacketServer = server; - m_DropSafeTimeout = Environment.TickCount + 15000; - - m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings); - - m_PacketQueue.OnQueueEmpty += TriggerOnQueueEmpty; - - m_AckTimer.Elapsed += AckTimerElapsed; - m_AckTimer.Start(); - } - - public void Dispose() - { - m_AckTimer.Stop(); - m_AckTimer.Close(); - - m_PacketQueue.Enqueue(null); - m_PacketQueue.Close(); - m_Client = null; - } - - // Send one packet. This actually doesn't send anything, it queues - // it. Designed to be fire-and-forget, but there is an optional - // notifier. - // - public void OutPacket( - Packet packet, ThrottleOutPacketType throttlePacketType) - { - OutPacket(packet, throttlePacketType, null); - } - - public void OutPacket( - Packet packet, ThrottleOutPacketType throttlePacketType, - Object id) - { - // Call the load balancer's hook. If this is not active here - // we defer to the sim server this client is actually connected - // to. Packet drop notifies will not be triggered in this - // configuration! - // - - packet.Header.Sequence = 0; - - lock (m_NeedAck) - { - DropResend(id); - - AddAcks(ref packet); - QueuePacket(packet, throttlePacketType, id); - } - } - - private void AddAcks(ref Packet packet) - { - // These packet types have shown to have issues with - // acks being appended to the payload, just don't send - // any with them until libsl is fixed. - // - if (packet is ViewerEffectPacket) - return; - if (packet is SimStatsPacket) - return; - - // Add acks to outgoing packets - // - if (m_PendingAcks.Count > 0) - { - int count = m_PendingAcks.Count; - if (count > 10) - count = 10; - packet.Header.AckList = new uint[count]; - packet.Header.AppendedAcks = true; - - for (int i = 0; i < count; i++) - { - packet.Header.AckList[i] = m_PendingAcks[i]; - m_PendingAcksMap.Remove(m_PendingAcks[i]); - } - m_PendingAcks.RemoveRange(0, count); - } - } - - private void QueuePacket( - Packet packet, ThrottleOutPacketType throttlePacketType, - Object id) - { - LLQueItem item = new LLQueItem(); - item.Packet = packet; - item.Incoming = false; - item.throttleType = throttlePacketType; - item.TickCount = Environment.TickCount; - item.Identifier = id; - item.Resends = 0; - item.Length = packet.Length; - item.Sequence = packet.Header.Sequence; - - m_PacketQueue.Enqueue(item); - m_PacketsSent++; - } - - private void ResendUnacked() - { - int now = Environment.TickCount; - - int intervalMs = 250; - - if (m_LastResend != 0) - intervalMs = now - m_LastResend; - - lock (m_NeedAck) - { - if (m_DropSafeTimeout > now || - intervalMs > 500) // We were frozen! - { - foreach (LLQueItem data in m_NeedAck.Values) - { - if (m_DropSafeTimeout > now) - { - m_NeedAck[data.Packet.Header.Sequence].TickCount = now; - } - else - { - m_NeedAck[data.Packet.Header.Sequence].TickCount += intervalMs; - } - } - } - - m_LastResend = now; - - // Unless we have received at least one ack, don't bother resending - // anything. There may not be a client there, don't clog up the - // pipes. - - - // Nothing to do - // - if (m_NeedAck.Count == 0) - return; - - int resent = 0; - long dueDate = now - m_ResendTimeout; - - List dropped = new List(); - foreach (LLQueItem data in m_NeedAck.Values) - { - Packet packet = data.Packet; - - // Packets this old get resent - // - if (data.TickCount < dueDate && data.Sequence != 0 && !m_PacketQueue.Contains(data.Sequence)) - { - if (resent < 20) // Was 20 (= Max 117kbit/sec resends) - { - m_NeedAck[packet.Header.Sequence].Resends++; - - // The client needs to be told that a packet is being resent, otherwise it appears to believe - // that it should reset its sequence to that packet number. - packet.Header.Resent = true; - - if ((m_NeedAck[packet.Header.Sequence].Resends >= m_MaxReliableResends) && - (!m_ReliableIsImportant)) - { - dropped.Add(data); - continue; - } - - m_NeedAck[packet.Header.Sequence].TickCount = Environment.TickCount; - QueuePacket(packet, ThrottleOutPacketType.Resend, data.Identifier); - resent++; - } - else - { - m_NeedAck[packet.Header.Sequence].TickCount += intervalMs; - } - } - } - - foreach (LLQueItem data in dropped) - { - m_NeedAck.Remove(data.Packet.Header.Sequence); - TriggerOnPacketDrop(data.Packet, data.Identifier); - m_PacketQueue.Cancel(data.Packet.Header.Sequence); - PacketPool.Instance.ReturnPacket(data.Packet); - } - } - } - - // Send the pending packet acks to the client - // Will send blocks of acks for up to 250 packets - // - private void SendAcks() - { - lock (m_NeedAck) - { - if (m_PendingAcks.Count == 0) - return; - - PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); - - // The case of equality is more common than one might think, - // because this function will be called unconditionally when - // the counter reaches 250. So there is a good chance another - // packet with 250 blocks exists. - // - if (acks.Packets == null || - acks.Packets.Length != m_PendingAcks.Count) - acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count]; - - for (int i = 0; i < m_PendingAcks.Count; i++) - { - acks.Packets[i] = new PacketAckPacket.PacketsBlock(); - acks.Packets[i].ID = m_PendingAcks[i]; - - } - m_PendingAcks.Clear(); - m_PendingAcksMap.Clear(); - - acks.Header.Reliable = false; - OutPacket(acks, ThrottleOutPacketType.Unknown); - } - } - - // Queue a packet ack. It will be sent either after 250 acks are - // queued, or when the timer fires. - // - private void AckPacket(Packet packet) - { - lock (m_NeedAck) - { - if (m_PendingAcks.Count < 250) - { - if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence)) - { - m_PendingAcks.Add(packet.Header.Sequence); - m_PendingAcksMap.Add(packet.Header.Sequence, - packet.Header.Sequence); - } - return; - } - } - - SendAcks(); - - lock (m_NeedAck) - { - // If this is still full we have a truly exceptional - // condition (means, can't happen) - // - if (m_PendingAcks.Count < 250) - { - if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence)) - { - m_PendingAcks.Add(packet.Header.Sequence); - m_PendingAcksMap.Add(packet.Header.Sequence, - packet.Header.Sequence); - } - return; - } - } - } - - // When the timer elapses, send the pending acks, trigger resends - // and report all the stats. - // - private void AckTimerElapsed(object sender, ElapsedEventArgs ea) - { - SendAcks(); - ResendUnacked(); - SendPacketStats(); - } - - // Push out pachet counts for the sim status reporter - // - private void SendPacketStats() - { - PacketStats handlerPacketStats = OnPacketStats; - if (handlerPacketStats != null) - { - handlerPacketStats( - m_PacketsReceived - m_PacketsReceivedReported, - m_PacketsSent - m_PacketsSentReported, - m_UnackedBytes); - - m_PacketsReceivedReported = m_PacketsReceived; - m_PacketsSentReported = m_PacketsSent; - } - } - - // We can't keep an unlimited record of dupes. This will prune the - // dictionary by age. - // - // NOTE: this needs to be called from within lock - // (m_alreadySeenTracker) context! - private void ExpireSeenPackets() - { - if (m_alreadySeenList.Count < 1024) - return; - - int ticks = 0; - int tc = Environment.TickCount & Int32.MaxValue; - if (tc >= m_lastAlreadySeenCheck) - ticks = tc - m_lastAlreadySeenCheck; - else - ticks = Int32.MaxValue - m_lastAlreadySeenCheck + tc; - - if (ticks < 2000) return; - m_lastAlreadySeenCheck = tc; - - // we calculate the drop dead tick count here instead of - // in the loop: any packet with a timestamp before - // dropDeadTC can be expired - int dropDeadTC = tc - m_alreadySeenWindow; - int i = 0; - while (i < m_alreadySeenList.Count && m_alreadySeenTracker[m_alreadySeenList[i]] < dropDeadTC) - { - m_alreadySeenTracker.Remove(m_alreadySeenList[i]); - i++; - } - // if we dropped packet from m_alreadySeenTracker we need - // to drop them from m_alreadySeenList as well, let's do - // that in one go: the list is ordered after all. - if (i > 0) - { - m_alreadySeenList.RemoveRange(0, i); - // m_log.DebugFormat("[CLIENT]: expired {0} packets, {1}:{2} left", i, m_alreadySeenList.Count, m_alreadySeenTracker.Count); - } - } - - public void InPacket(Packet packet) - { - if (packet == null) - return; - - // When too many acks are needed to be sent, the client sends - // a packet consisting of acks only - // - if (packet.Type == PacketType.PacketAck) - { - PacketAckPacket ackPacket = (PacketAckPacket)packet; - - foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) - { - ProcessAck(block.ID); - } - - PacketPool.Instance.ReturnPacket(packet); - return; - } - - // Any packet can have some packet acks in the header. - // Process them here - // - if (packet.Header.AppendedAcks) - { - foreach (uint id in packet.Header.AckList) - { - ProcessAck(id); - } - } - - // If this client is on another partial instance, no need - // to handle packets - // - if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest) - { - PacketPool.Instance.ReturnPacket(packet); - return; - } - - if (packet.Type == PacketType.StartPingCheck) - { - StartPingCheckPacket startPing = (StartPingCheckPacket)packet; - CompletePingCheckPacket endPing - = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck); - - endPing.PingID.PingID = startPing.PingID.PingID; - OutPacket(endPing, ThrottleOutPacketType.Task); - } - else - { - LLQueItem item = new LLQueItem(); - item.Packet = packet; - item.Incoming = true; - m_PacketQueue.Enqueue(item); - } - } - - public void ProcessInPacket(LLQueItem item) - { - Packet packet = item.Packet; - - // Always ack the packet! - // - if (packet.Header.Reliable) - AckPacket(packet); - - if (packet.Type != PacketType.AgentUpdate) - m_PacketsReceived++; - - // Check for duplicate packets.. packets that the client is - // resending because it didn't receive our ack - // - lock (m_alreadySeenTracker) - { - ExpireSeenPackets(); - - if (m_alreadySeenTracker.ContainsKey(packet.Header.Sequence)) - return; - - m_alreadySeenTracker.Add(packet.Header.Sequence, Environment.TickCount & Int32.MaxValue); - m_alreadySeenList.Add(packet.Header.Sequence); - } - - m_Client.ProcessInPacket(packet); - } - - public void Flush() - { - m_PacketQueue.Flush(); - m_UnackedBytes = (-1 * m_UnackedBytes); - SendPacketStats(); - } - - public void Clear() - { - m_UnackedBytes = (-1 * m_UnackedBytes); - SendPacketStats(); - lock (m_NeedAck) - { - m_NeedAck.Clear(); - m_PendingAcks.Clear(); - m_PendingAcksMap.Clear(); - } - m_Sequence += 1000000; - } - - private void ProcessAck(uint id) - { - LLQueItem data; - - lock (m_NeedAck) - { - //m_log.DebugFormat("[CLIENT]: In {0} received ack for packet {1}", m_Client.Scene.RegionInfo.ExternalEndPoint.Port, id); - - if (!m_NeedAck.TryGetValue(id, out data)) - return; - - m_NeedAck.Remove(id); - m_PacketQueue.Cancel(data.Sequence); - PacketPool.Instance.ReturnPacket(data.Packet); - m_UnackedBytes -= data.Length; - } - } - - // Allocate packet sequence numbers in a threadsave manner - // - protected uint NextPacketSequenceNumber() - { - // Set the sequence number - uint seq = 1; - lock (m_SequenceLock) - { - if (m_Sequence >= MAX_SEQUENCE) - { - m_Sequence = 1; - } - else - { - m_Sequence++; - } - seq = m_Sequence; - } - return seq; - } - - public ClientInfo GetClientInfo() - { - ClientInfo info = new ClientInfo(); - - info.pendingAcks = m_PendingAcksMap; - info.needAck = new Dictionary(); - - lock (m_NeedAck) - { - foreach (uint key in m_NeedAck.Keys) - info.needAck.Add(key, m_NeedAck[key].Packet.ToBytes()); - } - - LLQueItem[] queitems = m_PacketQueue.GetQueueArray(); - - for (int i = 0; i < queitems.Length; i++) - { - if (queitems[i].Incoming == false) - info.out_packets.Add(queitems[i].Packet.ToBytes()); - } - - info.sequence = m_Sequence; - - float multiplier = m_PacketQueue.ThrottleMultiplier; - info.resendThrottle = (int) (m_PacketQueue.ResendThrottle.Throttle / multiplier); - info.landThrottle = (int) (m_PacketQueue.LandThrottle.Throttle / multiplier); - info.windThrottle = (int) (m_PacketQueue.WindThrottle.Throttle / multiplier); - info.cloudThrottle = (int) (m_PacketQueue.CloudThrottle.Throttle / multiplier); - info.taskThrottle = (int) (m_PacketQueue.TaskThrottle.Throttle / multiplier); - info.assetThrottle = (int) (m_PacketQueue.AssetThrottle.Throttle / multiplier); - info.textureThrottle = (int) (m_PacketQueue.TextureThrottle.Throttle / multiplier); - info.totalThrottle = (int) (m_PacketQueue.TotalThrottle.Throttle / multiplier); - - return info; - } - - public void SetClientInfo(ClientInfo info) - { - m_PendingAcksMap = info.pendingAcks; - m_PendingAcks = new List(m_PendingAcksMap.Keys); - m_NeedAck = new Dictionary(); - - Packet packet = null; - int packetEnd = 0; - byte[] zero = new byte[3000]; - - foreach (uint key in info.needAck.Keys) - { - byte[] buff = info.needAck[key]; - packetEnd = buff.Length - 1; - - try - { - packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero); - } - catch (Exception) - { - } - - LLQueItem item = new LLQueItem(); - item.Packet = packet; - item.Incoming = false; - item.throttleType = 0; - item.TickCount = Environment.TickCount; - item.Identifier = 0; - item.Resends = 0; - item.Length = packet.Length; - item.Sequence = packet.Header.Sequence; - m_NeedAck.Add(key, item); - } - - m_Sequence = info.sequence; - - m_PacketQueue.ResendThrottle.Throttle = info.resendThrottle; - m_PacketQueue.LandThrottle.Throttle = info.landThrottle; - m_PacketQueue.WindThrottle.Throttle = info.windThrottle; - m_PacketQueue.CloudThrottle.Throttle = info.cloudThrottle; - m_PacketQueue.TaskThrottle.Throttle = info.taskThrottle; - m_PacketQueue.AssetThrottle.Throttle = info.assetThrottle; - m_PacketQueue.TextureThrottle.Throttle = info.textureThrottle; - m_PacketQueue.TotalThrottle.Throttle = info.totalThrottle; - } - - public void AddImportantPacket(PacketType type) - { - if (m_ImportantPackets.Contains(type)) - return; - - m_ImportantPackets.Add(type); - } - - public void RemoveImportantPacket(PacketType type) - { - if (!m_ImportantPackets.Contains(type)) - return; - - m_ImportantPackets.Remove(type); - } - - private void DropResend(Object id) - { - LLQueItem d = null; - - foreach (LLQueItem data in m_NeedAck.Values) - { - if (data.Identifier != null && data.Identifier == id) - { - d = data; - break; - } - } - - if (null == d) return; - - m_NeedAck.Remove(d.Packet.Header.Sequence); - m_PacketQueue.Cancel(d.Sequence); - PacketPool.Instance.ReturnPacket(d.Packet); - } - - private void TriggerOnPacketDrop(Packet packet, Object id) - { - PacketDrop handlerPacketDrop = OnPacketDrop; - - if (handlerPacketDrop == null) - return; - - handlerPacketDrop(packet, id); - } - - private void TriggerOnQueueEmpty(ThrottleOutPacketType queue) - { - QueueEmpty handlerQueueEmpty = OnQueueEmpty; - - if (handlerQueueEmpty != null) - handlerQueueEmpty(queue); - } - - // Convert the packet to bytes and stuff it onto the send queue - // - public void ProcessOutPacket(LLQueItem item) - { - Packet packet = item.Packet; - - // Assign sequence number here to prevent out of order packets - if (packet.Header.Sequence == 0) - { - lock (m_NeedAck) - { - packet.Header.Sequence = NextPacketSequenceNumber(); - item.Sequence = packet.Header.Sequence; - item.TickCount = Environment.TickCount; - - // We want to see that packet arrive if it's reliable - if (packet.Header.Reliable) - { - m_UnackedBytes += item.Length; - - // Keep track of when this packet was sent out - item.TickCount = Environment.TickCount; - - m_NeedAck[packet.Header.Sequence] = item; - } - } - } - - // If we sent a killpacket - if (packet is KillPacket) - Abort(); - - try - { - // If this packet has been reused/returned, the ToBytes - // will blow up in our face. - // Fail gracefully. - // - - // Actually make the byte array and send it - byte[] sendbuffer = item.Packet.ToBytes(); - - if (packet.Header.Zerocoded) - { - int packetsize = Helpers.ZeroEncode(sendbuffer, - sendbuffer.Length, m_ZeroOutBuffer); - m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize, - SocketFlags.None, m_Client.CircuitCode); - } - else - { - // Need some extra space in case we need to add proxy - // information to the message later - Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0, - sendbuffer.Length); - m_PacketServer.SendPacketTo(m_ZeroOutBuffer, - sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode); - } - } - catch (NullReferenceException) - { - m_log.Error("[PACKET]: Detected reuse of a returned packet"); - m_PacketQueue.Cancel(item.Sequence); - return; - } - - // If this is a reliable packet, we are still holding a ref - // Dont't return in that case - // - if (!packet.Header.Reliable) - { - m_PacketQueue.Cancel(item.Sequence); - PacketPool.Instance.ReturnPacket(packet); - } - } - - private void Abort() - { - m_PacketQueue.Close(); - Thread.CurrentThread.Abort(); - } - - public int GetQueueCount(ThrottleOutPacketType queue) - { - return m_PacketQueue.GetQueueCount(queue); - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs deleted file mode 100644 index 3eed2e0..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using System.Timers; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Statistics; -using OpenSim.Framework.Statistics.Interfaces; -using Timer=System.Timers.Timer; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public class LLPacketQueue : IPullStatsProvider, IDisposable - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Is queueing enabled at all? - /// - private bool m_enabled = true; - - private OpenSim.Framework.BlockingQueue SendQueue; - - private Queue IncomingPacketQueue; - private Queue OutgoingPacketQueue; - private Queue ResendOutgoingPacketQueue; - private Queue LandOutgoingPacketQueue; - private Queue WindOutgoingPacketQueue; - private Queue CloudOutgoingPacketQueue; - private Queue TaskOutgoingPacketQueue; - private Queue TaskLowpriorityPacketQueue; - private Queue TextureOutgoingPacketQueue; - private Queue AssetOutgoingPacketQueue; - - private List Empty = new List(); - // m_log.Info("[THROTTLE]: Entering Throttle"); - // private Dictionary PendingAcks = new Dictionary(); - // private Dictionary NeedAck = new Dictionary(); - - // All throttle times and number of bytes are calculated by dividing by this value - // This value also determines how many times per throttletimems the timer will run - // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds - - private float throttleMultiplier = 2.0f; // Default value really doesn't matter. - private int throttleTimeDivisor = 7; - - private int throttletimems = 1000; - - internal LLPacketThrottle ResendThrottle; - internal LLPacketThrottle LandThrottle; - internal LLPacketThrottle WindThrottle; - internal LLPacketThrottle CloudThrottle; - internal LLPacketThrottle TaskThrottle; - internal LLPacketThrottle AssetThrottle; - internal LLPacketThrottle TextureThrottle; - internal LLPacketThrottle TotalThrottle; - - private Dictionary contents = new Dictionary(); - - // private long LastThrottle; - // private long ThrottleInterval; - private Timer throttleTimer; - - private UUID m_agentId; - - public event QueueEmpty OnQueueEmpty; - - public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings) - { - // While working on this, the BlockingQueue had me fooled for a bit. - // The Blocking queue causes the thread to stop until there's something - // in it to process. it's an on-purpose threadlock though because - // without it, the clientloop will suck up all sim resources. - - SendQueue = new OpenSim.Framework.BlockingQueue(); - - IncomingPacketQueue = new Queue(); - OutgoingPacketQueue = new Queue(); - ResendOutgoingPacketQueue = new Queue(); - LandOutgoingPacketQueue = new Queue(); - WindOutgoingPacketQueue = new Queue(); - CloudOutgoingPacketQueue = new Queue(); - TaskOutgoingPacketQueue = new Queue(); - TaskLowpriorityPacketQueue = new Queue(); - TextureOutgoingPacketQueue = new Queue(); - AssetOutgoingPacketQueue = new Queue(); - - // Store the throttle multiplier for posterity. - throttleMultiplier = userSettings.ClientThrottleMultipler; - - - int throttleMaxBPS = 1500000; - if (userSettings.TotalThrottleSettings != null) - throttleMaxBPS = userSettings.TotalThrottleSettings.Max; - - // Set up the throttle classes (min, max, current) in bits per second - ResendThrottle = new LLPacketThrottle(5000, throttleMaxBPS / 15, 16000, userSettings.ClientThrottleMultipler); - LandThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 15, 2000, userSettings.ClientThrottleMultipler); - WindThrottle = new LLPacketThrottle(0, throttleMaxBPS / 15, 0, userSettings.ClientThrottleMultipler); - CloudThrottle = new LLPacketThrottle(0, throttleMaxBPS / 15, 0, userSettings.ClientThrottleMultipler); - TaskThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 3000, userSettings.ClientThrottleMultipler); - AssetThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 1000, userSettings.ClientThrottleMultipler); - TextureThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 4000, userSettings.ClientThrottleMultipler); - - - // Total Throttle trumps all - it is the number of bits in total that are allowed to go out per second. - - - ThrottleSettings totalThrottleSettings = userSettings.TotalThrottleSettings; - if (null == totalThrottleSettings) - { - totalThrottleSettings = new ThrottleSettings(0, throttleMaxBPS, 28000); - } - - TotalThrottle - = new LLPacketThrottle( - totalThrottleSettings.Min, totalThrottleSettings.Max, totalThrottleSettings.Current, - userSettings.ClientThrottleMultipler); - - throttleTimer = new Timer((int)(throttletimems / throttleTimeDivisor)); - throttleTimer.Elapsed += ThrottleTimerElapsed; - throttleTimer.Start(); - - // TIMERS needed for this - // LastThrottle = DateTime.Now.Ticks; - // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); - - m_agentId = agentId; - - if (StatsManager.SimExtraStats != null) - { - StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this); - } - } - - /* STANDARD QUEUE MANIPULATION INTERFACES */ - - public void Enqueue(LLQueItem item) - { - if (!m_enabled) - { - return; - } - // We could micro lock, but that will tend to actually - // probably be worse than just synchronizing on SendQueue - - if (item == null) - { - SendQueue.Enqueue(item); - return; - } - - if (item.Incoming) - { - SendQueue.PriorityEnqueue(item); - return; - } - - if (item.Sequence != 0) - lock (contents) - { - if (contents.ContainsKey(item.Sequence)) - contents[item.Sequence] += 1; - else - contents.Add(item.Sequence, 1); - } - - lock (this) - { - switch (item.throttleType & ThrottleOutPacketType.TypeMask) - { - case ThrottleOutPacketType.Resend: - ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item, ThrottleOutPacketType.Resend); - break; - case ThrottleOutPacketType.Texture: - ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item, ThrottleOutPacketType.Texture); - break; - case ThrottleOutPacketType.Task: - if ((item.throttleType & ThrottleOutPacketType.LowPriority) != 0) - ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item, ThrottleOutPacketType.Task); - else - ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item, ThrottleOutPacketType.Task); - break; - case ThrottleOutPacketType.Land: - ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item, ThrottleOutPacketType.Land); - break; - case ThrottleOutPacketType.Asset: - ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item, ThrottleOutPacketType.Asset); - break; - case ThrottleOutPacketType.Cloud: - ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item, ThrottleOutPacketType.Cloud); - break; - case ThrottleOutPacketType.Wind: - ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item, ThrottleOutPacketType.Wind); - break; - - default: - // Acknowledgements and other such stuff should go directly to the blocking Queue - // Throttling them may and likely 'will' be problematic - SendQueue.PriorityEnqueue(item); - break; - } - } - } - - public LLQueItem Dequeue() - { - while (true) - { - LLQueItem item = SendQueue.Dequeue(); - if (item == null) - return null; - if (item.Incoming) - return item; - item.TickCount = System.Environment.TickCount; - if (item.Sequence == 0) - return item; - lock (contents) - { - if (contents.ContainsKey(item.Sequence)) - { - if (contents[item.Sequence] == 1) - contents.Remove(item.Sequence); - else - contents[item.Sequence] -= 1; - return item; - } - } - } - } - - public void Cancel(uint sequence) - { - lock (contents) contents.Remove(sequence); - } - - public bool Contains(uint sequence) - { - lock (contents) return contents.ContainsKey(sequence); - } - - public void Flush() - { - lock (this) - { - // These categories do not contain transactional packets so we can safely drop any pending data in them - LandOutgoingPacketQueue.Clear(); - WindOutgoingPacketQueue.Clear(); - CloudOutgoingPacketQueue.Clear(); - TextureOutgoingPacketQueue.Clear(); - AssetOutgoingPacketQueue.Clear(); - - // Now comes the fun part.. we dump all remaining resend and task packets into the send queue - while (ResendOutgoingPacketQueue.Count > 0 || TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) - { - if (ResendOutgoingPacketQueue.Count > 0) - SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); - - if (TaskOutgoingPacketQueue.Count > 0) - SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue()); - - if (TaskLowpriorityPacketQueue.Count > 0) - SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue()); - } - } - } - - public void WipeClean() - { - lock (this) - { - ResendOutgoingPacketQueue.Clear(); - LandOutgoingPacketQueue.Clear(); - WindOutgoingPacketQueue.Clear(); - CloudOutgoingPacketQueue.Clear(); - TaskOutgoingPacketQueue.Clear(); - TaskLowpriorityPacketQueue.Clear(); - TextureOutgoingPacketQueue.Clear(); - AssetOutgoingPacketQueue.Clear(); - SendQueue.Clear(); - lock (contents) contents.Clear(); - } - } - - public void Close() - { - Dispose(); - } - - public void Dispose() - { - Flush(); - WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby - - m_enabled = false; - throttleTimer.Stop(); - throttleTimer.Close(); - - if (StatsManager.SimExtraStats != null) - { - StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId); - } - } - - private void ResetCounters() - { - ResendThrottle.Reset(); - LandThrottle.Reset(); - WindThrottle.Reset(); - CloudThrottle.Reset(); - TaskThrottle.Reset(); - AssetThrottle.Reset(); - TextureThrottle.Reset(); - TotalThrottle.Reset(); - } - - private bool PacketsWaiting() - { - return (ResendOutgoingPacketQueue.Count > 0 || - LandOutgoingPacketQueue.Count > 0 || - WindOutgoingPacketQueue.Count > 0 || - CloudOutgoingPacketQueue.Count > 0 || - TaskOutgoingPacketQueue.Count > 0 || - TaskLowpriorityPacketQueue.Count > 0 || - AssetOutgoingPacketQueue.Count > 0 || - TextureOutgoingPacketQueue.Count > 0); - } - - public void ProcessThrottle() - { - // I was considering this.. Will an event fire if the thread it's on is blocked? - - // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long - // The General overhead of the UDP protocol gets sent to the queue un-throttled by this - // so This'll pick up about around the right time. - - int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. - int throttleLoops = 0; - List e; - - // We're going to dequeue all of the saved up packets until - // we've hit the throttle limit or there's no more packets to send - lock (this) - { - // this variable will be true if there was work done in the last execution of the - // loop, since each pass through the loop checks the queue length, we no longer - // need the check on entering the loop - bool qchanged = true; - - ResetCounters(); - - while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) - { - qchanged = false; // We will break out of the loop if no work was accomplished - - throttleLoops++; - //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. - if ((ResendOutgoingPacketQueue.Count > 0) && ResendThrottle.UnderLimit()) - { - LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - ResendThrottle.AddBytes(qpack.Length); - - qchanged = true; - } - - if ((LandOutgoingPacketQueue.Count > 0) && LandThrottle.UnderLimit()) - { - LLQueItem qpack = LandOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - LandThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (LandOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Land)) - Empty.Add(ThrottleOutPacketType.Land); - } - - if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) - { - LLQueItem qpack = WindOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - WindThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (WindOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Wind)) - Empty.Add(ThrottleOutPacketType.Wind); - } - - if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) - { - LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - CloudThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (CloudOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Cloud)) - Empty.Add(ThrottleOutPacketType.Cloud); - } - - if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) - { - LLQueItem qpack; - if (TaskOutgoingPacketQueue.Count > 0) - { - qpack = TaskOutgoingPacketQueue.Dequeue(); - SendQueue.PriorityEnqueue(qpack); - } - else - { - qpack = TaskLowpriorityPacketQueue.Dequeue(); - SendQueue.Enqueue(qpack); - } - - TotalThrottle.AddBytes(qpack.Length); - TaskThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Task)) - Empty.Add(ThrottleOutPacketType.Task); - } - - if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) - { - LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - TextureThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (TextureOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Texture)) - Empty.Add(ThrottleOutPacketType.Texture); - } - - if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) - { - LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue(); - - SendQueue.Enqueue(qpack); - TotalThrottle.AddBytes(qpack.Length); - AssetThrottle.AddBytes(qpack.Length); - qchanged = true; - - if (AssetOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Asset)) - Empty.Add(ThrottleOutPacketType.Asset); - } - } - // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); - - e = new List(Empty); - Empty.Clear(); - } - - foreach (ThrottleOutPacketType t in e) - { - if (GetQueueCount(t) == 0) - TriggerOnQueueEmpty(t); - } - } - - private void TriggerOnQueueEmpty(ThrottleOutPacketType queue) - { - QueueEmpty handlerQueueEmpty = OnQueueEmpty; - - if (handlerQueueEmpty != null) - handlerQueueEmpty(queue); - } - - private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) - { - // just to change the signature, and that ProcessThrottle - // will be used elsewhere possibly - ProcessThrottle(); - } - - private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue q, LLQueItem item, ThrottleOutPacketType itemType) - { - // The idea.. is if the packet throttle queues are empty - // and the client is under throttle for the type. Queue - // it up directly. This basically short cuts having to - // wait for the timer to fire to put things into the - // output queue - - if ((q.Count == 0) && (throttle.UnderLimit())) - { - try - { - Monitor.Enter(this); - throttle.AddBytes(item.Length); - TotalThrottle.AddBytes(item.Length); - SendQueue.Enqueue(item); - lock (this) - { - if (!Empty.Contains(itemType)) - Empty.Add(itemType); - } - } - catch (Exception e) - { - // Probably a serialization exception - m_log.WarnFormat("ThrottleCheck: {0}", e.ToString()); - } - finally - { - Monitor.Pulse(this); - Monitor.Exit(this); - } - } - else - { - q.Enqueue(item); - } - } - - private static int ScaleThrottle(int value, int curmax, int newmax) - { - return (int)((value / (float)curmax) * newmax); - } - - public byte[] GetThrottlesPacked(float multiplier) - { - int singlefloat = 4; - float tResend = ResendThrottle.Throttle*multiplier; - float tLand = LandThrottle.Throttle*multiplier; - float tWind = WindThrottle.Throttle*multiplier; - float tCloud = CloudThrottle.Throttle*multiplier; - float tTask = TaskThrottle.Throttle*multiplier; - float tTexture = TextureThrottle.Throttle*multiplier; - float tAsset = AssetThrottle.Throttle*multiplier; - - byte[] throttles = new byte[singlefloat*7]; - int i = 0; - Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat); - i++; - Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat); - - return throttles; - } - - public void SetThrottleFromClient(byte[] throttle) - { - // From mantis http://opensimulator.org/mantis/view.php?id=1374 - // it appears that sometimes we are receiving empty throttle byte arrays. - // TODO: Investigate this behaviour - if (throttle.Length == 0) - { - m_log.Warn("[PACKET QUEUE]: SetThrottleFromClient unexpectedly received a throttle byte array containing no elements!"); - return; - } - - int tResend = -1; - int tLand = -1; - int tWind = -1; - int tCloud = -1; - int tTask = -1; - int tTexture = -1; - int tAsset = -1; - int tall = -1; - int singlefloat = 4; - - //Agent Throttle Block contains 7 single floatingpoint values. - int j = 0; - - // Some Systems may be big endian... - // it might be smart to do this check more often... - if (!BitConverter.IsLittleEndian) - for (int i = 0; i < 7; i++) - Array.Reverse(throttle, j + i*singlefloat, singlefloat); - - // values gotten from OpenMetaverse.org/wiki/Throttle. Thanks MW_ - // bytes - // Convert to integer, since.. the full fp space isn't used. - tResend = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tLand = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tWind = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tCloud = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tTask = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tTexture = (int) BitConverter.ToSingle(throttle, j); - j += singlefloat; - tAsset = (int) BitConverter.ToSingle(throttle, j); - - tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; - - /* - m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbits=" + tResend + - " landbits=" + tLand + - " windbits=" + tWind + - " cloudbits=" + tCloud + - " taskbits=" + tTask + - " texturebits=" + tTexture + - " Assetbits=" + tAsset + - " Allbits=" + tall); - */ - - - // Total Sanity - // Make sure that the client sent sane total values. - - // If the client didn't send acceptable values.... - // Scale the clients values down until they are acceptable. - - if (tall <= TotalThrottle.Max) - { - ResendThrottle.Throttle = tResend; - LandThrottle.Throttle = tLand; - WindThrottle.Throttle = tWind; - CloudThrottle.Throttle = tCloud; - TaskThrottle.Throttle = tTask; - TextureThrottle.Throttle = tTexture; - AssetThrottle.Throttle = tAsset; - TotalThrottle.Throttle = tall; - } -// else if (tall < 1) -// { -// // client is stupid, penalize him by minning everything -// ResendThrottle.Throttle = ResendThrottle.Min; -// LandThrottle.Throttle = LandThrottle.Min; -// WindThrottle.Throttle = WindThrottle.Min; -// CloudThrottle.Throttle = CloudThrottle.Min; -// TaskThrottle.Throttle = TaskThrottle.Min; -// TextureThrottle.Throttle = TextureThrottle.Min; -// AssetThrottle.Throttle = AssetThrottle.Min; -// TotalThrottle.Throttle = TotalThrottle.Min; -// } - else - { - // we're over so figure out percentages and use those - ResendThrottle.Throttle = tResend; - - LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max); - WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max); - CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max); - TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max); - TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max); - AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max); - TotalThrottle.Throttle = TotalThrottle.Max; - } - // effectively wiggling the slider causes things reset -// ResetCounters(); // DO NOT reset, better to send less for one period than more - } - - // See IPullStatsProvider - public string GetStats() - { - return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", - SendQueue.Count(), - IncomingPacketQueue.Count, - OutgoingPacketQueue.Count, - ResendOutgoingPacketQueue.Count, - LandOutgoingPacketQueue.Count, - WindOutgoingPacketQueue.Count, - CloudOutgoingPacketQueue.Count, - TaskOutgoingPacketQueue.Count, - TextureOutgoingPacketQueue.Count, - AssetOutgoingPacketQueue.Count); - } - - public LLQueItem[] GetQueueArray() - { - return SendQueue.GetQueueArray(); - } - - public float ThrottleMultiplier - { - get { return throttleMultiplier; } - } - - public int GetQueueCount(ThrottleOutPacketType queue) - { - switch (queue) - { - case ThrottleOutPacketType.Land: - return LandOutgoingPacketQueue.Count; - case ThrottleOutPacketType.Wind: - return WindOutgoingPacketQueue.Count; - case ThrottleOutPacketType.Cloud: - return CloudOutgoingPacketQueue.Count; - case ThrottleOutPacketType.Task: - return TaskOutgoingPacketQueue.Count; - case ThrottleOutPacketType.Texture: - return TextureOutgoingPacketQueue.Count; - case ThrottleOutPacketType.Asset: - return AssetOutgoingPacketQueue.Count; - } - - return 0; - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs deleted file mode 100644 index f08b7be..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Net; -using System.Net.Sockets; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - /// - /// This class sets up new client stacks. It also handles the immediate distribution of incoming packets to - /// client stacks - /// - public class LLPacketServer - { -// private static readonly log4net.ILog m_log -// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - protected readonly LLUDPServer m_networkHandler; - protected IScene m_scene; - - /// - /// Tweakable user settings - /// - private ClientStackUserSettings m_userSettings; - - public LLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings) - { - m_userSettings = userSettings; - m_networkHandler = networkHandler; - - m_networkHandler.RegisterPacketServer(this); - } - - public IScene LocalScene - { - set { m_scene = value; } - } - - /// - /// Process an incoming packet. - /// - /// - /// - public virtual void InPacket(uint circuitCode, Packet packet) - { - m_scene.ClientManager.InPacket(circuitCode, packet); - } - - /// - /// Create a new client circuit - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - protected virtual IClientAPI CreateNewCircuit( - EndPoint remoteEP, IScene scene, - LLPacketServer packServer, AuthenticateResponse sessionInfo, - UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP) - { - return - new LLClientView( - remoteEP, scene, packServer, sessionInfo, agentId, sessionId, circuitCode, proxyEP, - m_userSettings); - } - - /// - /// Check whether a given client is authorized to connect. - /// - /// - /// - /// - /// - public virtual bool IsClientAuthorized( - UseCircuitCodePacket useCircuit, AgentCircuitManager circuitManager, out AuthenticateResponse sessionInfo) - { - UUID agentId = useCircuit.CircuitCode.ID; - UUID sessionId = useCircuit.CircuitCode.SessionID; - uint circuitCode = useCircuit.CircuitCode.Code; - - sessionInfo = circuitManager.AuthenticateSession(sessionId, agentId, circuitCode); - - if (!sessionInfo.Authorised) - return false; - - return true; - } - - /// - /// Add a new client circuit. We assume that is has already passed an authorization check - /// - /// - /// - /// - /// - /// - /// - /// true if a new circuit was created, false if a circuit with the given circuit code already existed - /// - public virtual bool AddNewClient( - EndPoint epSender, UseCircuitCodePacket useCircuit, - AuthenticateResponse sessionInfo, EndPoint proxyEP) - { - IClientAPI newuser; - uint circuitCode = useCircuit.CircuitCode.Code; - - if (m_scene.ClientManager.TryGetClient(circuitCode, out newuser)) - { - // The circuit is already known to the scene. This not actually a problem since this will currently - // occur if a client is crossing borders (hence upgrading its circuit). However, we shouldn't - // really by trying to add a new client if this is the case. - return false; - } - - UUID agentId = useCircuit.CircuitCode.ID; - UUID sessionId = useCircuit.CircuitCode.SessionID; - - newuser - = CreateNewCircuit( - epSender, m_scene, this, sessionInfo, agentId, sessionId, circuitCode, proxyEP); - - m_scene.ClientManager.Add(circuitCode, newuser); - - newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; - newuser.OnLogout += LogoutHandler; - newuser.OnConnectionClosed += CloseClient; - - newuser.Start(); - - return true; - } - - public void LogoutHandler(IClientAPI client) - { - client.SendLogoutPacket(); - CloseClient(client); - } - - /// - /// Send a packet to the given circuit - /// - /// - /// - /// - /// - public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) - { - m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode); - } - - /// - /// Close a client circuit only - /// - /// - public virtual void CloseCircuit(uint circuitcode) - { - m_networkHandler.RemoveClientCircuit(circuitcode); - } - - /// - /// Completely close down the given client. - /// - /// - public virtual void CloseClient(IClientAPI client) - { - //m_log.Info("PacketServer:CloseClient()"); - - CloseCircuit(client.CircuitCode); - m_scene.ClientManager.Remove(client.CircuitCode); - client.Close(false); - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs b/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs deleted file mode 100644 index 0ed2bc1..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse.Packets; -using OpenSim.Framework; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public class LLQueItem - { - public LLQueItem() - { - } - - public Packet Packet; - public bool Incoming; - public ThrottleOutPacketType throttleType; - public int TickCount; - public Object Identifier; - public int Resends; - public int Length; - public uint Sequence; - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs new file mode 100644 index 0000000..ad01135 --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -0,0 +1,370 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public delegate void QueueEmpty(ThrottleOutPacketType category); + + public class LLUDPClient + { + /// The number of packet categories to throttle on. If a throttle category is added + /// or removed, this number must also change + const int THROTTLE_CATEGORY_COUNT = 7; + + public event QueueEmpty OnQueueEmpty; + + /// AgentID for this client + public readonly UUID AgentID; + /// The remote address of the connected client + public readonly IPEndPoint RemoteEndPoint; + /// Circuit code that this client is connected on + public readonly uint CircuitCode; + /// Sequence numbers of packets we've received (for duplicate checking) + public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); + /// Packets we have sent that need to be ACKed by the client + public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); + /// ACKs that are queued up, waiting to be sent to the client + public readonly LocklessQueue PendingAcks = new LocklessQueue(); + + /// Reference to the IClientAPI for this client + public LLClientView ClientAPI; + /// Current packet sequence number + public int CurrentSequence; + /// Current ping sequence number + public byte CurrentPingSequence; + /// True when this connection is alive, otherwise false + public bool IsConnected = true; + /// True when this connection is paused, otherwise false + public bool IsPaused = true; + /// Environment.TickCount when the last packet was received for this client + public int TickLastPacketReceived; + + /// Timer granularity. This is set to the measured resolution of Environment.TickCount + public readonly float G; + /// Smoothed round-trip time. A smoothed average of the round-trip time for sending a + /// reliable packet to the client and receiving an ACK + public float SRTT; + /// Round-trip time variance. Measures the consistency of round-trip times + public float RTTVAR; + /// Retransmission timeout. Packets that have not been acknowledged in this number of + /// milliseconds or longer will be resent + /// Calculated from and using the + /// guidelines in RFC 2988 + public int RTO; + /// Number of bytes received since the last acknowledgement was sent out. This is used + /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2) + public int BytesSinceLastACK; + + /// Throttle bucket for this agent's connection + private readonly TokenBucket throttle; + /// Throttle buckets for each packet category + private readonly TokenBucket[] throttleCategories; + /// Throttle rate defaults and limits + private readonly ThrottleRates defaultThrottleRates; + /// Outgoing queues for throttled packets + private readonly LocklessQueue[] packetOutboxes = new LocklessQueue[THROTTLE_CATEGORY_COUNT]; + /// A container that can hold one packet for each outbox, used to store + /// dequeued packets that are being held for throttling + private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; + /// An optimization to store the length of dequeued packets being held + /// for throttling. This avoids expensive calls to Packet.Length + private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; + /// A reference to the LLUDPServer that is managing this client + private readonly LLUDPServer udpServer; + + public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) + { + udpServer = server; + AgentID = agentID; + RemoteEndPoint = remoteEndPoint; + CircuitCode = circuitCode; + defaultThrottleRates = rates; + + for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) + packetOutboxes[i] = new LocklessQueue(); + + throttle = new TokenBucket(parentThrottle, 0, 0); + throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; + throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); + throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); + throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); + throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); + throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task); + throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); + throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); + + // Set the granularity variable used for retransmission calculations to + // the measured resolution of Environment.TickCount + G = server.TickCountResolution; + + // Default the retransmission timeout to three seconds + RTO = 3000; + } + + public void Shutdown() + { + IsConnected = false; + } + + public ClientInfo GetClientInfo() + { + // TODO: This data structure is wrong in so many ways + ClientInfo info = new ClientInfo(); + info.pendingAcks = new Dictionary(); + info.needAck = new Dictionary(); + + info.resendThrottle = throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; + info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; + info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; + info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; + info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; + info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; + info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; + info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + + info.taskThrottle + info.assetThrottle + info.textureThrottle; + + return info; + } + + public void SetClientInfo(ClientInfo info) + { + } + + public string GetStats() + { + return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0); + } + + public void SetThrottles(byte[] throttleData) + { + byte[] adjData; + int pos = 0; + + if (!BitConverter.IsLittleEndian) + { + byte[] newData = new byte[7 * 4]; + Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4); + + for (int i = 0; i < 7; i++) + Array.Reverse(newData, i * 4, 4); + + adjData = newData; + } + else + { + adjData = throttleData; + } + + int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + + resend = (resend <= defaultThrottleRates.ResendLimit) ? resend : defaultThrottleRates.ResendLimit; + land = (land <= defaultThrottleRates.LandLimit) ? land : defaultThrottleRates.LandLimit; + wind = (wind <= defaultThrottleRates.WindLimit) ? wind : defaultThrottleRates.WindLimit; + cloud = (cloud <= defaultThrottleRates.CloudLimit) ? cloud : defaultThrottleRates.CloudLimit; + task = (task <= defaultThrottleRates.TaskLimit) ? task : defaultThrottleRates.TaskLimit; + texture = (texture <= defaultThrottleRates.TextureLimit) ? texture : defaultThrottleRates.TextureLimit; + asset = (asset <= defaultThrottleRates.AssetLimit) ? asset : defaultThrottleRates.AssetLimit; + + SetThrottle(ThrottleOutPacketType.Resend, resend); + SetThrottle(ThrottleOutPacketType.Land, land); + SetThrottle(ThrottleOutPacketType.Wind, wind); + SetThrottle(ThrottleOutPacketType.Cloud, cloud); + SetThrottle(ThrottleOutPacketType.Task, task); + SetThrottle(ThrottleOutPacketType.Texture, texture); + SetThrottle(ThrottleOutPacketType.Asset, asset); + } + + public byte[] GetThrottlesPacked() + { + byte[] data = new byte[7 * 4]; + int i = 0; + + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Task].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; + + return data; + } + + public void SetThrottle(ThrottleOutPacketType category, int rate) + { + int i = (int)category; + if (i >= 0 && i < throttleCategories.Length) + { + TokenBucket bucket = throttleCategories[(int)category]; + bucket.MaxBurst = rate; + bucket.DripRate = rate; + } + } + + public bool EnqueueOutgoing(OutgoingPacket packet) + { + int category = (int)packet.Category; + + if (category >= 0 && category < packetOutboxes.Length) + { + LocklessQueue queue = packetOutboxes[category]; + TokenBucket bucket = throttleCategories[category]; + + if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) + { + // Enough tokens were removed from the bucket, the packet will not be queued + return false; + } + else + { + // Not enough tokens in the bucket, queue this packet + queue.Enqueue(packet); + return true; + } + } + else + { + // We don't have a token bucket for this category, so it will not be queued + return false; + } + } + + /// + /// Loops through all of the packet queues for this client and tries to send + /// any outgoing packets, obeying the throttling bucket limits + /// + /// This function is only called from a synchronous loop in the + /// UDPServer so we don't need to bother making this thread safe + /// True if any packets were sent, otherwise false + public bool DequeueOutgoing() + { + OutgoingPacket packet; + LocklessQueue queue; + TokenBucket bucket; + bool packetSent = false; + + for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) + { + bucket = throttleCategories[i]; + + if (nextPackets[i] != null) + { + // This bucket was empty the last time we tried to send a packet, + // leaving a dequeued packet still waiting to be sent out. Try to + // send it again + if (bucket.RemoveTokens(nextPacketLengths[i])) + { + // Send the packet + udpServer.SendPacketFinal(nextPackets[i]); + nextPackets[i] = null; + packetSent = true; + } + } + else + { + // No dequeued packet waiting to be sent, try to pull one off + // this queue + queue = packetOutboxes[i]; + if (queue.Dequeue(out packet)) + { + // A packet was pulled off the queue. See if we have + // enough tokens in the bucket to send it out + if (bucket.RemoveTokens(packet.Buffer.DataLength)) + { + // Send the packet + udpServer.SendPacketFinal(packet); + packetSent = true; + } + else + { + // Save the dequeued packet and the length calculation for + // the next iteration + nextPackets[i] = packet; + nextPacketLengths[i] = packet.Buffer.DataLength; + } + } + else + { + // No packets in this queue. Fire the queue empty callback + QueueEmpty callback = OnQueueEmpty; + if (callback != null) + callback((ThrottleOutPacketType)i); + } + } + } + + return packetSent; + } + + public void UpdateRoundTrip(float r) + { + const float ALPHA = 0.125f; + const float BETA = 0.25f; + const float K = 4.0f; + + if (RTTVAR == 0.0f) + { + // First RTT measurement + SRTT = r; + RTTVAR = r * 0.5f; + } + else + { + // Subsequence RTT measurement + RTTVAR = (1.0f - BETA) * RTTVAR + BETA * Math.Abs(SRTT - r); + SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r; + } + + // Always round retransmission timeout up to two seconds + RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); + //Logger.Debug("Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + + // RTTVAR + " based on new RTT of " + r + "ms"); + } + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs new file mode 100644 index 0000000..7d2da68 --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs @@ -0,0 +1,185 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenSim.Framework; +using OpenMetaverse; + +using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class UDPClientCollection + { + Dictionary Dictionary1; + Dictionary Dictionary2; + LLUDPClient[] Array; + ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl(); + + public UDPClientCollection() + { + Dictionary1 = new Dictionary(); + Dictionary2 = new Dictionary(); + Array = new LLUDPClient[0]; + } + + public UDPClientCollection(int capacity) + { + Dictionary1 = new Dictionary(capacity); + Dictionary2 = new Dictionary(capacity); + Array = new LLUDPClient[0]; + } + + public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) + { + rwLock.EnterWriteLock(); + + try + { + if (Dictionary1.ContainsKey(key1)) + { + if (!Dictionary2.ContainsKey(key2)) + throw new ArgumentException("key1 exists in the dictionary but not key2"); + } + else if (Dictionary2.ContainsKey(key2)) + { + if (!Dictionary1.ContainsKey(key1)) + throw new ArgumentException("key2 exists in the dictionary but not key1"); + } + + Dictionary1[key1] = value; + Dictionary2[key2] = value; + + LLUDPClient[] oldArray = Array; + int oldLength = oldArray.Length; + + LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; + for (int i = 0; i < oldLength; i++) + newArray[i] = oldArray[i]; + newArray[oldLength] = value; + + Array = newArray; + } + finally { rwLock.ExitWriteLock(); } + } + + public bool Remove(UUID key1, IPEndPoint key2) + { + rwLock.EnterWriteLock(); + + try + { + LLUDPClient value; + if (Dictionary1.TryGetValue(key1, out value)) + { + Dictionary1.Remove(key1); + Dictionary2.Remove(key2); + + LLUDPClient[] oldArray = Array; + int oldLength = oldArray.Length; + + LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; + int j = 0; + for (int i = 0; i < oldLength; i++) + { + if (oldArray[i] != value) + newArray[j++] = oldArray[i]; + } + + Array = newArray; + return true; + } + } + finally { rwLock.ExitWriteLock(); } + + return false; + } + + public void Clear() + { + rwLock.EnterWriteLock(); + + try + { + Dictionary1.Clear(); + Dictionary2.Clear(); + Array = new LLUDPClient[0]; + } + finally { rwLock.ExitWriteLock(); } + } + + public int Count + { + get { return Array.Length; } + } + + public bool ContainsKey(UUID key) + { + return Dictionary1.ContainsKey(key); + } + + public bool ContainsKey(IPEndPoint key) + { + return Dictionary2.ContainsKey(key); + } + + public bool TryGetValue(UUID key, out LLUDPClient value) + { + bool success; + bool doLock = !rwLock.IsUpgradeableReadLockHeld; + if (doLock) rwLock.EnterReadLock(); + + try { success = Dictionary1.TryGetValue(key, out value); } + finally { if (doLock) rwLock.ExitReadLock(); } + + return success; + } + + public bool TryGetValue(IPEndPoint key, out LLUDPClient value) + { + bool success; + bool doLock = !rwLock.IsUpgradeableReadLockHeld; + if (doLock) rwLock.EnterReadLock(); + + try { success = Dictionary2.TryGetValue(key, out value); } + finally { if (doLock) rwLock.ExitReadLock(); } + + return success; + } + + public void ForEach(Action action) + { + bool doLock = !rwLock.IsUpgradeableReadLockHeld; + if (doLock) rwLock.EnterUpgradeableReadLock(); + + try { Parallel.ForEach(Array, action); } + finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } + } + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 7964c50..348615e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -35,6 +35,7 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; +using OpenSim.Framework.Statistics; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; @@ -190,31 +191,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void RemoveClient(LLUDPClient udpClient) - { - IClientAPI client; - - if (m_scene.ClientManager.TryGetClient(udpClient.CircuitCode, out client)) - RemoveClient(client); - else - m_log.Warn("[LLUDPSERVER]: Failed to lookup IClientAPI for LLUDPClient " + udpClient.AgentID); - } - - public void SetClientPaused(UUID agentID, bool paused) - { - LLUDPClient client; - if (clients.TryGetValue(agentID, out client)) - { - client.IsPaused = paused; - } - else - { - m_log.Warn("[LLUDPSERVER]: Attempted to pause/unpause unknown agent " + agentID); - } - } - public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) { + // CoarseLocationUpdate packets cannot be split in an automated way + if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) + allowSplitting = false; + if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); @@ -251,6 +233,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { + // CoarseLocationUpdate packets cannot be split in an automated way + if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) + allowSplitting = false; + if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); @@ -339,6 +325,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void SendPing(LLUDPClient client) + { + IClientAPI api = client.ClientAPI; + if (api != null) + api.SendStartPingCheck(client.CurrentPingSequence++); + } + public void ResendUnacked(LLUDPClient client) { if (client.NeedAcks.Count > 0) @@ -387,9 +380,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP //FIXME: Make 60 an .ini setting if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) { - m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.RemoteEndPoint); + m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name); - RemoveClient(client); + RemoveClient(client.ClientAPI); return; } } @@ -590,8 +583,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); clients.Add(agentID, client.RemoteEndPoint, client); - // Create the IClientAPI - IClientAPI clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); + // Create the LLClientView + LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; clientApi.OnLogout += LogoutHandler; clientApi.OnConnectionClosed += RemoveClient; @@ -618,23 +611,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void IncomingPacketHandler() { - IncomingPacket incomingPacket = new IncomingPacket(); - Packet packet = null; - LLUDPClient client = null; + // Set this culture for the thread that incoming packets are received + // on to en-US to avoid number parsing issues + Culture.SetCurrentCulture(); + + IncomingPacket incomingPacket = default(IncomingPacket); while (base.IsRunning) { - // Reset packet to null for the check below - packet = null; - if (packetInbox.Dequeue(100, ref incomingPacket)) - { - packet = incomingPacket.Packet; - client = incomingPacket.Client; - - if (packet != null && client != null) - client.ClientAPI.ProcessInPacket(packet); - } + Util.FireAndForget(ProcessInPacket, incomingPacket); } if (packetInbox.Count > 0) @@ -642,32 +628,98 @@ namespace OpenSim.Region.ClientStack.LindenUDP packetInbox.Clear(); } + private void ProcessInPacket(object state) + { + IncomingPacket incomingPacket = (IncomingPacket)state; + Packet packet = incomingPacket.Packet; + LLUDPClient client = incomingPacket.Client; + + if (packet != null && client != null) + { + try + { + client.ClientAPI.ProcessInPacket(packet); + } + catch (ThreadAbortException) + { + throw; + } + catch (Exception e) + { + if (StatsManager.SimExtraStats != null) + StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); + + // Don't let a failure in an individual client thread crash the whole sim. + m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} {1} crashed. Logging them out", client.ClientAPI.Name, client.AgentID); + m_log.Error(e.Message, e); + + try + { + // Make an attempt to alert the user that their session has crashed + AgentAlertMessagePacket alert = client.ClientAPI.BuildAgentAlertPacket( + "Unfortunately the session for this client on the server has crashed.\n" + + "Any further actions taken will not be processed.\n" + + "Please relog", true); + + SendPacket(client, alert, ThrottleOutPacketType.Unknown, false); + + // TODO: There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to + // listeners yet, though. + client.ClientAPI.SendLogoutPacket(); + RemoveClient(client.ClientAPI); + } + catch (ThreadAbortException) + { + throw; + } + catch (Exception e2) + { + m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.ClientAPI.Name); + m_log.Error(e2.Message, e2); + } + } + } + } + private void OutgoingPacketHandler() { + // Set this culture for the thread that outgoing packets are sent + // on to en-US to avoid number parsing issues + Culture.SetCurrentCulture(); + int now = Environment.TickCount; int elapsedMS = 0; int elapsed100MS = 0; + int elapsed500MS = 0; while (base.IsRunning) { bool resendUnacked = false; bool sendAcks = false; + bool sendPings = false; bool packetSent = false; elapsedMS += Environment.TickCount - now; - // Check for packets that need to be resent every 100ms + // Check for pending outgoing resends every 100ms if (elapsedMS >= 100) { resendUnacked = true; elapsedMS -= 100; ++elapsed100MS; } - // Check for ACKs that need to be sent out every 500ms + // Check for pending outgoing ACKs every 500ms if (elapsed100MS >= 5) { sendAcks = true; elapsed100MS = 0; + ++elapsed500MS; + } + // Send pings to clients every 2000ms + if (elapsed500MS >= 4) + { + sendPings = true; + elapsed500MS = 0; } clients.ForEach( @@ -679,6 +731,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResendUnacked(client); if (sendAcks) SendAcks(client); + if (sendPings) + SendPing(client); } ); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs deleted file mode 100644 index 066b19d..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using OpenMetaverse; - -using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public class LLUtil - { - /// - /// Convert a string to bytes suitable for use in an LL UDP packet. - /// - /// Truncated to 254 characters if necessary - /// - public static byte[] StringToPacketBytes(string s) - { - // Anything more than 254 will cause libsecondlife to barf - // (libsl 1550) adds an \0 on the Utils.StringToBytes conversion if it isn't present - if (s.Length > 254) - { - s = s.Remove(254); - } - - return Utils.StringToBytes(s); - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs new file mode 100644 index 0000000..69b0c5f --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class OutgoingPacket + { + /// Client this packet is destined for + public LLUDPClient Client; + /// Packet data to send + public UDPPacketBuffer Buffer; + /// Sequence number of the wrapped packet + public uint SequenceNumber; + /// Number of times this packet has been resent + public int ResendCount; + /// Environment.TickCount when this packet was last sent over the wire + public int TickCount; + /// Category this packet belongs to + public ThrottleOutPacketType Category; + + public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) + { + Client = client; + Buffer = buffer; + Category = category; + } + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs new file mode 100644 index 0000000..ffa20d5 --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using Nini.Config; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class ThrottleRates + { + public int Resend; + public int Land; + public int Wind; + public int Cloud; + public int Task; + public int Texture; + public int Asset; + + public int ResendLimit; + public int LandLimit; + public int WindLimit; + public int CloudLimit; + public int TaskLimit; + public int TextureLimit; + public int AssetLimit; + + public ThrottleRates(IConfigSource config) + { + try + { + IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; + + Resend = throttleConfig.GetInt("ResendDefault", 12500); + Land = throttleConfig.GetInt("LandDefault", 500); + Wind = throttleConfig.GetInt("WindDefault", 500); + Cloud = throttleConfig.GetInt("CloudDefault", 500); + Task = throttleConfig.GetInt("TaskDefault", 500); + Texture = throttleConfig.GetInt("TextureDefault", 500); + Asset = throttleConfig.GetInt("AssetDefault", 500); + + ResendLimit = throttleConfig.GetInt("ResendLimit", 18750); + LandLimit = throttleConfig.GetInt("LandLimit", 29750); + WindLimit = throttleConfig.GetInt("WindLimit", 18750); + CloudLimit = throttleConfig.GetInt("CloudLimit", 18750); + TaskLimit = throttleConfig.GetInt("TaskLimit", 55750); + TextureLimit = throttleConfig.GetInt("TextureLimit", 55750); + AssetLimit = throttleConfig.GetInt("AssetLimit", 27500); + } + catch (Exception) { } + } + } +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs new file mode 100644 index 0000000..16c0035 --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class UnackedPacketCollection + { + public object SyncRoot = new object(); + + SortedDictionary packets; + + public int Count { get { return packets.Count; } } + + public UnackedPacketCollection() + { + packets = new SortedDictionary(); + } + + public bool Add(OutgoingPacket packet) + { + lock (SyncRoot) + { + if (!packets.ContainsKey(packet.SequenceNumber)) + { + packets.Add(packet.SequenceNumber, packet); + return true; + } + return false; + } + } + + public bool RemoveUnsafe(uint sequenceNumber) + { + return packets.Remove(sequenceNumber); + } + + public bool RemoveUnsafe(uint sequenceNumber, out OutgoingPacket packet) + { + if (packets.TryGetValue(sequenceNumber, out packet)) + { + packets.Remove(sequenceNumber); + return true; + } + + return false; + } + + public OutgoingPacket GetOldest() + { + lock (SyncRoot) + { + using (SortedDictionary.ValueCollection.Enumerator e = packets.Values.GetEnumerator()) + return e.Current; + } + } + + public List GetExpiredPackets(int timeout) + { + List expiredPackets = null; + + lock (SyncRoot) + { + int now = Environment.TickCount; + foreach (OutgoingPacket packet in packets.Values) + { + if (packet.TickCount == 0) + continue; + + if (now - packet.TickCount >= timeout) + { + if (expiredPackets == null) + expiredPackets = new List(); + expiredPackets.Add(packet); + } + else + { + break; + } + } + } + + return expiredPackets; + } + } +} -- cgit v1.1 From 2519f071f2c592aeea0414c8b2871e5df623271c Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 02:50:59 -0700 Subject: Fixing a few compile errors in the previous commit --- OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 1 - OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | 1 - OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 2 -- OpenSim/Region/Framework/Scenes/Scene.cs | 2 -- OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs | 1 - OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs | 1 - OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs | 1 - OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs | 1 - .../ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs | 1 - 9 files changed, 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 45e724d..d78931a 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -323,7 +323,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest httpThread.IsBackground = true; _finished = false; httpThread.Start(); - ThreadTracker.Add(httpThread); } /* diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 8a169f8..97899a7 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -639,7 +639,6 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC httpThread.IsBackground = true; _finished = false; httpThread.Start(); - ThreadTracker.Add(httpThread); } /* diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 05ed70a..4fb4c51 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -345,7 +345,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapItemReqThread.Priority = ThreadPriority.BelowNormal; mapItemReqThread.SetApartmentState(ApartmentState.MTA); mapItemReqThread.Start(); - ThreadTracker.Add(mapItemReqThread); } /// @@ -447,7 +446,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // end gracefully if (st.agentID == UUID.Zero) { - ThreadTracker.Remove(mapItemReqThread); break; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 606135b..30c2223 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -901,7 +901,6 @@ namespace OpenSim.Region.Framework.Scenes //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); if (HeartbeatThread != null) { - ThreadTracker.Remove(HeartbeatThread); HeartbeatThread.Abort(); HeartbeatThread = null; } @@ -910,7 +909,6 @@ namespace OpenSim.Region.Framework.Scenes HeartbeatThread.SetApartmentState(ApartmentState.MTA); HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName); HeartbeatThread.Priority = ThreadPriority.AboveNormal; - ThreadTracker.Add(HeartbeatThread); HeartbeatThread.Start(); } diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index 9273fb5..cd401a6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -360,7 +360,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat m_listener.Name = "IRCConnectorListenerThread"; m_listener.IsBackground = true; m_listener.Start(); - ThreadTracker.Add(m_listener); // This is the message order recommended by RFC 2812 if (m_password != null) diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs index 7202601..16fe9e9 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs @@ -152,7 +152,6 @@ namespace OpenSim.Region.OptionalModules.ContentManagement m_thread.Name = "Content Management"; m_thread.IsBackground = true; m_thread.Start(); - ThreadTracker.Add(m_thread); m_state = State.NONE; } } diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs index 0feb967..583d2ff 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs @@ -138,7 +138,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine EventQueueThread.Priority = MyThreadPriority; EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; EventQueueThread.Start(); - ThreadTracker.Add(EventQueueThread); // Look at this... Don't you wish everyone did that solid // coding everywhere? :P diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs index 8bafe77..7ffdb1a 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs @@ -97,7 +97,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine MaintenanceThreadThread.Name = "ScriptMaintenanceThread"; MaintenanceThreadThread.IsBackground = true; MaintenanceThreadThread.Start(); - ThreadTracker.Add(MaintenanceThreadThread); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index e454524..1607d34 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -142,7 +142,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api cmdHandlerThread.Priority = ThreadPriority.BelowNormal; cmdHandlerThread.IsBackground = true; cmdHandlerThread.Start(); - ThreadTracker.Add(cmdHandlerThread); } } -- cgit v1.1 From 3db4d38645260b0299e082b47b010dddf569bf31 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 09:54:15 -0700 Subject: Removing dependencies on System.Runtime.Remoting. --- OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs index 44e850b..6c89ac8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs @@ -61,6 +61,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private void OnRegionUp(GridRegion otherRegion) { + // This shouldn't happen + if (otherRegion == null) + return; + m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}", m_scene.RegionInfo.RegionName, otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); -- cgit v1.1 From fb19d1ca0a7c6e82c540c4e8d22c82c09b7bec98 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 10:12:59 -0700 Subject: * Try/catch around EndInvoke() when Util.FireAndForget() returns to catch exceptions thrown in the async method * Added packet stats handling to the new LLUDP implementation * Attempting to avoid a race condition when creating a new LLUDPClient --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 3 +- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 40 ++++-- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 147 ++++++++++++--------- 3 files changed, 112 insertions(+), 78 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 767020f..84e705a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -186,8 +186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer = udpServer; m_udpClient = udpClient; m_udpClient.OnQueueEmpty += HandleQueueEmpty; - // FIXME: Implement this - //m_udpClient.OnPacketStats += PopulateStats; + m_udpClient.OnPacketStats += PopulateStats; RegisterLocalPacketHandlers(); } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index ad01135..f2e76d3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -33,6 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { + public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); public delegate void QueueEmpty(ThrottleOutPacketType category); public class LLUDPClient @@ -41,6 +42,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// or removed, this number must also change const int THROTTLE_CATEGORY_COUNT = 7; + public event PacketStats OnPacketStats; public event QueueEmpty OnQueueEmpty; /// AgentID for this client @@ -84,6 +86,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Number of bytes received since the last acknowledgement was sent out. This is used /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2) public int BytesSinceLastACK; + /// Number of packets received from this client + public int PacketsReceived; + /// Number of packets sent to this client + public int PacketsSent; + /// Total byte count of unacked packets sent to this client + public int UnackedBytes; + + /// Total number of received packets that we have reported to the OnPacketStats event(s) + private int m_packetsReceivedReported; + /// Total number of sent packets that we have reported to the OnPacketStats event(s) + private int m_packetsSentReported; /// Throttle bucket for this agent's connection private readonly TokenBucket throttle; @@ -162,17 +175,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP public string GetStats() { + // TODO: ??? return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + public void SendPacketStats() + { + PacketStats callback = OnPacketStats; + if (callback != null) + { + int newPacketsReceived = PacketsReceived - m_packetsReceivedReported; + int newPacketsSent = PacketsSent - m_packetsSentReported; + + callback(newPacketsReceived, newPacketsSent, UnackedBytes); + + m_packetsReceivedReported += newPacketsReceived; + m_packetsSentReported += newPacketsSent; + } } public void SetThrottles(byte[] throttleData) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 348615e..38890da 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -359,6 +359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // is actually sent out again outgoingPacket.TickCount = 0; + // Bump up the resend count on this packet Interlocked.Increment(ref outgoingPacket.ResendCount); //Interlocked.Increment(ref Stats.ResentPackets); @@ -393,6 +394,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Flush() { + // FIXME: Implement? + } + + internal void SendPacketFinal(OutgoingPacket outgoingPacket) + { + UDPPacketBuffer buffer = outgoingPacket.Buffer; + byte flags = buffer.Data[0]; + bool isResend = (flags & Helpers.MSG_RESENT) != 0; + bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; + LLUDPClient client = outgoingPacket.Client; + + // Keep track of when this packet was sent out (right now) + outgoingPacket.TickCount = Environment.TickCount; + + #region ACK Appending + + int dataLength = buffer.DataLength; + + // Keep appending ACKs until there is no room left in the packet or there are + // no more ACKs to append + uint ackCount = 0; + uint ack; + while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) + { + Utils.UIntToBytesBig(ack, buffer.Data, dataLength); + dataLength += 4; + ++ackCount; + } + + if (ackCount > 0) + { + // Set the last byte of the packet equal to the number of appended ACKs + buffer.Data[dataLength++] = (byte)ackCount; + // Set the appended ACKs flag on this packet + buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); + } + + buffer.DataLength = dataLength; + + #endregion ACK Appending + + if (!isResend) + { + // Not a resend, assign a new sequence number + uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); + Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); + outgoingPacket.SequenceNumber = sequenceNumber; + + if (isReliable) + { + // Add this packet to the list of ACK responses we are waiting on from the server + client.NeedAcks.Add(outgoingPacket); + } + } + + // Stats tracking + Interlocked.Increment(ref client.PacketsSent); + if (isReliable) + Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); + + // Put the UDP payload on the wire + AsyncBeginSend(buffer); } protected override void PacketReceived(UDPPacketBuffer buffer) @@ -456,8 +519,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion UseCircuitCode Handling - //if (packet.Header.Resent) - // Interlocked.Increment(ref Stats.ReceivedResends); + // Stats tracking + Interlocked.Increment(ref client.PacketsReceived); #region ACK Receiving @@ -581,7 +644,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // Create the LLUDPClient LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); - clients.Add(agentID, client.RemoteEndPoint, client); // Create the LLClientView LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); @@ -589,12 +651,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP clientApi.OnLogout += LogoutHandler; clientApi.OnConnectionClosed += RemoveClient; - // Give LLUDPClient a reference to IClientAPI - client.ClientAPI = clientApi; - // Start the IClientAPI m_scene.ClientManager.Add(circuitCode, clientApi); clientApi.Start(); + + // Give LLUDPClient a reference to IClientAPI + client.ClientAPI = clientApi; + + // Add the new client to our list of tracked clients + clients.Add(agentID, client.RemoteEndPoint, client); } private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) @@ -602,6 +667,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket ackedPacket; if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend) { + // Update stats + Interlocked.Add(ref client.UnackedBytes, -ackedPacket.Buffer.DataLength); + // Calculate the round-trip time for this packet and its ACK int rtt = currentTime - ackedPacket.TickCount; if (rtt > 0) @@ -650,7 +718,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); // Don't let a failure in an individual client thread crash the whole sim. - m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} {1} crashed. Logging them out", client.ClientAPI.Name, client.AgentID); + m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} crashed. Logging them out", client.AgentID); m_log.Error(e.Message, e); try @@ -674,7 +742,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } catch (Exception e2) { - m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.ClientAPI.Name); + m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.AgentID); m_log.Error(e2.Message, e2); } } @@ -715,8 +783,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP elapsed100MS = 0; ++elapsed500MS; } - // Send pings to clients every 2000ms - if (elapsed500MS >= 4) + // Send pings to clients every 5000ms + if (elapsed500MS >= 10) { sendPings = true; elapsed500MS = 0; @@ -730,7 +798,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (resendUnacked) ResendUnacked(client); if (sendAcks) + { SendAcks(client); + client.SendPacketStats(); + } if (sendPings) SendPing(client); } @@ -746,61 +817,5 @@ namespace OpenSim.Region.ClientStack.LindenUDP client.SendLogoutPacket(); RemoveClient(client); } - - internal void SendPacketFinal(OutgoingPacket outgoingPacket) - { - UDPPacketBuffer buffer = outgoingPacket.Buffer; - byte flags = buffer.Data[0]; - bool isResend = (flags & Helpers.MSG_RESENT) != 0; - bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; - LLUDPClient client = outgoingPacket.Client; - - // Keep track of when this packet was sent out (right now) - outgoingPacket.TickCount = Environment.TickCount; - - #region ACK Appending - - int dataLength = buffer.DataLength; - - // Keep appending ACKs until there is no room left in the packet or there are - // no more ACKs to append - uint ackCount = 0; - uint ack; - while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) - { - Utils.UIntToBytesBig(ack, buffer.Data, dataLength); - dataLength += 4; - ++ackCount; - } - - if (ackCount > 0) - { - // Set the last byte of the packet equal to the number of appended ACKs - buffer.Data[dataLength++] = (byte)ackCount; - // Set the appended ACKs flag on this packet - buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); - } - - buffer.DataLength = dataLength; - - #endregion ACK Appending - - if (!isResend) - { - // Not a resend, assign a new sequence number - uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); - Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); - outgoingPacket.SequenceNumber = sequenceNumber; - - if (isReliable) - { - // Add this packet to the list of ACK responses we are waiting on from the server - client.NeedAcks.Add(outgoingPacket); - } - } - - // Put the UDP payload on the wire - AsyncBeginSend(buffer); - } } } -- cgit v1.1 From 77b4abaa251929a4d6079d766f041f997071dc46 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 11:08:11 -0700 Subject: * Removed verbose debug message * Restored HG inventory access which had been lost upon adding a 3rd argument to inventory and asset server handlers * Fixed a stupid bug in the InventoryConnector which was making move items do things twice --- .../ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs | 2 +- .../ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs index bb9a4b2..879cc70 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs @@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset m_log.Info("[RegionAssetService]: Starting..."); - Object[] args = new Object[] { m_Config, MainServer.Instance }; + Object[] args = new Object[] { m_Config, MainServer.Instance, string.Empty }; ServerUtils.LoadPlugin("OpenSim.Server.Handlers.dll:AssetServiceConnector", args); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs index c326818..54c6d89 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs @@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory m_log.Info("[RegionInventoryService]: Starting..."); - Object[] args = new Object[] { m_Config, MainServer.Instance }; + Object[] args = new Object[] { m_Config, MainServer.Instance, String.Empty }; ServerUtils.LoadPlugin("OpenSim.Server.Handlers.dll:InventoryServiceInConnector", args); } -- cgit v1.1 From 61b537215328499155c58f46e6338d459aba87ec Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 12:13:16 -0700 Subject: * Added missing references to prebuild.xml and commented out the LindenUDP tests until a new test harness is written * Clients are no longer disconnected when a packet handler crashes. We'll see how this works out in practice * Added documentation and cleanup, getting ready for the first public push * Deleted an old LLUDP file --- .../Region/ClientStack/LindenUDP/IncomingPacket.cs | 17 ++- .../ClientStack/LindenUDP/LLPacketThrottle.cs | 128 --------------------- .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 56 ++++++++- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 103 +++++++---------- .../Region/ClientStack/LindenUDP/OutgoingPacket.cs | 14 +++ .../Region/ClientStack/LindenUDP/ThrottleRates.cs | 23 ++++ .../LindenUDP/UnackedPacketCollection.cs | 49 +++++++- 7 files changed, 195 insertions(+), 195 deletions(-) delete mode 100644 OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs index dc0d62a..90b3ede 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs @@ -32,11 +32,26 @@ using OpenMetaverse.Packets; namespace OpenSim.Region.ClientStack.LindenUDP { - public struct IncomingPacket + /// + /// Holds a reference to a and a + /// for incoming packets + /// + public sealed class IncomingPacket { /// Client this packet came from public LLUDPClient Client; /// Packet data that has been received public Packet Packet; + + /// + /// Default constructor + /// + /// Reference to the client this packet came from + /// Packet data + public IncomingPacket(LLUDPClient client, Packet packet) + { + Client = client; + Packet = packet; + } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs deleted file mode 100644 index 52effc5..0000000 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public class LLPacketThrottle - { - private readonly int m_maxAllowableThrottle; - private readonly int m_minAllowableThrottle; - private int m_currentThrottle; - private const int m_throttleTimeDivisor = 7; - private int m_currentBitsSent; - private int m_throttleBits; - - /// - /// Value with which to multiply all the throttle fields - /// - private float m_throttleMultiplier; - - public int Max - { - get { return m_maxAllowableThrottle; } - } - - public int Min - { - get { return m_minAllowableThrottle; } - } - - public int Current - { - get { return m_currentThrottle; } - } - - /// - /// Constructor. - /// - /// - /// - /// - /// - /// A parameter that's ends up multiplying all throttle settings. An alternative solution would have been - /// to multiply all the parameters by this before giving them to the constructor. But doing it this way - /// represents the fact that the multiplier is a hack that pumps data to clients much faster than the actual - /// settings that we are given. - /// - public LLPacketThrottle(int min, int max, int throttle, float throttleMultiplier) - { - m_throttleMultiplier = throttleMultiplier; - m_maxAllowableThrottle = max; - m_minAllowableThrottle = min; - m_currentThrottle = throttle; - m_currentBitsSent = 0; - - CalcBits(); - } - - /// - /// Calculate the actual throttle required. - /// - private void CalcBits() - { - m_throttleBits = (int)((float)m_currentThrottle * m_throttleMultiplier / (float)m_throttleTimeDivisor); - } - - public void Reset() - { - m_currentBitsSent = 0; - } - - public bool UnderLimit() - { - return m_currentBitsSent < m_throttleBits; - } - - public int AddBytes(int bytes) - { - m_currentBitsSent += bytes * 8; - return m_currentBitsSent; - } - - public int Throttle - { - get { return m_currentThrottle; } - set - { - if (value < m_minAllowableThrottle) - { - m_currentThrottle = m_minAllowableThrottle; - } - else if (value > m_maxAllowableThrottle) - { - m_currentThrottle = m_maxAllowableThrottle; - } - else - { - m_currentThrottle = value; - } - - CalcBits(); - } - } - } -} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index f2e76d3..871e8e8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -33,16 +33,40 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { + #region Delegates + + /// + /// Fired when updated networking stats are produced for this client + /// + /// Number of incoming packets received since this + /// event was last fired + /// Number of outgoing packets sent since this + /// event was last fired + /// Current total number of bytes in packets we + /// are waiting on ACKs for public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); + /// + /// Fired when the queue for a packet category is empty. This event can be + /// hooked to put more data on the empty queue + /// + /// Category of the packet queue that is empty public delegate void QueueEmpty(ThrottleOutPacketType category); - public class LLUDPClient + #endregion Delegates + + /// + /// Tracks state for a client UDP connection and provides client-specific methods + /// + public sealed class LLUDPClient { /// The number of packet categories to throttle on. If a throttle category is added /// or removed, this number must also change const int THROTTLE_CATEGORY_COUNT = 7; + /// Fired when updated networking stats are produced for this client public event PacketStats OnPacketStats; + /// Fired when the queue for a packet category is empty. This event can be + /// hooked to put more data on the empty queue public event QueueEmpty OnQueueEmpty; /// AgentID for this client @@ -115,6 +139,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// A reference to the LLUDPServer that is managing this client private readonly LLUDPServer udpServer; + /// + /// Default constructor + /// + /// Reference to the UDP server this client is connected to + /// Default throttling rates and maximum throttle limits + /// Parent HTB (hierarchical token bucket) + /// that the child throttles will be governed by + /// Circuit code for this connection + /// AgentID for the connected agent + /// Remote endpoint for this connection public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) { udpServer = server; @@ -144,14 +178,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP RTO = 3000; } + /// + /// Shuts down this client connection + /// public void Shutdown() { + // TODO: Do we need to invalidate the circuit? IsConnected = false; } + /// + /// Gets information about this client connection + /// + /// Information about the client connection public ClientInfo GetClientInfo() { - // TODO: This data structure is wrong in so many ways + // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists + // of pending and needed ACKs for every client every time some method wants information about + // this connection is a recipe for poor performance ClientInfo info = new ClientInfo(); info.pendingAcks = new Dictionary(); info.needAck = new Dictionary(); @@ -169,8 +213,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP return info; } + /// + /// Modifies the UDP throttles + /// + /// New throttling values public void SetClientInfo(ClientInfo info) { + // TODO: Allowing throttles to be manually set from this function seems like a reasonable + // idea. On the other hand, letting external code manipulate our ACK accounting is not + // going to happen + throw new NotImplementedException(); } public string GetStats() diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 38890da..c0a84a8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -41,7 +41,10 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { - public class LLUDPServerShim : IClientNetworkServer + /// + /// A shim around LLUDPServer that implements the IClientNetworkServer interface + /// + public sealed class LLUDPServerShim : IClientNetworkServer { LLUDPServer m_udpServer; @@ -80,6 +83,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// + /// The LLUDP server for a region. This handles incoming and outgoing + /// packets for all UDP connections to the region + /// public class LLUDPServer : UDPBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -152,6 +159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public new void Stop() { + m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); base.Stop(); } @@ -591,11 +599,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Type != PacketType.PacketAck) { // Inbox insertion - IncomingPacket incomingPacket; - incomingPacket.Client = client; - incomingPacket.Packet = packet; - - packetInbox.Enqueue(incomingPacket); + packetInbox.Enqueue(new IncomingPacket(client, packet)); } } @@ -683,7 +687,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - IncomingPacket incomingPacket = default(IncomingPacket); + IncomingPacket incomingPacket = null; while (base.IsRunning) { @@ -696,59 +700,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP packetInbox.Clear(); } - private void ProcessInPacket(object state) - { - IncomingPacket incomingPacket = (IncomingPacket)state; - Packet packet = incomingPacket.Packet; - LLUDPClient client = incomingPacket.Client; - - if (packet != null && client != null) - { - try - { - client.ClientAPI.ProcessInPacket(packet); - } - catch (ThreadAbortException) - { - throw; - } - catch (Exception e) - { - if (StatsManager.SimExtraStats != null) - StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); - - // Don't let a failure in an individual client thread crash the whole sim. - m_log.ErrorFormat("[LLUDPSERVER]: Client thread for {0} crashed. Logging them out", client.AgentID); - m_log.Error(e.Message, e); - - try - { - // Make an attempt to alert the user that their session has crashed - AgentAlertMessagePacket alert = client.ClientAPI.BuildAgentAlertPacket( - "Unfortunately the session for this client on the server has crashed.\n" + - "Any further actions taken will not be processed.\n" + - "Please relog", true); - - SendPacket(client, alert, ThrottleOutPacketType.Unknown, false); - - // TODO: There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to - // listeners yet, though. - client.ClientAPI.SendLogoutPacket(); - RemoveClient(client.ClientAPI); - } - catch (ThreadAbortException) - { - throw; - } - catch (Exception e2) - { - m_log.Error("[LLUDPSERVER]: Further exception thrown on forced session logout for " + client.AgentID); - m_log.Error(e2.Message, e2); - } - } - } - } - private void OutgoingPacketHandler() { // Set this culture for the thread that outgoing packets are sent @@ -812,6 +763,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + private void ProcessInPacket(object state) + { + IncomingPacket incomingPacket = (IncomingPacket)state; + Packet packet = incomingPacket.Packet; + LLUDPClient client = incomingPacket.Client; + + // Sanity check + if (packet == null || client == null || client.ClientAPI == null) + { + m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"", + packet, client, (client != null) ? client.ClientAPI : null); + } + + try + { + // Process this packet + client.ClientAPI.ProcessInPacket(packet); + } + catch (ThreadAbortException) + { + // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down + m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); + Stop(); + } + catch (Exception e) + { + // Don't let a failure in an individual client thread crash the whole sim. + m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", client.AgentID, packet.Type); + m_log.Error(e.Message, e); + } + } + private void LogoutHandler(IClientAPI client) { client.SendLogoutPacket(); diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 69b0c5f..1a1a1cb 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -31,6 +31,13 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { + /// + /// Holds a reference to the this packet is + /// destined for, along with the serialized packet data, sequence number + /// (if this is a resend), number of times this packet has been resent, + /// the time of the last resend, and the throttling category for this + /// packet + /// public sealed class OutgoingPacket { /// Client this packet is destined for @@ -46,6 +53,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Category this packet belongs to public ThrottleOutPacketType Category; + /// + /// Default constructor + /// + /// Reference to the client this packet is destined for + /// Serialized packet data. If the flags or sequence number + /// need to be updated, they will be injected directly into this binary buffer + /// Throttling category for this packet public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category) { Client = client; diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs index ffa20d5..858a03c 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs @@ -30,24 +30,47 @@ using Nini.Config; namespace OpenSim.Region.ClientStack.LindenUDP { + /// + /// Holds drip rates and maximum burst rates for throttling with hierarchical + /// token buckets. The maximum burst rates set here are hard limits and can + /// not be overridden by client requests + /// public sealed class ThrottleRates { + /// Drip rate for resent packets public int Resend; + /// Drip rate for terrain packets public int Land; + /// Drip rate for wind packets public int Wind; + /// Drip rate for cloud packets public int Cloud; + /// Drip rate for task (state and transaction) packets public int Task; + /// Drip rate for texture packets public int Texture; + /// Drip rate for asset packets public int Asset; + /// Maximum burst rate for resent packets public int ResendLimit; + /// Maximum burst rate for land packets public int LandLimit; + /// Maximum burst rate for wind packets public int WindLimit; + /// Maximum burst rate for cloud packets public int CloudLimit; + /// Maximum burst rate for task (state and transaction) packets public int TaskLimit; + /// Maximum burst rate for texture packets public int TextureLimit; + /// Maximum burst rate for asset packets public int AssetLimit; + /// + /// Default constructor + /// + /// Config source to load defaults from public ThrottleRates(IConfigSource config) { try diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 16c0035..b7df84d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -32,19 +32,34 @@ using OpenMetaverse; namespace OpenSim.Region.ClientStack.LindenUDP { + /// + /// Special collection that is optimized for tracking unacknowledged packets + /// public sealed class UnackedPacketCollection { + /// Synchronization primitive. A lock must be acquired on this + /// object before calling any of the unsafe methods public object SyncRoot = new object(); - SortedDictionary packets; + /// Holds the actual unacked packet data, sorted by sequence number + private SortedDictionary packets = new SortedDictionary(); + /// Gets the total number of unacked packets public int Count { get { return packets.Count; } } + /// + /// Default constructor + /// public UnackedPacketCollection() { - packets = new SortedDictionary(); } + /// + /// Add an unacked packet to the collection + /// + /// Packet that is awaiting acknowledgement + /// True if the packet was successfully added, false if the + /// packet already existed in the collection public bool Add(OutgoingPacket packet) { lock (SyncRoot) @@ -58,11 +73,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// + /// Removes a packet from the collection without attempting to obtain a + /// lock first + /// + /// Sequence number of the packet to remove + /// True if the packet was found and removed, otherwise false public bool RemoveUnsafe(uint sequenceNumber) { return packets.Remove(sequenceNumber); } + /// + /// Removes a packet from the collection without attempting to obtain a + /// lock first + /// + /// Sequence number of the packet to remove + /// Returns the removed packet + /// True if the packet was found and removed, otherwise false public bool RemoveUnsafe(uint sequenceNumber, out OutgoingPacket packet) { if (packets.TryGetValue(sequenceNumber, out packet)) @@ -74,6 +102,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return false; } + /// + /// Gets the packet with the lowest sequence number + /// + /// The packet with the lowest sequence number, or null if the + /// collection is empty public OutgoingPacket GetOldest() { lock (SyncRoot) @@ -83,7 +116,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public List GetExpiredPackets(int timeout) + /// + /// Returns a list of all of the packets with a TickCount older than + /// the specified timeout + /// + /// Number of ticks (milliseconds) before a + /// packet is considered expired + /// A list of all expired packets according to the given + /// expiration timeout + public List GetExpiredPackets(int timeoutMS) { List expiredPackets = null; @@ -95,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.TickCount == 0) continue; - if (now - packet.TickCount >= timeout) + if (now - packet.TickCount >= timeoutMS) { if (expiredPackets == null) expiredPackets = new List(); -- cgit v1.1 From 25676ac5cf61a35f1e6e3cd7f7aba95c31bdf494 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 13:39:10 -0700 Subject: * Added a sanity check for Mono before trying to enumerate over an empty SortedDictionary * Changed the order of a log line from DotNetEngine so you can tell whether or not it is actually loading --- OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | 3 +++ OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index b7df84d..6ecc0c8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -111,6 +111,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (SyncRoot) { + if (packets.Count == 0) + return null; + using (SortedDictionary.ValueCollection.Enumerator e = packets.Values.GetEnumerator()) return e.Current; } diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs index 3c91b29..9806218 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -129,10 +129,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine public void AddRegion(Scene Sceneworld) { - m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); - - m_Scene = Sceneworld; - // Make sure we have config if (ConfigSource.Configs[ScriptEngineName] == null) ConfigSource.AddConfig(ScriptEngineName); @@ -143,6 +139,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine if (!m_enabled) return; + m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); + + m_Scene = Sceneworld; + // Create all objects we'll be using m_EventQueueManager = new EventQueueManager(this); m_EventManager = new EventManager(this, true); -- cgit v1.1 From eb205ef4f02852ccb62103d307e70de80270f795 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 14:07:04 -0700 Subject: Added a debug line for nebadon --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b25be8e..ceff28b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1446,6 +1446,9 @@ namespace OpenSim.Region.Framework.Scenes m_log.Info("[SCENE]: Loading objects from datastore"); List PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID); + + m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count + " objects from the datastore"); + foreach (SceneObjectGroup group in PrimsFromDB) { if (group.RootPart == null) -- cgit v1.1 From 74fe284a20976923ab9112e7c32249aa59392d5f Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 14:50:46 -0700 Subject: Trying Melanie's fix --- OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 6ecc0c8..39882fb 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -111,11 +111,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (SyncRoot) { - if (packets.Count == 0) - return null; + OutgoingPacket p; using (SortedDictionary.ValueCollection.Enumerator e = packets.Values.GetEnumerator()) - return e.Current; + p = e.Current; + + return p; } } -- cgit v1.1 From 9cb5db362123dda7d10ce2500926e2d3db9765f9 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 15:08:09 -0700 Subject: Applying the real fix (thank you for tracking that MSDN doc down Melanie) --- .../Region/ClientStack/LindenUDP/UnackedPacketCollection.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 39882fb..195ca57 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -111,12 +111,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (SyncRoot) { - OutgoingPacket p; - using (SortedDictionary.ValueCollection.Enumerator e = packets.Values.GetEnumerator()) - p = e.Current; - - return p; + { + if (e.MoveNext()) + return e.Current; + else + return null; + } } } -- cgit v1.1 From e992ca025571a891333a57012c2cd4419b6581e5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 15:39:53 -0700 Subject: Rewrote parts of the code that were double-locking different objects. This is about half of the code base reviewed. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 116 ++++++++++++--------- .../CoreModules/Avatar/Friends/FriendsModule.cs | 42 ++++---- .../Avatar/InstantMessage/PresenceModule.cs | 11 +- .../Inventory/Transfer/InventoryTransferModule.cs | 15 +-- .../Scripting/EMailModules/EmailModule.cs | 37 +++---- .../CoreModules/World/Land/LandManagementModule.cs | 8 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 36 ++++--- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 36 ++++--- 8 files changed, 174 insertions(+), 127 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 0052729..fe37a08 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3122,6 +3122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP objectData.TextureAnim = textureanim; } + bool doUpdate = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0) @@ -3130,8 +3131,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdates.Add(objectData); if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - ProcessPrimFullUpdates(this, null); + doUpdate = true; } + if (doUpdate) + ProcessPrimFullUpdates(this, null); } void HandleQueueEmpty(ThrottleOutPacketType queue) @@ -3152,35 +3155,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) { + bool stopTimer = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - - return; - } + stopTimer = true; + } + if (stopTimer) + { + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + return; + } - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + lock (m_primFullUpdates) + { for (count = 0 ; count < max ; count++) { int length = 0; @@ -3204,9 +3212,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); + stopTimer = true; } + + if (stopTimer) + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); } /// @@ -3225,6 +3236,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); + bool doUpdate = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) @@ -3233,43 +3245,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primTerseUpdates.Add(objectData); if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - ProcessPrimTerseUpdates(this, null); + doUpdate = true; } + if (doUpdate) + ProcessPrimTerseUpdates(this, null); } void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { + bool stopTimer = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) - { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + stopTimer = true; + } + if (stopTimer) + { + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); - return; - } + return; + } - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - for (count = 0 ; count < max ; count++) + lock (m_primTerseUpdates) + { + for (count = 0; count < max; count++) { int length = 0; m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); @@ -3294,9 +3314,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); if (m_primTerseUpdates.Count == 0) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + stopTimer = true; } + if (stopTimer) + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); } public void FlushPrimUpdates() diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index fc7d63a..4abad81 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -442,42 +442,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private ScenePresence GetRootPresenceFromAgentID(UUID AgentID) { - ScenePresence returnAgent = null; + List scenes = null; lock (m_scenes) + scenes = new List(m_scenes.Values); + + ScenePresence returnAgent = null; + ScenePresence queryagent = null; + foreach (Scene scene in scenes) { - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) + if (!queryagent.IsChildAgent) { - if (!queryagent.IsChildAgent) - { - returnAgent = queryagent; - break; - } + returnAgent = queryagent; + break; } } } + return returnAgent; } private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID) { - ScenePresence returnAgent = null; + List scenes = null; lock (m_scenes) + scenes = new List(m_scenes.Values); + + ScenePresence returnAgent = null; + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) { - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) - { - returnAgent = queryagent; - break; - } + returnAgent = queryagent; + break; } } + return returnAgent; } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs index ad05bab..42dd7ff 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs @@ -290,13 +290,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // get the agent. This should work every time, as we just got a packet from it ScenePresence agent = null; + List scenes = null; lock (m_Scenes) + scenes = new List(m_Scenes); + + foreach (Scene scene in scenes) { - foreach (Scene scene in m_Scenes) - { - agent = scene.GetScenePresence(agentID); - if (agent != null) break; - } + agent = scene.GetScenePresence(agentID); + if (agent != null) break; } // just to be paranoid... diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index d9a021f..e6e0483 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -111,16 +111,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private Scene FindClientScene(UUID agentId) { + List scenes = null; lock (m_Scenelist) + scenes = new List(m_Scenelist); + + foreach (Scene scene in scenes) { - foreach (Scene scene in m_Scenelist) + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) { - ScenePresence presence = scene.GetScenePresence(agentId); - if (presence != null) - { - if (!presence.IsChildAgent) - return scene; - } + if (!presence.IsChildAgent) + return scene; } } return null; diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index 83f004d..f9f01fe 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -198,19 +198,20 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName) { + List scenes = null; lock (m_Scenes) + scenes = new List(m_Scenes.Values); + + foreach (Scene s in scenes) { - foreach (Scene s in m_Scenes.Values) + SceneObjectPart part = s.GetSceneObjectPart(objectID); + if (part != null) { - SceneObjectPart part = s.GetSceneObjectPart(objectID); - if (part != null) - { - ObjectRegionName = s.RegionInfo.RegionName; - uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); - uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); - ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; - return part; - } + ObjectRegionName = s.RegionInfo.RegionName; + uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); + uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); + ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; + return part; } } ObjectRegionName = string.Empty; @@ -363,6 +364,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules public Email GetNextEmail(UUID objectID, string sender, string subject) { List queue = null; + List removal = new List(); lock (m_LastGetEmailCall) { @@ -375,7 +377,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules // Hopefully this isn't too time consuming. If it is, we can always push it into a worker thread. DateTime now = DateTime.Now; - List removal = new List(); foreach (UUID uuid in m_LastGetEmailCall.Keys) { if ((now - m_LastGetEmailCall[uuid]) > m_QueueTimeout) @@ -383,15 +384,15 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules removal.Add(uuid); } } + } - foreach (UUID remove in removal) - { + foreach (UUID remove in removal) + { + lock (m_LastGetEmailCall) m_LastGetEmailCall.Remove(remove); - lock (m_MailQueues) - { - m_MailQueues.Remove(remove); - } - } + + lock (m_MailQueues) + m_MailQueues.Remove(remove); } lock (m_MailQueues) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index d2b5cb1..0fed1bd 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -187,14 +187,16 @@ namespace OpenSim.Region.CoreModules.World.Land LandData newData = data.Copy(); newData.LocalID = local_id; + ILandObject land = null; lock (m_landList) { if (m_landList.ContainsKey(local_id)) { m_landList[local_id].LandData = newData; - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); + land = m_landList[local_id]; } } + m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land); } public bool AllowedForcefulBans @@ -504,6 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land.localID of the peice of land to remove. public void removeLandObject(int local_id) { + UUID id = UUID.Zero; lock (m_landList) { for (int x = 0; x < 64; x++) @@ -520,9 +523,10 @@ namespace OpenSim.Region.CoreModules.World.Land } } - m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); + id = m_landList[local_id].LandData.GlobalID; m_landList.Remove(local_id); } + m_scene.EventManager.TriggerLandObjectRemoved(id); } private void performFinalLandJoin(ILandObject master, ILandObject slave) diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 5b571c7..df9473d 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -122,12 +122,13 @@ namespace OpenSim.Region.Framework.Scenes public bool InventoryDeQueueAndDelete() { DeleteToInventoryHolder x = null; + int left = 0; try { lock (m_inventoryDeletes) { - int left = m_inventoryDeletes.Count; + left = m_inventoryDeletes.Count; if (left > 0) { x = m_inventoryDeletes.Dequeue(); @@ -136,23 +137,26 @@ namespace OpenSim.Region.Framework.Scenes m_inventoryDeletes.Enqueue(x); return true; } + } + } - m_log.DebugFormat( - "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); - - try - { - m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); - if (x.permissionToDelete) - m_scene.DeleteSceneObject(x.objectGroup, false); - } - catch (Exception e) - { - m_log.DebugFormat("Exception background sending object: " + e); - } - - return true; + if (left > 0) + { + m_log.DebugFormat( + "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); + + try + { + m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); + if (x.permissionToDelete) + m_scene.DeleteSceneObject(x.objectGroup, false); + } + catch (Exception e) + { + m_log.DebugFormat("Exception background sending object: " + e); } + + return true; } } catch (Exception e) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 54ac792..20b3b5c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -297,34 +297,44 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); + List parts = null; + bool found = false; lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) { + found = true; Entities.Add(sceneObject); m_numPrim += sceneObject.Children.Count; if (attachToBackup) sceneObject.AttachToBackup(); - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); - - lock (m_dictionary_lock) + parts = new List(sceneObject.Children.Values); + + } + } + + if (found) + { + lock (m_dictionary_lock) + { + SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + foreach (SceneObjectPart part in parts) { - SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; - foreach (SceneObjectPart part in sceneObject.Children.Values) - { - SceneObjectGroupsByFullID[part.UUID] = sceneObject; - SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; - } + SceneObjectGroupsByFullID[part.UUID] = sceneObject; + SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } - - return true; } + + if (OnObjectCreate != null) + OnObjectCreate(sceneObject); + + return true; } + return false; } -- cgit v1.1 From 7199976d486eccb101b2942fe93a16df444bf73a Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 15:51:56 -0700 Subject: Checks the number of ThreadPool and IOCP threads on startup and bumps up the numbers to .NET defaults of 500/1000 if need be --- OpenSim/Region/Application/Application.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 33b01e5..555baa4 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -91,6 +91,18 @@ namespace OpenSim m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); } + // Increase the number of IOCP threads available. Mono defaults to a tragically low number + int workerThreads, iocpThreads; + System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads); + if (workerThreads < 500 || iocpThreads < 1000) + { + workerThreads = 500; + iocpThreads = 1000; + m_log.Info("[OPENSIM MAIN]: Bumping up to 500 worker threads and 1000 IOCP threads"); + System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads); + } + // Check if the system is compatible with OpenSimulator. // Ensures that the minimum system requirements are met m_log.Info("Performing compatibility checks... "); -- cgit v1.1 From 312438f145aa7286df365e37df423e743dd85db0 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Tue, 6 Oct 2009 15:55:39 -0700 Subject: Commented noisy debugging about packet splitting --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index c0a84a8..2c5ad85 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -210,8 +210,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; - if (packetCount > 1) - m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); + //if (packetCount > 1) + // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { @@ -250,8 +250,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; - if (packetCount > 1) - m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); + //if (packetCount > 1) + // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { -- cgit v1.1 From 9618c196c274fefda4437eff6d25c7a12e7a3ee1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 7 Oct 2009 01:44:36 +0100 Subject: Revert "Merging in diva's locking fixes" This reverts commit 832cc685138b2244529f10b54b373c34adb4a633. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 116 +++++++++------------ .../CoreModules/Avatar/Friends/FriendsModule.cs | 42 ++++---- .../Avatar/InstantMessage/PresenceModule.cs | 11 +- .../Inventory/Transfer/InventoryTransferModule.cs | 15 ++- .../Scripting/EMailModules/EmailModule.cs | 37 ++++--- .../CoreModules/World/Land/LandManagementModule.cs | 8 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 36 +++---- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 36 +++---- 8 files changed, 127 insertions(+), 174 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 60dab5f..84e705a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3546,7 +3546,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP objectData.TextureAnim = textureanim; } - bool doUpdate = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0) @@ -3555,10 +3554,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdates.Add(objectData); if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - doUpdate = true; + ProcessPrimFullUpdates(this, null); } - if (doUpdate) - ProcessPrimFullUpdates(this, null); } void HandleQueueEmpty(ThrottleOutPacketType queue) @@ -3579,40 +3576,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) { - bool stopTimer = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - stopTimer = true; - } - if (stopTimer) - { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - return; - } + { + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + + return; + } - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - lock (m_primFullUpdates) - { for (count = 0 ; count < max ; count++) { int length = 0; @@ -3636,12 +3628,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task); if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - stopTimer = true; + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); } - - if (stopTimer) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); } /// @@ -3660,7 +3649,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); - bool doUpdate = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) @@ -3669,51 +3657,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primTerseUpdates.Add(objectData); if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - doUpdate = true; + ProcessPrimTerseUpdates(this, null); } - if (doUpdate) - ProcessPrimTerseUpdates(this, null); } void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { - bool stopTimer = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) - stopTimer = true; - } - if (stopTimer) - { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + { + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); - return; - } + return; + } - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - lock (m_primTerseUpdates) - { - for (count = 0; count < max; count++) + for (count = 0 ; count < max ; count++) { int length = 0; m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); @@ -3738,11 +3718,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task); if (m_primTerseUpdates.Count == 0) - stopTimer = true; + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); } - if (stopTimer) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); } public void FlushPrimUpdates() diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4abad81..fc7d63a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -442,46 +442,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private ScenePresence GetRootPresenceFromAgentID(UUID AgentID) { - List scenes = null; - lock (m_scenes) - scenes = new List(m_scenes.Values); - ScenePresence returnAgent = null; - ScenePresence queryagent = null; - foreach (Scene scene in scenes) + lock (m_scenes) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) { - if (!queryagent.IsChildAgent) + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) { - returnAgent = queryagent; - break; + if (!queryagent.IsChildAgent) + { + returnAgent = queryagent; + break; + } } } } - return returnAgent; } private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID) { - List scenes = null; - lock (m_scenes) - scenes = new List(m_scenes.Values); - ScenePresence returnAgent = null; - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) + lock (m_scenes) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) { - returnAgent = queryagent; - break; + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) + { + returnAgent = queryagent; + break; + } } } - return returnAgent; } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs index 42dd7ff..ad05bab 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs @@ -290,14 +290,13 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // get the agent. This should work every time, as we just got a packet from it ScenePresence agent = null; - List scenes = null; lock (m_Scenes) - scenes = new List(m_Scenes); - - foreach (Scene scene in scenes) { - agent = scene.GetScenePresence(agentID); - if (agent != null) break; + foreach (Scene scene in m_Scenes) + { + agent = scene.GetScenePresence(agentID); + if (agent != null) break; + } } // just to be paranoid... diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index e6e0483..d9a021f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -111,17 +111,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private Scene FindClientScene(UUID agentId) { - List scenes = null; lock (m_Scenelist) - scenes = new List(m_Scenelist); - - foreach (Scene scene in scenes) { - ScenePresence presence = scene.GetScenePresence(agentId); - if (presence != null) + foreach (Scene scene in m_Scenelist) { - if (!presence.IsChildAgent) - return scene; + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return scene; + } } } return null; diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index f9f01fe..83f004d 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -198,20 +198,19 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName) { - List scenes = null; lock (m_Scenes) - scenes = new List(m_Scenes.Values); - - foreach (Scene s in scenes) { - SceneObjectPart part = s.GetSceneObjectPart(objectID); - if (part != null) + foreach (Scene s in m_Scenes.Values) { - ObjectRegionName = s.RegionInfo.RegionName; - uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); - uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); - ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; - return part; + SceneObjectPart part = s.GetSceneObjectPart(objectID); + if (part != null) + { + ObjectRegionName = s.RegionInfo.RegionName; + uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); + uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); + ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; + return part; + } } } ObjectRegionName = string.Empty; @@ -364,7 +363,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules public Email GetNextEmail(UUID objectID, string sender, string subject) { List queue = null; - List removal = new List(); lock (m_LastGetEmailCall) { @@ -377,6 +375,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules // Hopefully this isn't too time consuming. If it is, we can always push it into a worker thread. DateTime now = DateTime.Now; + List removal = new List(); foreach (UUID uuid in m_LastGetEmailCall.Keys) { if ((now - m_LastGetEmailCall[uuid]) > m_QueueTimeout) @@ -384,15 +383,15 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules removal.Add(uuid); } } - } - foreach (UUID remove in removal) - { - lock (m_LastGetEmailCall) + foreach (UUID remove in removal) + { m_LastGetEmailCall.Remove(remove); - - lock (m_MailQueues) - m_MailQueues.Remove(remove); + lock (m_MailQueues) + { + m_MailQueues.Remove(remove); + } + } } lock (m_MailQueues) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 0fed1bd..d2b5cb1 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -187,16 +187,14 @@ namespace OpenSim.Region.CoreModules.World.Land LandData newData = data.Copy(); newData.LocalID = local_id; - ILandObject land = null; lock (m_landList) { if (m_landList.ContainsKey(local_id)) { m_landList[local_id].LandData = newData; - land = m_landList[local_id]; + m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); } } - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land); } public bool AllowedForcefulBans @@ -506,7 +504,6 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land.localID of the peice of land to remove. public void removeLandObject(int local_id) { - UUID id = UUID.Zero; lock (m_landList) { for (int x = 0; x < 64; x++) @@ -523,10 +520,9 @@ namespace OpenSim.Region.CoreModules.World.Land } } - id = m_landList[local_id].LandData.GlobalID; + m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); m_landList.Remove(local_id); } - m_scene.EventManager.TriggerLandObjectRemoved(id); } private void performFinalLandJoin(ILandObject master, ILandObject slave) diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index df9473d..5b571c7 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -122,13 +122,12 @@ namespace OpenSim.Region.Framework.Scenes public bool InventoryDeQueueAndDelete() { DeleteToInventoryHolder x = null; - int left = 0; try { lock (m_inventoryDeletes) { - left = m_inventoryDeletes.Count; + int left = m_inventoryDeletes.Count; if (left > 0) { x = m_inventoryDeletes.Dequeue(); @@ -137,26 +136,23 @@ namespace OpenSim.Region.Framework.Scenes m_inventoryDeletes.Enqueue(x); return true; } - } - } - if (left > 0) - { - m_log.DebugFormat( - "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); - - try - { - m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); - if (x.permissionToDelete) - m_scene.DeleteSceneObject(x.objectGroup, false); - } - catch (Exception e) - { - m_log.DebugFormat("Exception background sending object: " + e); + m_log.DebugFormat( + "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); + + try + { + m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); + if (x.permissionToDelete) + m_scene.DeleteSceneObject(x.objectGroup, false); + } + catch (Exception e) + { + m_log.DebugFormat("Exception background sending object: " + e); + } + + return true; } - - return true; } } catch (Exception e) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 20b3b5c..54ac792 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -297,44 +297,34 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); - List parts = null; - bool found = false; lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) { - found = true; Entities.Add(sceneObject); m_numPrim += sceneObject.Children.Count; if (attachToBackup) sceneObject.AttachToBackup(); - parts = new List(sceneObject.Children.Values); - - } - } - - if (found) - { - lock (m_dictionary_lock) - { - SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; - foreach (SceneObjectPart part in parts) + if (OnObjectCreate != null) + OnObjectCreate(sceneObject); + + lock (m_dictionary_lock) { - SceneObjectGroupsByFullID[part.UUID] = sceneObject; - SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; + SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + SceneObjectGroupsByFullID[part.UUID] = sceneObject; + SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; + } } - } - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); - - return true; + return true; + } } - return false; } -- cgit v1.1 From 89d23a1fa23cb191e7ebde047311adcadf3b2e45 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 7 Oct 2009 01:45:49 +0100 Subject: Revert "Rewrote parts of the code that were double-locking different objects. This is about half of the code base reviewed." This reverts commit e992ca025571a891333a57012c2cd4419b6581e5. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 116 +++++++++------------ .../CoreModules/Avatar/Friends/FriendsModule.cs | 42 ++++---- .../Avatar/InstantMessage/PresenceModule.cs | 11 +- .../Inventory/Transfer/InventoryTransferModule.cs | 15 ++- .../Scripting/EMailModules/EmailModule.cs | 37 ++++--- .../CoreModules/World/Land/LandManagementModule.cs | 8 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 36 +++---- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 36 +++---- 8 files changed, 127 insertions(+), 174 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index fe37a08..0052729 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3122,7 +3122,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP objectData.TextureAnim = textureanim; } - bool doUpdate = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0) @@ -3131,10 +3130,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdates.Add(objectData); if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - doUpdate = true; + ProcessPrimFullUpdates(this, null); } - if (doUpdate) - ProcessPrimFullUpdates(this, null); } void HandleQueueEmpty(ThrottleOutPacketType queue) @@ -3155,40 +3152,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) { - bool stopTimer = false; lock (m_primFullUpdates) { if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - stopTimer = true; - } - if (stopTimer) - { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - return; - } + { + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + + return; + } - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - lock (m_primFullUpdates) - { for (count = 0 ; count < max ; count++) { int length = 0; @@ -3212,12 +3204,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - stopTimer = true; + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); } - - if (stopTimer) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); } /// @@ -3236,7 +3225,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); - bool doUpdate = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) @@ -3245,51 +3233,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primTerseUpdates.Add(objectData); if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - doUpdate = true; + ProcessPrimTerseUpdates(this, null); } - if (doUpdate) - ProcessPrimTerseUpdates(this, null); } void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { - bool stopTimer = false; lock (m_primTerseUpdates) { if (m_primTerseUpdates.Count == 0) - stopTimer = true; - } - if (stopTimer) - { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); + { + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); - return; - } + return; + } - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; - int count = 0; - int size = 0; + int count = 0; + int size = 0; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - lock (m_primTerseUpdates) - { - for (count = 0; count < max; count++) + for (count = 0 ; count < max ; count++) { int length = 0; m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); @@ -3314,11 +3294,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); if (m_primTerseUpdates.Count == 0) - stopTimer = true; + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); } - if (stopTimer) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); } public void FlushPrimUpdates() diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4abad81..fc7d63a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -442,46 +442,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private ScenePresence GetRootPresenceFromAgentID(UUID AgentID) { - List scenes = null; - lock (m_scenes) - scenes = new List(m_scenes.Values); - ScenePresence returnAgent = null; - ScenePresence queryagent = null; - foreach (Scene scene in scenes) + lock (m_scenes) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) { - if (!queryagent.IsChildAgent) + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) { - returnAgent = queryagent; - break; + if (!queryagent.IsChildAgent) + { + returnAgent = queryagent; + break; + } } } } - return returnAgent; } private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID) { - List scenes = null; - lock (m_scenes) - scenes = new List(m_scenes.Values); - ScenePresence returnAgent = null; - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) + lock (m_scenes) { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) { - returnAgent = queryagent; - break; + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) + { + returnAgent = queryagent; + break; + } } } - return returnAgent; } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs index 42dd7ff..ad05bab 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs @@ -290,14 +290,13 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // get the agent. This should work every time, as we just got a packet from it ScenePresence agent = null; - List scenes = null; lock (m_Scenes) - scenes = new List(m_Scenes); - - foreach (Scene scene in scenes) { - agent = scene.GetScenePresence(agentID); - if (agent != null) break; + foreach (Scene scene in m_Scenes) + { + agent = scene.GetScenePresence(agentID); + if (agent != null) break; + } } // just to be paranoid... diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index e6e0483..d9a021f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -111,17 +111,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private Scene FindClientScene(UUID agentId) { - List scenes = null; lock (m_Scenelist) - scenes = new List(m_Scenelist); - - foreach (Scene scene in scenes) { - ScenePresence presence = scene.GetScenePresence(agentId); - if (presence != null) + foreach (Scene scene in m_Scenelist) { - if (!presence.IsChildAgent) - return scene; + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return scene; + } } } return null; diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index f9f01fe..83f004d 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -198,20 +198,19 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName) { - List scenes = null; lock (m_Scenes) - scenes = new List(m_Scenes.Values); - - foreach (Scene s in scenes) { - SceneObjectPart part = s.GetSceneObjectPart(objectID); - if (part != null) + foreach (Scene s in m_Scenes.Values) { - ObjectRegionName = s.RegionInfo.RegionName; - uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); - uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); - ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; - return part; + SceneObjectPart part = s.GetSceneObjectPart(objectID); + if (part != null) + { + ObjectRegionName = s.RegionInfo.RegionName; + uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); + uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); + ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; + return part; + } } } ObjectRegionName = string.Empty; @@ -364,7 +363,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules public Email GetNextEmail(UUID objectID, string sender, string subject) { List queue = null; - List removal = new List(); lock (m_LastGetEmailCall) { @@ -377,6 +375,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules // Hopefully this isn't too time consuming. If it is, we can always push it into a worker thread. DateTime now = DateTime.Now; + List removal = new List(); foreach (UUID uuid in m_LastGetEmailCall.Keys) { if ((now - m_LastGetEmailCall[uuid]) > m_QueueTimeout) @@ -384,15 +383,15 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules removal.Add(uuid); } } - } - foreach (UUID remove in removal) - { - lock (m_LastGetEmailCall) + foreach (UUID remove in removal) + { m_LastGetEmailCall.Remove(remove); - - lock (m_MailQueues) - m_MailQueues.Remove(remove); + lock (m_MailQueues) + { + m_MailQueues.Remove(remove); + } + } } lock (m_MailQueues) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 0fed1bd..d2b5cb1 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -187,16 +187,14 @@ namespace OpenSim.Region.CoreModules.World.Land LandData newData = data.Copy(); newData.LocalID = local_id; - ILandObject land = null; lock (m_landList) { if (m_landList.ContainsKey(local_id)) { m_landList[local_id].LandData = newData; - land = m_landList[local_id]; + m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); } } - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land); } public bool AllowedForcefulBans @@ -506,7 +504,6 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land.localID of the peice of land to remove. public void removeLandObject(int local_id) { - UUID id = UUID.Zero; lock (m_landList) { for (int x = 0; x < 64; x++) @@ -523,10 +520,9 @@ namespace OpenSim.Region.CoreModules.World.Land } } - id = m_landList[local_id].LandData.GlobalID; + m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); m_landList.Remove(local_id); } - m_scene.EventManager.TriggerLandObjectRemoved(id); } private void performFinalLandJoin(ILandObject master, ILandObject slave) diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index df9473d..5b571c7 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -122,13 +122,12 @@ namespace OpenSim.Region.Framework.Scenes public bool InventoryDeQueueAndDelete() { DeleteToInventoryHolder x = null; - int left = 0; try { lock (m_inventoryDeletes) { - left = m_inventoryDeletes.Count; + int left = m_inventoryDeletes.Count; if (left > 0) { x = m_inventoryDeletes.Dequeue(); @@ -137,26 +136,23 @@ namespace OpenSim.Region.Framework.Scenes m_inventoryDeletes.Enqueue(x); return true; } - } - } - if (left > 0) - { - m_log.DebugFormat( - "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); - - try - { - m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); - if (x.permissionToDelete) - m_scene.DeleteSceneObject(x.objectGroup, false); - } - catch (Exception e) - { - m_log.DebugFormat("Exception background sending object: " + e); + m_log.DebugFormat( + "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); + + try + { + m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); + if (x.permissionToDelete) + m_scene.DeleteSceneObject(x.objectGroup, false); + } + catch (Exception e) + { + m_log.DebugFormat("Exception background sending object: " + e); + } + + return true; } - - return true; } } catch (Exception e) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 20b3b5c..54ac792 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -297,44 +297,34 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); - List parts = null; - bool found = false; lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) { - found = true; Entities.Add(sceneObject); m_numPrim += sceneObject.Children.Count; if (attachToBackup) sceneObject.AttachToBackup(); - parts = new List(sceneObject.Children.Values); - - } - } - - if (found) - { - lock (m_dictionary_lock) - { - SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; - foreach (SceneObjectPart part in parts) + if (OnObjectCreate != null) + OnObjectCreate(sceneObject); + + lock (m_dictionary_lock) { - SceneObjectGroupsByFullID[part.UUID] = sceneObject; - SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; + SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + SceneObjectGroupsByFullID[part.UUID] = sceneObject; + SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; + } } - } - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); - - return true; + return true; + } } - return false; } -- cgit v1.1 From b5b53dd3ebb331c5d235df161fe9cefc405c3660 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 19:55:35 -0700 Subject: * One more debug message on FetchInventoryDescendants * More streams close on finally --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a4460e4..1917228 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1168,6 +1168,7 @@ namespace OpenSim.Region.Framework.Scenes private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { + m_log.DebugFormat("[AGENT INVENTORY]: Send Inventory Folder {0} Update to {1} {2}", folder.Name, client.FirstName, client.LastName); InventoryCollection contents = InventoryService.GetFolderContent(client.AgentId, folder.ID); client.SendInventoryFolderDetails(client.AgentId, folder.ID, contents.Items, contents.Folders, fetchFolders, fetchItems); } -- cgit v1.1 From 58c33fbc890a4320b6323b379917bb9615968946 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 21:32:15 -0700 Subject: Uncommented log message on CAPs FetchInventoryDescendants --- OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index e561efb..f6d8eac 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -477,9 +477,9 @@ namespace OpenSim.Region.Framework.Scenes public InventoryCollection HandleFetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder, out int version) { -// m_log.DebugFormat( -// "[INVENTORY CACHE]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", -// fetchFolders, fetchItems, folderID, agentID); + m_log.DebugFormat( + "[INVENTORY CACHE]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", + fetchFolders, fetchItems, folderID, agentID); // FIXME MAYBE: We're not handling sortOrder! -- cgit v1.1 From adc208e56872c293f31ca2a3521775b5c6b297f2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 7 Oct 2009 04:36:36 +0100 Subject: Replace LLClientView on the branch with master. UNCOMPILABLE! --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 12726 ++++++++++--------- 1 file changed, 6646 insertions(+), 6080 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 84e705a..0052729 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -58,180 +58,526 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector { - // LLClientView Only - public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); - - /// Used to adjust Sun Orbit values so Linden based viewers properly position sun - private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients - private readonly LLUDPServer m_udpServer; - private readonly LLUDPClient m_udpClient; + /* static variables */ + public static SynchronizeClientHandler SynchronizeClient; + /* private variables */ private readonly UUID m_sessionId; - private readonly UUID m_secureSessionId; - private readonly UUID m_agentId; - private readonly uint m_circuitCode; - private readonly byte[] m_channelVersion = Utils.EmptyBytes; - private readonly Dictionary m_defaultAnimations = new Dictionary(); - private readonly IGroupsModule m_GroupsModule; + private readonly UUID m_secureSessionId = UUID.Zero; + + private int m_debugPacketLevel; + //private readonly IAssetCache m_assetCache; private int m_cachedTextureSerial; + private Timer m_clientPingTimer; + private Timer m_avatarTerseUpdateTimer; private List m_avatarTerseUpdates = new List(); + private Timer m_primTerseUpdateTimer; private List m_primTerseUpdates = new List(); private Timer m_primFullUpdateTimer; - private List m_primFullUpdates = new List(); + private List m_primFullUpdates = + new List(); + + private bool m_clientBlocked; + + private int m_probesWithNoIngressPackets; + + private readonly UUID m_agentId; + private readonly uint m_circuitCode; private int m_moneyBalance; + private readonly ILLPacketHandler m_PacketHandler; + private int m_animationSequenceNumber = 1; + + private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL + + private readonly Dictionary m_defaultAnimations = new Dictionary(); + private bool m_SendLogoutPacketWhenClosing = true; - private AgentUpdateArgs lastarg; - private bool m_IsActive = true; + + private int m_inPacketsChecked; + + // Used to adjust Sun Orbit values so Linden based viewers properly position sun + private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; + + + /* protected variables */ + + protected static Dictionary PacketHandlers = + new Dictionary(); //Global/static handlers for all clients protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers + protected IScene m_scene; + + protected LLPacketServer m_networkServer; + protected LLImageManager m_imageManager; + + /* public variables */ protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; protected Vector3 m_startpos; protected EndPoint m_userEndPoint; + protected EndPoint m_proxyEndPoint; protected UUID m_activeGroupID = UUID.Zero; protected string m_activeGroupName = String.Empty; protected ulong m_activeGroupPowers; protected Dictionary m_groupPowers = new Dictionary(); - protected int m_terrainCheckerCount; + protected int m_avatarTerseUpdateRate = 50; + protected int m_avatarTerseUpdatesPerPacket = 5; - // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet + // LL uses these limits, apparently. Compressed terse would be + // 23, but we don't have that yet + // protected int m_primTerseUpdatesPerPacket = 10; protected int m_primFullUpdatesPerPacket = 14; + protected int m_primTerseUpdateRate = 10; protected int m_primFullUpdateRate = 14; + protected int m_textureSendLimit = 20; protected int m_textureDataLimit = 10; - protected int m_avatarTerseUpdateRate = 50; - protected int m_avatarTerseUpdatesPerPacket = 5; + protected int m_packetMTU = 1400; + protected IAssetService m_assetService; - #region Properties + // LLClientView Only + public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); + + /* Instantiated Designated Event Delegates */ + //- used so we don't create new objects for each incoming packet and then toss it out later */ + + private GenericMessage handlerGenericMessage; + private RequestAvatarProperties handlerRequestAvatarProperties; //OnRequestAvatarProperties; + private UpdateAvatarProperties handlerUpdateAvatarProperties; // OnUpdateAvatarProperties; + private ChatMessage handlerChatFromClient; //OnChatFromClient; + private ChatMessage handlerChatFromClient2; //OnChatFromClient; + private ImprovedInstantMessage handlerInstantMessage; //OnInstantMessage; + private FriendActionDelegate handlerApproveFriendRequest; //OnApproveFriendRequest; + private FriendshipTermination handlerTerminateFriendship; //OnTerminateFriendship; + private RezObject handlerRezObject; //OnRezObject; + private DeRezObject handlerDeRezObject; //OnDeRezObject; + private ModifyTerrain handlerModifyTerrain; + private BakeTerrain handlerBakeTerrain; + private EstateChangeInfo handlerEstateChangeInfo; + private Action handlerRegionHandShakeReply; //OnRegionHandShakeReply; + private GenericCall2 handlerRequestWearables; //OnRequestWearables; + private Action handlerRequestAvatarsData; //OnRequestAvatarsData; + private SetAppearance handlerSetAppearance; //OnSetAppearance; + private AvatarNowWearing handlerAvatarNowWearing; //OnAvatarNowWearing; + private RezSingleAttachmentFromInv handlerRezSingleAttachment; //OnRezSingleAttachmentFromInv; + private RezMultipleAttachmentsFromInv handlerRezMultipleAttachments; //OnRezMultipleAttachmentsFromInv; + private UUIDNameRequest handlerDetachAttachmentIntoInv; // Detach attachment! + private ObjectAttach handlerObjectAttach; //OnObjectAttach; + private SetAlwaysRun handlerSetAlwaysRun; //OnSetAlwaysRun; + private GenericCall2 handlerCompleteMovementToRegion; //OnCompleteMovementToRegion; + private UpdateAgent handlerAgentUpdate; //OnAgentUpdate; + private StartAnim handlerStartAnim; + private StopAnim handlerStopAnim; + private AgentRequestSit handlerAgentRequestSit; //OnAgentRequestSit; + private AgentSit handlerAgentSit; //OnAgentSit; + private AvatarPickerRequest handlerAvatarPickerRequest; //OnAvatarPickerRequest; + private FetchInventory handlerAgentDataUpdateRequest; //OnAgentDataUpdateRequest; + private TeleportLocationRequest handlerSetStartLocationRequest; //OnSetStartLocationRequest; + private TeleportLandmarkRequest handlerTeleportLandmarkRequest; //OnTeleportLandmarkRequest; + private LinkObjects handlerLinkObjects; //OnLinkObjects; + private DelinkObjects handlerDelinkObjects; //OnDelinkObjects; + private AddNewPrim handlerAddPrim; //OnAddPrim; + private UpdateShape handlerUpdatePrimShape; //null; + private ObjectExtraParams handlerUpdateExtraParams; //OnUpdateExtraParams; + private ObjectDuplicate handlerObjectDuplicate; + private ObjectDuplicateOnRay handlerObjectDuplicateOnRay; + private ObjectRequest handlerObjectRequest; + private ObjectSelect handlerObjectSelect; + private ObjectDeselect handlerObjectDeselect; + private ObjectIncludeInSearch handlerObjectIncludeInSearch; + private UpdatePrimFlags handlerUpdatePrimFlags; //OnUpdatePrimFlags; + private UpdatePrimTexture handlerUpdatePrimTexture; + private GrabObject handlerGrabObject; //OnGrabObject; + private MoveObject handlerGrabUpdate; //OnGrabUpdate; + private DeGrabObject handlerDeGrabObject; //OnDeGrabObject; + private SpinStart handlerSpinStart; //OnSpinStart; + private SpinObject handlerSpinUpdate; //OnSpinUpdate; + private SpinStop handlerSpinStop; //OnSpinStop; + private GenericCall7 handlerObjectDescription; + private GenericCall7 handlerObjectName; + private GenericCall7 handlerObjectClickAction; + private GenericCall7 handlerObjectMaterial; + private ObjectPermissions handlerObjectPermissions; + private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily; //OnRequestObjectPropertiesFamily; + //private TextureRequest handlerTextureRequest; + private UDPAssetUploadRequest handlerAssetUploadRequest; //OnAssetUploadRequest; + private RequestXfer handlerRequestXfer; //OnRequestXfer; + private XferReceive handlerXferReceive; //OnXferReceive; + private ConfirmXfer handlerConfirmXfer; //OnConfirmXfer; + private AbortXfer handlerAbortXfer; + private CreateInventoryFolder handlerCreateInventoryFolder; //OnCreateNewInventoryFolder; + private UpdateInventoryFolder handlerUpdateInventoryFolder; + private MoveInventoryFolder handlerMoveInventoryFolder; + private CreateNewInventoryItem handlerCreateNewInventoryItem; //OnCreateNewInventoryItem; + private FetchInventory handlerFetchInventory; + private FetchInventoryDescendents handlerFetchInventoryDescendents; //OnFetchInventoryDescendents; + private PurgeInventoryDescendents handlerPurgeInventoryDescendents; //OnPurgeInventoryDescendents; + private UpdateInventoryItem handlerUpdateInventoryItem; + private CopyInventoryItem handlerCopyInventoryItem; + private MoveInventoryItem handlerMoveInventoryItem; + private RemoveInventoryItem handlerRemoveInventoryItem; + private RemoveInventoryFolder handlerRemoveInventoryFolder; + private RequestTaskInventory handlerRequestTaskInventory; //OnRequestTaskInventory; + private UpdateTaskInventory handlerUpdateTaskInventory; //OnUpdateTaskInventory; + private MoveTaskInventory handlerMoveTaskItem; + private RemoveTaskInventory handlerRemoveTaskItem; //OnRemoveTaskItem; + private RezScript handlerRezScript; //OnRezScript; + private RequestMapBlocks handlerRequestMapBlocks; //OnRequestMapBlocks; + private RequestMapName handlerMapNameRequest; //OnMapNameRequest; + private TeleportLocationRequest handlerTeleportLocationRequest; //OnTeleportLocationRequest; + private MoneyBalanceRequest handlerMoneyBalanceRequest; //OnMoneyBalanceRequest; + private UUIDNameRequest handlerNameRequest; + private ParcelAccessListRequest handlerParcelAccessListRequest; //OnParcelAccessListRequest; + private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest; //OnParcelAccessListUpdateRequest; + private ParcelPropertiesRequest handlerParcelPropertiesRequest; //OnParcelPropertiesRequest; + private ParcelDivideRequest handlerParcelDivideRequest; //OnParcelDivideRequest; + private ParcelJoinRequest handlerParcelJoinRequest; //OnParcelJoinRequest; + private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest; //OnParcelPropertiesUpdateRequest; + private ParcelSelectObjects handlerParcelSelectObjects; //OnParcelSelectObjects; + private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest; //OnParcelObjectOwnerRequest; + private ParcelAbandonRequest handlerParcelAbandonRequest; + private ParcelGodForceOwner handlerParcelGodForceOwner; + private ParcelReclaim handlerParcelReclaim; + private RequestTerrain handlerRequestTerrain; + private RequestTerrain handlerUploadTerrain; + private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest; + private RegionInfoRequest handlerRegionInfoRequest; //OnRegionInfoRequest; + private EstateCovenantRequest handlerEstateCovenantRequest; //OnEstateCovenantRequest; + private RequestGodlikePowers handlerReqGodlikePowers; //OnRequestGodlikePowers; + private GodKickUser handlerGodKickUser; //OnGodKickUser; + private ViewerEffectEventHandler handlerViewerEffect; //OnViewerEffect; + private Action handlerLogout; //OnLogout; + private MoneyTransferRequest handlerMoneyTransferRequest; //OnMoneyTransferRequest; + private ParcelBuy handlerParcelBuy; + private EconomyDataRequest handlerEconomoyDataRequest; + + private UpdateVector handlerUpdatePrimSinglePosition; //OnUpdatePrimSinglePosition; + private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation; //OnUpdatePrimSingleRotation; + private UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition; //OnUpdatePrimSingleRotation; + private UpdateVector handlerUpdatePrimScale; //OnUpdatePrimScale; + private UpdateVector handlerUpdatePrimGroupScale; //OnUpdateGroupScale; + private UpdateVector handlerUpdateVector; //OnUpdatePrimGroupPosition; + private UpdatePrimRotation handlerUpdatePrimRotation; //OnUpdatePrimGroupRotation; + // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; //OnUpdatePrimGroupMouseRotation; + // private RequestAsset handlerRequestAsset; // OnRequestAsset; + private UUIDNameRequest handlerTeleportHomeRequest; + + private RegionHandleRequest handlerRegionHandleRequest; // OnRegionHandleRequest + private ParcelInfoRequest handlerParcelInfoRequest; // OnParcelInfoRequest + + private ScriptAnswer handlerScriptAnswer; + private RequestPayPrice handlerRequestPayPrice; + private ObjectSaleInfo handlerObjectSaleInfo; + private ObjectBuy handlerObjectBuy; + //private BuyObjectInventory handlerBuyObjectInventory; + private ObjectDeselect handlerObjectDetach; + private ObjectDrop handlerObjectDrop; + private AgentSit handlerOnUndo; + + private ForceReleaseControls handlerForceReleaseControls; + + private GodLandStatRequest handlerLandStatRequest; + + private UUIDNameRequest handlerUUIDGroupNameRequest; + + private ParcelDeedToGroup handlerParcelDeedToGroup; + + private RequestObjectPropertiesFamily handlerObjectGroupRequest; + private ScriptReset handlerScriptReset; + private GetScriptRunning handlerGetScriptRunning; + private SetScriptRunning handlerSetScriptRunning; + private UpdateVector handlerAutoPilotGo; + //Gesture + private ActivateGesture handlerActivateGesture; + private DeactivateGesture handlerDeactivateGesture; + //Sound + private SoundTrigger handlerSoundTrigger; + private ObjectOwner handlerObjectOwner; + + private DirPlacesQuery handlerDirPlacesQuery; + private DirFindQuery handlerDirFindQuery; + private DirLandQuery handlerDirLandQuery; + private DirPopularQuery handlerDirPopularQuery; + private DirClassifiedQuery handlerDirClassifiedQuery; + private ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime; + + private MapItemRequest handlerMapItemRequest; + + private StartLure handlerStartLure; + private TeleportLureRequest handlerTeleportLureRequest; + + private NetworkStats handlerNetworkStatsUpdate; + + private ClassifiedInfoRequest handlerClassifiedInfoRequest; + private ClassifiedInfoUpdate handlerClassifiedInfoUpdate; + private ClassifiedDelete handlerClassifiedDelete; + private ClassifiedDelete handlerClassifiedGodDelete; + + private EventNotificationAddRequest handlerEventNotificationAddRequest; + private EventNotificationRemoveRequest handlerEventNotificationRemoveRequest; + private EventGodDelete handlerEventGodDelete; + + private ParcelDwellRequest handlerParcelDwellRequest; + + private UserInfoRequest handlerUserInfoRequest; + private UpdateUserInfo handlerUpdateUserInfo; + + private RetrieveInstantMessages handlerRetrieveInstantMessages; + + private PickDelete handlerPickDelete; + private PickGodDelete handlerPickGodDelete; + private PickInfoUpdate handlerPickInfoUpdate; + private AvatarNotesUpdate handlerAvatarNotesUpdate; + + private MuteListRequest handlerMuteListRequest; + + //private AvatarInterestUpdate handlerAvatarInterestUpdate; + + private PlacesQuery handlerPlacesQuery; + + private readonly IGroupsModule m_GroupsModule; + + private AgentUpdateArgs lastarg = null; + + //private TerrainUnacked handlerUnackedTerrain = null; + + //** + + /* Properties */ + + public UUID SecureSessionId + { + get { return m_secureSessionId; } + } + + public IScene Scene + { + get { return m_scene; } + } + + public UUID SessionId + { + get { return m_sessionId; } + } - public UUID SecureSessionId { get { return m_secureSessionId; } } - public IScene Scene { get { return m_scene; } } - public UUID SessionId { get { return m_sessionId; } } public Vector3 StartPos { get { return m_startpos; } set { m_startpos = value; } } - public UUID AgentId { get { return m_agentId; } } - public UUID ActiveGroupId { get { return m_activeGroupID; } } - public string ActiveGroupName { get { return m_activeGroupName; } } - public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } - public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } + + public UUID AgentId + { + get { return m_agentId; } + } + + public UUID ActiveGroupId + { + get { return m_activeGroupID; } + } + + public string ActiveGroupName + { + get { return m_activeGroupName; } + } + + public ulong ActiveGroupPowers + { + get { return m_activeGroupPowers; } + } + + public bool IsGroupMember(UUID groupID) + { + return m_groupPowers.ContainsKey(groupID); + } + + public ulong GetGroupPowers(UUID groupID) + { + if (groupID == m_activeGroupID) + return m_activeGroupPowers; + + if (m_groupPowers.ContainsKey(groupID)) + return m_groupPowers[groupID]; + + return 0; + } + + /// + /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. + /// + public bool ChildAgentStatus() + { + return m_scene.PresenceChildStatus(AgentId); + } + /// /// First name of the agent/avatar represented by the client /// - public string FirstName { get { return m_firstName; } } + public string FirstName + { + get { return m_firstName; } + } + /// /// Last name of the agent/avatar represented by the client /// - public string LastName { get { return m_lastName; } } + public string LastName + { + get { return m_lastName; } + } + /// /// Full name of the client (first name and last name) /// - public string Name { get { return FirstName + " " + LastName; } } - public uint CircuitCode { get { return m_circuitCode; } } - public int MoneyBalance { get { return m_moneyBalance; } } - public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } + public string Name + { + get { return FirstName + " " + LastName; } + } + + public uint CircuitCode + { + get { return m_circuitCode; } + } + + public int MoneyBalance + { + get { return m_moneyBalance; } + } + + public int NextAnimationSequenceNumber + { + get { return m_animationSequenceNumber++; } + } + + public ILLPacketHandler PacketHandler + { + get { return m_PacketHandler; } + } + + bool m_IsActive = true; + public bool IsActive { get { return m_IsActive; } set { m_IsActive = value; } } - public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } - #endregion Properties + public bool SendLogoutPacketWhenClosing + { + set { m_SendLogoutPacketWhenClosing = value; } + } + + /* METHODS */ /// /// Constructor /// - public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, - UUID agentId, UUID sessionId, uint circuitCode) + public LLClientView( + EndPoint remoteEP, IScene scene, LLPacketServer packServer, + AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP, + ClientStackUserSettings userSettings) { - RegisterInterface(this); - RegisterInterface(this); - RegisterInterface(this); - + // Should be called first? + RegisterInterfaces(); + + m_GroupsModule = scene.RequestModuleInterface(); + m_moneyBalance = 1000; + + m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); + InitDefaultAnimations(); m_scene = scene; + //m_assetCache = assetCache; + m_assetService = m_scene.RequestModuleInterface(); - m_GroupsModule = scene.RequestModuleInterface(); - m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); - m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); + + m_networkServer = packServer; + m_agentId = agentId; m_sessionId = sessionId; - m_secureSessionId = sessionInfo.LoginInfo.SecureSession; m_circuitCode = circuitCode; + m_userEndPoint = remoteEP; + m_proxyEndPoint = proxyEP; + m_firstName = sessionInfo.LoginInfo.First; m_lastName = sessionInfo.LoginInfo.Last; m_startpos = sessionInfo.LoginInfo.StartPos; - m_moneyBalance = 1000; - m_udpServer = udpServer; - m_udpClient = udpClient; - m_udpClient.OnQueueEmpty += HandleQueueEmpty; - m_udpClient.OnPacketStats += PopulateStats; + if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) + { + m_secureSessionId = sessionInfo.LoginInfo.SecureSession; + } + + // While working on this, the BlockingQueue had me fooled for a bit. + // The Blocking queue causes the thread to stop until there's something + // in it to process. It's an on-purpose threadlock though because + // without it, the clientloop will suck up all sim resources. + + m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings); + m_PacketHandler.SynchronizeClient = SynchronizeClient; + m_PacketHandler.OnPacketStats += PopulateStats; + m_PacketHandler.OnQueueEmpty += HandleQueueEmpty; + + if (scene.Config != null) + { + IConfig clientConfig = scene.Config.Configs["LLClient"]; + if (clientConfig != null) + { + m_PacketHandler.ReliableIsImportant = + clientConfig.GetBoolean("ReliableIsImportant", + false); + m_PacketHandler.MaxReliableResends = clientConfig.GetInt("MaxReliableResends", + m_PacketHandler.MaxReliableResends); + m_primTerseUpdatesPerPacket = clientConfig.GetInt("TerseUpdatesPerPacket", + m_primTerseUpdatesPerPacket); + m_primFullUpdatesPerPacket = clientConfig.GetInt("FullUpdatesPerPacket", + m_primFullUpdatesPerPacket); + + m_primTerseUpdateRate = clientConfig.GetInt("TerseUpdateRate", + m_primTerseUpdateRate); + m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate", + m_primFullUpdateRate); + + m_textureSendLimit = clientConfig.GetInt("TextureSendLimit", + m_textureSendLimit); + + m_textureDataLimit = clientConfig.GetInt("TextureDataLimit", + m_textureDataLimit); + + m_packetMTU = clientConfig.GetInt("PacketMTU", 1400); + } + } RegisterLocalPacketHandlers(); + m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); } - public void SetDebugPacketLevel(int newDebug) + public void SetDebugPacketLevel(int newDebugPacketLevel) { + m_debugPacketLevel = newDebugPacketLevel; } - #region Client Methods - - /// - /// Close down the client view. This *must* be the last method called, since the last # - /// statement of CloseCleanup() aborts the thread. - /// - /// - public void Close(bool shutdownCircuit) - { - m_log.DebugFormat( - "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", - shutdownCircuit, Name, m_scene.RegionInfo.RegionName); - - if (m_imageManager != null) - m_imageManager.Close(); - - if (m_udpServer != null) - m_udpServer.Flush(); - - // raise an event on the packet server to Shutdown the circuit - // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup - // here otherwise we'll end up calling it twice. - // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks - // horribly tangly. Hopefully it should be possible to greatly simplify it. - if (shutdownCircuit) - { - if (OnConnectionClosed != null) - OnConnectionClosed(this); - } - else - { - CloseCleanup(shutdownCircuit); - } - } + # region Client Methods private void CloseCleanup(bool shutdownCircuit) { + + m_scene.RemoveClient(AgentId); //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); @@ -244,6 +590,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP Thread.Sleep(2000); // Shut down timers. Thread Context of this method is murky. Lock all timers + if (m_clientPingTimer.Enabled) + lock (m_clientPingTimer) + m_clientPingTimer.Stop(); if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -276,21 +625,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP // of the client thread regardless of where Close() is called. KillEndDone(); } + + Terminate(); + } - IsActive = false; + /// + /// Close down the client view. This *must* be the last method called, since the last # + /// statement of CloseCleanup() aborts the thread. + /// + /// + public void Close(bool shutdownCircuit) + { + m_clientPingTimer.Enabled = false; - m_avatarTerseUpdateTimer.Close(); - m_primTerseUpdateTimer.Close(); - m_primFullUpdateTimer.Close(); + m_log.DebugFormat( + "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", + shutdownCircuit, Name, m_scene.RegionInfo.RegionName); - //m_udpServer.OnPacketStats -= PopulateStats; - m_udpClient.Shutdown(); + if (m_imageManager != null) + m_imageManager.Close(); - // wait for thread stoped - // m_clientThread.Join(); + if (m_PacketHandler != null) + m_PacketHandler.Flush(); - // delete circuit code - //m_networkServer.CloseClient(this); + // raise an event on the packet server to Shutdown the circuit + // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup + // here otherwise we'll end up calling it twice. + // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks + // horribly tangly. Hopefully it should be possible to greatly simplify it. + if (shutdownCircuit) + { + if (OnConnectionClosed != null) + OnConnectionClosed(this); + } + else + { + CloseCleanup(shutdownCircuit); + } } public void Kick(string message) @@ -312,6 +683,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Stop() { // Shut down timers. Thread Context is Murky, lock all timers! + if (m_clientPingTimer.Enabled) + lock (m_clientPingTimer) + m_clientPingTimer.Stop(); + if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -325,13 +700,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdateTimer.Stop(); } - #endregion Client Methods + public void Restart() + { + // re-construct + m_PacketHandler.Clear(); + + m_clientPingTimer = new Timer(5000); + m_clientPingTimer.Elapsed += CheckClientConnectivity; + m_clientPingTimer.Enabled = true; + + m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); + m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); + m_avatarTerseUpdateTimer.AutoReset = false; + + m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); + m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); + m_primTerseUpdateTimer.AutoReset = false; + + m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); + m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); + m_primFullUpdateTimer.AutoReset = false; + } + + private void Terminate() + { + IsActive = false; + + m_clientPingTimer.Close(); + m_avatarTerseUpdateTimer.Close(); + m_primTerseUpdateTimer.Close(); + m_primFullUpdateTimer.Close(); + + m_PacketHandler.OnPacketStats -= PopulateStats; + m_PacketHandler.Dispose(); + + // wait for thread stoped + // m_clientThread.Join(); + + // delete circuit code + //m_networkServer.CloseClient(this); + } + + #endregion - #region Packet Handling + # region Packet Handling public void PopulateStats(int inPackets, int outPackets, int unAckedBytes) { - NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate; + handlerNetworkStatsUpdate = OnNetworkStatsUpdate; if (handlerNetworkStatsUpdate != null) { handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes); @@ -412,7 +828,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return result; } - /*protected void DebugPacket(string direction, Packet packet) + protected void DebugPacket(string direction, Packet packet) { string info; @@ -438,27 +854,113 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); - }*/ - - #endregion Packet Handling - - # region Setup + } /// - /// Starts up the timers to check the client and resend unacked packets - /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene + /// Main packet processing loop for the UDP component of the client session. Both incoming and outgoing + /// packets are processed here. /// - protected virtual void InitNewClient() + protected virtual void ClientLoop() { - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); - m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); - m_avatarTerseUpdateTimer.AutoReset = false; + m_log.DebugFormat( + "[CLIENT]: Entered main packet processing loop for {0} in {1}", Name, Scene.RegionInfo.RegionName); - m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); - m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); - m_primTerseUpdateTimer.AutoReset = false; + while (IsActive) + { + LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue(); + + if (nextPacket == null) { + m_log.DebugFormat("[CLIENT]: PacketQueue return null LLQueItem"); + continue; + } - m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); + if (nextPacket.Incoming) + { + if (m_debugPacketLevel > 0) + DebugPacket("IN", nextPacket.Packet); + m_PacketHandler.ProcessInPacket(nextPacket); + } + else + { + if (m_debugPacketLevel > 0) + DebugPacket("OUT", nextPacket.Packet); + m_PacketHandler.ProcessOutPacket(nextPacket); + } + } + } + + # endregion + + protected int m_terrainCheckerCount; + + /// + /// Event handler for check client timer + /// Checks to ensure that the client is still connected. If the client has failed to respond to many pings + /// in succession then close down the connection. + /// + /// + /// + protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) + { + if (m_PacketHandler.PacketsReceived == m_inPacketsChecked) + { + // no packet came in since the last time we checked... + + m_probesWithNoIngressPackets++; + if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) // agent active + || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) // agent paused + { + m_clientPingTimer.Enabled = false; + + m_log.WarnFormat( + "[CLIENT]: Client for agent {0} {1} has stopped responding to pings. Closing connection", + Name, AgentId); + + if (OnConnectionClosed != null) + { + OnConnectionClosed(this); + } + } + else + { + // this will normally trigger at least one packet (ping response) + SendStartPingCheck(0); + } + } + else + { + // Something received in the meantime - we can reset the counters + m_probesWithNoIngressPackets = 0; + // ... and store the current number of packets received to find out if another one got in on the next cycle + m_inPacketsChecked = m_PacketHandler.PacketsReceived; + } + + } + + # region Setup + + /// + /// Starts up the timers to check the client and resend unacked packets + /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene + /// + protected virtual void InitNewClient() + { + //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); + + // Ping the client regularly to check that it's still there + m_clientPingTimer = new Timer(5000); + m_clientPingTimer.Elapsed += CheckClientConnectivity; + m_clientPingTimer.Enabled = true; + + m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); + m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); + m_avatarTerseUpdateTimer.AutoReset = false; + + m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); + m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); + m_primTerseUpdateTimer.AutoReset = false; + + m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); m_primFullUpdateTimer.AutoReset = false; @@ -469,18 +971,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - // This sets up all the timers - InitNewClient(); + m_clientThread = new Thread(RunUserSession); + m_clientThread.Name = "ClientThread"; + m_clientThread.IsBackground = true; + m_clientThread.Start(); + ThreadTracker.Add(m_clientThread); } /// /// Run a user session. This method lies at the base of the entire client thread. /// - protected void RunUserSession() + protected virtual void RunUserSession() { + //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) + //otherwise it will override this and use the system default + Culture.SetCurrentCulture(); + try { - + // This sets up all the timers + InitNewClient(); + ClientLoop(); } catch (Exception e) { @@ -504,7 +1015,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP + "Any further actions taken will not be processed.\n" + "Please relog", true); - m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false); + LLQueItem item = new LLQueItem(); + item.Packet = packet; + item.Sequence = packet.Header.Sequence; + + m_PacketHandler.ProcessOutPacket(item); // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to // listeners yet, though. @@ -522,8 +1037,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP # endregion - #region Events - + // Previously ClientView.API partial class public event GenericMessage OnGenericMessage; public event BinaryGenericMessage OnBinaryGenericMessage; public event Action OnLogout; @@ -683,10 +1197,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; + public event TerrainUnacked OnUnackedTerrain; + public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; public event ObjectOwner OnObjectOwner; + public event DirPlacesQuery OnDirPlacesQuery; public event DirFindQuery OnDirFindQuery; public event DirLandQuery OnDirLandQuery; @@ -694,34 +1211,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event DirClassifiedQuery OnDirClassifiedQuery; public event EventInfoRequest OnEventInfoRequest; public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; + public event MapItemRequest OnMapItemRequest; + public event OfferCallingCard OnOfferCallingCard; public event AcceptCallingCard OnAcceptCallingCard; public event DeclineCallingCard OnDeclineCallingCard; public event SoundTrigger OnSoundTrigger; + public event StartLure OnStartLure; public event TeleportLureRequest OnTeleportLureRequest; public event NetworkStats OnNetworkStatsUpdate; + public event ClassifiedInfoRequest OnClassifiedInfoRequest; public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; public event ClassifiedDelete OnClassifiedDelete; public event ClassifiedDelete OnClassifiedGodDelete; + public event EventNotificationAddRequest OnEventNotificationAddRequest; public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; public event EventGodDelete OnEventGodDelete; + public event ParcelDwellRequest OnParcelDwellRequest; + public event UserInfoRequest OnUserInfoRequest; public event UpdateUserInfo OnUpdateUserInfo; + public event RetrieveInstantMessages OnRetrieveInstantMessages; + public event PickDelete OnPickDelete; public event PickGodDelete OnPickGodDelete; public event PickInfoUpdate OnPickInfoUpdate; public event AvatarNotesUpdate OnAvatarNotesUpdate; + public event MuteListRequest OnMuteListRequest; - public event AvatarInterestUpdate OnAvatarInterestUpdate; - public event PlacesQuery OnPlacesQuery; - #endregion Events + //public event AvatarInterestUpdate OnAvatarInterestUpdate; + + public event PlacesQuery OnPlacesQuery; public void ActivateGesture(UUID assetId, UUID gestureId) { @@ -1323,13 +1850,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendStartPingCheck(byte seq) { StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); - pc.Header.Reliable = false; - - OutgoingPacket oldestPacket = m_udpClient.NeedAcks.GetOldest(); - pc.PingID.PingID = seq; - pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; - + pc.Header.Reliable = false; OutPacket(pc, ThrottleOutPacketType.Unknown); } @@ -1405,12 +1927,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP descend.ItemData[i].AssetID = item.AssetID; descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; descend.ItemData[i].BaseMask = item.BasePermissions; - descend.ItemData[i].Description = Util.StringToBytes256(item.Description); + descend.ItemData[i].Description = LLUtil.StringToPacketBytes(item.Description); descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; descend.ItemData[i].OwnerMask = item.CurrentPermissions; descend.ItemData[i].FolderID = item.Folder; descend.ItemData[i].InvType = (sbyte)item.InvType; - descend.ItemData[i].Name = Util.StringToBytes256(item.Name); + descend.ItemData[i].Name = LLUtil.StringToPacketBytes(item.Name); descend.ItemData[i].NextOwnerMask = item.NextPermissions; descend.ItemData[i].OwnerID = item.Owner; descend.ItemData[i].Type = (sbyte)item.AssetType; @@ -1491,7 +2013,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); descend.FolderData[i].FolderID = folder.ID; - descend.FolderData[i].Name = Util.StringToBytes256(folder.Name); + descend.FolderData[i].Name = LLUtil.StringToPacketBytes(folder.Name); descend.FolderData[i].ParentID = folder.ParentID; descend.FolderData[i].Type = (sbyte)folder.Type; @@ -1606,11 +2128,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; inventoryReply.InventoryData[0].CreationDate = item.CreationDate; - inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description); + inventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(item.Description); inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; inventoryReply.InventoryData[0].FolderID = item.Folder; inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; - inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name); + inventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(item.Name); inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; inventoryReply.InventoryData[0].OwnerID = item.Owner; inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; @@ -1735,7 +2257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; folderBlock.Type = -1; - folderBlock.Name = Util.StringToBytes256(folder.Name); + folderBlock.Name = LLUtil.StringToPacketBytes(folder.Name); return folderBlock; } @@ -1753,11 +2275,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP itemBlock.AssetID = item.AssetID; itemBlock.CreatorID = item.CreatorIdAsUuid; itemBlock.BaseMask = item.BasePermissions; - itemBlock.Description = Util.StringToBytes256(item.Description); + itemBlock.Description = LLUtil.StringToPacketBytes(item.Description); itemBlock.EveryoneMask = item.EveryOnePermissions; itemBlock.FolderID = item.Folder; itemBlock.InvType = (sbyte)item.InvType; - itemBlock.Name = Util.StringToBytes256(item.Name); + itemBlock.Name = LLUtil.StringToPacketBytes(item.Name); itemBlock.NextOwnerMask = item.NextPermissions; itemBlock.OwnerID = item.Owner; itemBlock.OwnerMask = item.CurrentPermissions; @@ -1817,11 +2339,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid; bulkUpdate.ItemData[0].BaseMask = item.BasePermissions; bulkUpdate.ItemData[0].CreationDate = item.CreationDate; - bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description); + bulkUpdate.ItemData[0].Description = LLUtil.StringToPacketBytes(item.Description); bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions; bulkUpdate.ItemData[0].FolderID = item.Folder; bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType; - bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name); + bulkUpdate.ItemData[0].Name = LLUtil.StringToPacketBytes(item.Name); bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions; bulkUpdate.ItemData[0].OwnerID = item.Owner; bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; @@ -1864,11 +2386,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP InventoryReply.InventoryData[0].AssetID = Item.AssetID; InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid; InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions; - InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description); + InventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(Item.Description); InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions; InventoryReply.InventoryData[0].FolderID = Item.Folder; InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType; - InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name); + InventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(Item.Name); InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions; InventoryReply.InventoryData[0].OwnerID = Item.Owner; InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; @@ -2035,7 +2557,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// /// - public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) + protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) { AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); alertPack.AgentData.AgentID = AgentId; @@ -2246,8011 +2768,7983 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(avatarReply, ThrottleOutPacketType.Task); } - /// - /// Send the client an Estate message blue box pop-down with a single OK button - /// - /// - /// - /// - /// - public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) - { - if (!ChildAgentStatus()) - SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); + #endregion - //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); - } + // Gesture - public void SendLogoutPacket() + #region Appearance/ Wearables Methods + + public void SendWearables(AvatarWearable[] wearables, int serial) { - // I know this is a bit of a hack, however there are times when you don't - // want to send this, but still need to do the rest of the shutdown process - // this method gets called from the packet server.. which makes it practically - // impossible to do any other way. + AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); + aw.AgentData.AgentID = AgentId; + aw.AgentData.SerialNum = (uint)serial; + aw.AgentData.SessionID = m_sessionId; - if (m_SendLogoutPacketWhenClosing) + // TODO: don't create new blocks if recycling an old packet + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + for (int i = 0; i < wearables.Length; i++) { - LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); - // TODO: don't create new blocks if recycling an old packet - logReply.AgentData.AgentID = AgentId; - logReply.AgentData.SessionID = SessionId; - logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; - logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); - logReply.InventoryData[0].ItemID = UUID.Zero; + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = wearables[i].AssetID; + awb.ItemID = wearables[i].ItemID; + aw.WearableData[i] = awb; - OutPacket(logReply, ThrottleOutPacketType.Task); +// m_log.DebugFormat( +// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", +// awb.ItemID, awb.AssetID, i, Name); } - } - public void SendHealth(float health) - { - HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); - healthpacket.HealthData.Health = health; - OutPacket(healthpacket, ThrottleOutPacketType.Task); + OutPacket(aw, ThrottleOutPacketType.Task); } - public void SendAgentOnline(UUID[] agentIDs) + public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { - OnlineNotificationPacket onp = new OnlineNotificationPacket(); - OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) - { - OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - onpb[i] = onpbl; - } - onp.AgentBlock = onpb; - onp.Header.Reliable = true; - OutPacket(onp, ThrottleOutPacketType.Task); - } + AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); + // TODO: don't create new blocks if recycling an old packet + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + avp.ObjectData.TextureEntry = textureEntry; - public void SendAgentOffline(UUID[] agentIDs) - { - OfflineNotificationPacket offp = new OfflineNotificationPacket(); - OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) { - OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - offpb[i] = onpbl; + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; } - offp.AgentBlock = offpb; - offp.Header.Reliable = true; - OutPacket(offp, ThrottleOutPacketType.Task); + + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + OutPacket(avp, ThrottleOutPacketType.Task); } - public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, - Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) + public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) { - AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); - avatarSitResponse.SitObject.ID = TargetID; - if (CameraAtOffset != Vector3.Zero) + //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); + + AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); + // TODO: don't create new blocks if recycling an old packet + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = sourceAgentId; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; + ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; + + for (int i = 0; i < animations.Length; ++i) { - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; - } - avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; - avatarSitResponse.SitTransform.AutoPilot = autopilot; - avatarSitResponse.SitTransform.SitPosition = OffsetPos; - avatarSitResponse.SitTransform.SitRotation = SitOrientation; + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; - OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); + ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[i].ObjectID = objectIDs[i]; + if (objectIDs[i] == UUID.Zero) + ani.AnimationSourceList[i].ObjectID = sourceAgentId; + } + ani.Header.Reliable = false; + OutPacket(ani, ThrottleOutPacketType.Task); } - public void SendAdminResponse(UUID Token, uint AdminLevel) - { - GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); - GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); - GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); + #endregion - adb.AgentID = AgentId; - adb.SessionID = SessionId; // More security - gdb.GodLevel = (byte)AdminLevel; - gdb.Token = Token; - //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; - respondPacket.GrantData = gdb; - respondPacket.AgentData = adb; - OutPacket(respondPacket, ThrottleOutPacketType.Task); - } + #region Avatar Packet/data sending Methods - public void SendGroupMembership(GroupMembershipData[] GroupMembership) + /// + /// send a objectupdate packet with information about the clients avatar + /// + public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, + uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) { - m_groupPowers.Clear(); + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + objupdate.RegionData.RegionHandle = regionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); - AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); - AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; - for (int i = 0; i < GroupMembership.Length; i++) - { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatarLocalID; + objupdate.ObjectData[0].FullID = avatarID; + objupdate.ObjectData[0].ParentID = parentID; + objupdate.ObjectData[0].NameValue = + Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); - AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); - Group.AcceptNotices = GroupMembership[i].AcceptNotices; - Group.Contribution = GroupMembership[i].Contribution; - Group.GroupID = GroupMembership[i].GroupID; - Group.GroupInsigniaID = GroupMembership[i].GroupPicture; - Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); - Group.GroupPowers = GroupMembership[i].GroupPowers; - Groups[i] = Group; + Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); - } - Groupupdate.GroupData = Groups; - Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); - Groupupdate.AgentData.AgentID = AgentId; - OutPacket(Groupupdate, ThrottleOutPacketType.Task); + objupdate.Header.Zerocoded = true; + OutPacket(objupdate, ThrottleOutPacketType.Task); + } - try + /// + /// Send a terse positional/rotation/velocity update about an avatar + /// to the client. This avatar can be that of the client itself. + /// + public virtual void SendAvatarTerseUpdate(ulong regionHandle, + ushort timeDilation, uint localID, Vector3 position, + Vector3 velocity, Quaternion rotation, UUID agentid) + { + if (rotation.X == rotation.Y && + rotation.Y == rotation.Z && + rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; + + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = + CreateAvatarImprovedBlock(localID, position, velocity,rotation); + + lock (m_avatarTerseUpdates) { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) + m_avatarTerseUpdates.Add(terseBlock); + + // If packet is full or own movement packet, send it. + if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) { - eq.GroupMembership(Groupupdate, this.AgentId); + ProcessAvatarTerseUpdates(this, null); + } + else if (m_avatarTerseUpdates.Count == 1) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Start(); } } - catch (Exception ex) - { - m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending group membership data via UDP"); - OutPacket(Groupupdate, ThrottleOutPacketType.Task); - } - } - - - public void SendGroupNameReply(UUID groupLLUID, string GroupName) - { - UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); - UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; - UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); - uidnamebloc.ID = groupLLUID; - uidnamebloc.GroupName = Utils.StringToBytes(GroupName); - uidnameblock[0] = uidnamebloc; - pack.UUIDNameBlock = uidnameblock; - OutPacket(pack, ThrottleOutPacketType.Task); } - public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) + private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) { - LandStatReplyPacket lsrp = new LandStatReplyPacket(); - // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); - LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; - //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - // lsrepdb. - lsrp.RequestData.ReportType = reportType; - lsrp.RequestData.RequestFlags = requestFlags; - lsrp.RequestData.TotalObjectCount = resultCount; - for (int i = 0; i < lsrpia.Length; i++) + lock (m_avatarTerseUpdates) { - LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - lsrepdb.LocationX = lsrpia[i].LocationX; - lsrepdb.LocationY = lsrpia[i].LocationY; - lsrepdb.LocationZ = lsrpia[i].LocationZ; - lsrepdb.Score = lsrpia[i].Score; - lsrepdb.TaskID = lsrpia[i].TaskID; - lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; - lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); - lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); - lsrepdba[i] = lsrepdb; - } - lsrp.ReportData = lsrepdba; - OutPacket(lsrp, ThrottleOutPacketType.Task); - } + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) - { - ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); - scriptRunningReply.Script.ObjectID = objectID; - scriptRunningReply.Script.ItemID = itemID; - scriptRunningReply.Script.Running = running; + terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); - OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); - } + terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; + terse.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - public void SendAsset(AssetRequestToClient req) - { - //m_log.Debug("sending asset " + req.RequestAssetID); - TransferInfoPacket Transfer = new TransferInfoPacket(); - Transfer.TransferInfo.ChannelType = 2; - Transfer.TransferInfo.Status = 0; - Transfer.TransferInfo.TargetType = 0; - if (req.AssetRequestSource == 2) - { - Transfer.TransferInfo.Params = new byte[20]; - Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - int assType = req.AssetInf.Type; - Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); - } - else if (req.AssetRequestSource == 3) - { - Transfer.TransferInfo.Params = req.Params; - // Transfer.TransferInfo.Params = new byte[100]; - //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); - } - Transfer.TransferInfo.Size = req.AssetInf.Data.Length; - Transfer.TransferInfo.TransferID = req.TransferRequestID; - Transfer.Header.Zerocoded = true; - OutPacket(Transfer, ThrottleOutPacketType.Asset); + int max = m_avatarTerseUpdatesPerPacket; + if (max > m_avatarTerseUpdates.Count) + max = m_avatarTerseUpdates.Count; - if (req.NumPackets == 1) - { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 0; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; - TransferPacket.TransferData.Data = req.AssetInf.Data; - TransferPacket.TransferData.Status = 1; - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - } - else - { - int processedLength = 0; - int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; - int packetNumber = 0; + int count = 0; + int size = 0; - while (processedLength < req.AssetInf.Data.Length) + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + + for (count = 0 ; count < max ; count++) { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = packetNumber; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; + int length = 0; + m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } - int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); - byte[] chunk = new byte[chunkSize]; - Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; - TransferPacket.TransferData.Data = chunk; + for (int i = 0 ; i < count ; i++) + { + terse.ObjectData[i] = m_avatarTerseUpdates[0]; + m_avatarTerseUpdates.RemoveAt(0); + } - // 0 indicates more packets to come, 1 indicates last packet - if (req.AssetInf.Data.Length - processedLength > maxChunkSize) - { - TransferPacket.TransferData.Status = 0; - } - else - { - TransferPacket.TransferData.Status = 1; - } - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + terse.Header.Reliable = false; + terse.Header.Zerocoded = true; + OutPacket(terse, ThrottleOutPacketType.Task); - processedLength += chunkSize; - packetNumber++; + if (m_avatarTerseUpdates.Count == 0) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Stop(); } } } - public void SendTexture(AssetBase TextureAsset) - { - - } - - public void SendRegionHandle(UUID regionID, ulong handle) - { - RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); - reply.ReplyBlock.RegionID = regionID; - reply.ReplyBlock.RegionHandle = handle; - OutPacket(reply, ThrottleOutPacketType.Land); - } - - public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) + public void SendCoarseLocationUpdate(List users, List CoarseLocations) { - ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); - reply.AgentData.AgentID = m_agentId; - reply.Data.ParcelID = parcelID; - reply.Data.OwnerID = land.OwnerID; - reply.Data.Name = Utils.StringToBytes(land.Name); - reply.Data.Desc = Utils.StringToBytes(land.Description); - reply.Data.ActualArea = land.Area; - reply.Data.BillableArea = land.Area; // TODO: what is this? + if (!IsActive) return; // We don't need to update inactive clients. - // Bit 0: Mature, bit 7: on sale, other bits: no idea - reply.Data.Flags = (byte)( - ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + - ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); + // TODO: don't create new blocks if recycling an old packet + int total = CoarseLocations.Count; + CoarseLocationUpdatePacket.IndexBlock ib = + new CoarseLocationUpdatePacket.IndexBlock(); + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; - Vector3 pos = land.UserLocation; - if (pos.Equals(Vector3.Zero)) + for (int i = 0; i < total; i++) { - pos = (land.AABBMax + land.AABBMin) * 0.5f; + CoarseLocationUpdatePacket.LocationBlock lb = + new CoarseLocationUpdatePacket.LocationBlock(); + lb.X = (byte)CoarseLocations[i].X; + lb.Y = (byte)CoarseLocations[i].Y; + + lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); + loc.Location[i] = lb; + loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); + loc.AgentData[i].AgentID = users[i]; } - reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; - reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; - reply.Data.GlobalZ = pos.Z; - reply.Data.SimName = Utils.StringToBytes(info.RegionName); - reply.Data.SnapshotID = land.SnapshotID; - reply.Data.Dwell = land.Dwell; - reply.Data.SalePrice = land.SalePrice; - reply.Data.AuctionID = (int)land.AuctionID; + ib.You = -1; + ib.Prey = -1; + loc.Index = ib; + loc.Header.Reliable = false; + loc.Header.Zerocoded = true; - OutPacket(reply, ThrottleOutPacketType.Land); + OutPacket(loc, ThrottleOutPacketType.Task); } - public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) - { - ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); + #endregion - packet.Data.ObjectName = Utils.StringToBytes(objName); - packet.Data.SimName = Utils.StringToBytes(simName); - packet.Data.SimPosition = pos; - packet.Data.LookAt = lookAt; + #region Primitive Packet/data Sending Methods - OutPacket(packet, ThrottleOutPacketType.Task); + /// + /// + /// + /// + /// + /// + public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) + { + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; + + ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); + // TODO: don't create new blocks if recycling an old packet + attach.AgentData.AgentID = AgentId; + attach.AgentData.SessionID = m_sessionId; + attach.AgentData.AttachmentPoint = attachPoint; + attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; + attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); + attach.ObjectData[0].ObjectLocalID = localID; + attach.ObjectData[0].Rotation = rotation; + attach.Header.Zerocoded = true; + OutPacket(attach, ThrottleOutPacketType.Task); } - public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, + uint flags, UUID objectID, UUID ownerID, string text, byte[] color, + uint parentID, byte[] particleSystem, byte clickAction, byte material) { - DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + byte[] textureanim = new byte[0]; - packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, + acc, rotation, rvel, flags, + objectID, ownerID, text, color, parentID, particleSystem, + clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); + } - packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; - packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, + uint flags, + UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, + byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) + { - packet.QueryReplies = - new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; + if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; + if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) + return; - packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ - data.Length]; + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - packet.AgentData.AgentID = AgentId; + ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); - packet.QueryData[0].QueryID = queryID; + objectData.ID = localID; + objectData.FullID = objectID; + objectData.OwnerID = ownerID; - int i = 0; - foreach (DirPlacesReplyData d in data) + objectData.Text = LLUtil.StringToPacketBytes(text); + objectData.TextColor[0] = color[0]; + objectData.TextColor[1] = color[1]; + objectData.TextColor[2] = color[2]; + objectData.TextColor[3] = color[3]; + objectData.ParentID = parentID; + objectData.PSBlock = particleSystem; + objectData.ClickAction = clickAction; + objectData.Material = material; + objectData.Flags = 0; + + if (attachment) { - packet.QueryReplies[i] = - new DirPlacesReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].Dwell = d.dwell; - packet.StatusData[i].Status = d.Status; - i++; + // Necessary??? + objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); + objectData.JointPivot = new Vector3(0, 0, 0); + + // Item from inventory??? + objectData.NameValue = + Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); + objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); } - OutPacket(packet, ThrottleOutPacketType.Task); - } + // Xantor 20080528: Send sound info as well + // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again + objectData.Sound = SoundId; + if (SoundId == UUID.Zero) + { + objectData.OwnerID = UUID.Zero; + objectData.Gain = 0.0f; + objectData.Radius = 0.0f; + objectData.Flags = 0; + } + else + { + objectData.OwnerID = ownerID; + objectData.Gain = (float)SoundGain; + objectData.Radius = (float)SoundRadius; + objectData.Flags = SoundFlags; + } - public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) - { - DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); - packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + byte[] vel = velocity.GetBytes(); + Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); - packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); - packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ - data.Length]; + byte[] rvel = rotational_velocity.GetBytes(); + Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); - int i = 0; - foreach (DirPeopleReplyData d in data) + if (textureanim.Length > 0) { - packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].AgentID = d.agentID; - packet.QueryReplies[i].FirstName = - Utils.StringToBytes(d.firstName); - packet.QueryReplies[i].LastName = - Utils.StringToBytes(d.lastName); - packet.QueryReplies[i].Group = - Utils.StringToBytes(d.group); - packet.QueryReplies[i].Online = d.online; - packet.QueryReplies[i].Reputation = d.reputation; - i++; + objectData.TextureAnim = textureanim; } - OutPacket(packet, ThrottleOutPacketType.Task); - } - - public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) - { - DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); - - packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; - - packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; - - packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ - data.Length]; + lock (m_primFullUpdates) + { + if (m_primFullUpdates.Count == 0) + m_primFullUpdateTimer.Start(); - packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ - data.Length]; + m_primFullUpdates.Add(objectData); - int i = 0; - foreach (DirEventsReplyData d in data) - { - packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].OwnerID = d.ownerID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].EventID = d.eventID; - packet.QueryReplies[i].Date = - Utils.StringToBytes(d.date); - packet.QueryReplies[i].UnixTime = d.unixTime; - packet.QueryReplies[i].EventFlags = d.eventFlags; - packet.StatusData[i].Status = d.Status; - i++; + if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) + ProcessPrimFullUpdates(this, null); } - - OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) + void HandleQueueEmpty(ThrottleOutPacketType queue) { - DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); - - packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; - - packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; - - packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ - data.Length]; - - int i = 0; - foreach (DirGroupsReplyData d in data) + switch (queue) { - packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].GroupID = d.groupID; - packet.QueryReplies[i].GroupName = - Utils.StringToBytes(d.groupName); - packet.QueryReplies[i].Members = d.members; - packet.QueryReplies[i].SearchOrder = d.searchOrder; - i++; + case ThrottleOutPacketType.Texture: + ProcessTextureRequests(); + break; } + } - OutPacket(packet, ThrottleOutPacketType.Task); + void ProcessTextureRequests() + { + if (m_imageManager != null) + m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); } - public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) + void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) { - DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); + lock (m_primFullUpdates) + { + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) + { + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); - packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + return; + } - packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ - data.Length]; - packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ - data.Length]; + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - int i = 0; - foreach (DirClassifiedReplyData d in data) - { - packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ClassifiedID = d.classifiedID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; - packet.QueryReplies[i].CreationDate = d.creationDate; - packet.QueryReplies[i].ExpirationDate = d.expirationDate; - packet.QueryReplies[i].PriceForListing = d.price; - packet.StatusData[i].Status = d.Status; - i++; - } + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; - OutPacket(packet, ThrottleOutPacketType.Task); - } + int count = 0; + int size = 0; - public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) - { - DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + for (count = 0 ; count < max ; count++) + { + int length = 0; + m_primFullUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } - packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + outPacket.ObjectData = + new ObjectUpdatePacket.ObjectDataBlock[count]; - packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ - data.Length]; + for (int index = 0 ; index < count ; index++) + { + outPacket.ObjectData[index] = m_primFullUpdates[0]; + m_primFullUpdates.RemoveAt(0); + } - int i = 0; - foreach (DirLandReplyData d in data) - { - packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].SalePrice = d.salePrice; - packet.QueryReplies[i].ActualArea = d.actualArea; - i++; - } + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); - OutPacket(packet, ThrottleOutPacketType.Task); + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + } } - public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) + /// + /// + /// + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, + Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) { - DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); - - packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; - packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ - data.Length]; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = + CreatePrimImprovedBlock(localID, position, rotation, + velocity, rotationalvelocity, state); - int i = 0; - foreach (DirPopularReplyData d in data) + lock (m_primTerseUpdates) { - packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Dwell = d.dwell; - i++; - } + if (m_primTerseUpdates.Count == 0) + m_primTerseUpdateTimer.Start(); - OutPacket(packet, ThrottleOutPacketType.Task); + m_primTerseUpdates.Add(objectData); + + if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) + ProcessPrimTerseUpdates(this, null); + } } - public void SendEventInfoReply(EventData data) + void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { - EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); + lock (m_primTerseUpdates) + { + if (m_primTerseUpdates.Count == 0) + { + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); - packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + return; + } - packet.EventData = new EventInfoReplyPacket.EventDataBlock(); - packet.EventData.EventID = data.eventID; - packet.EventData.Creator = Utils.StringToBytes(data.creator); - packet.EventData.Name = Utils.StringToBytes(data.name); - packet.EventData.Category = Utils.StringToBytes(data.category); - packet.EventData.Desc = Utils.StringToBytes(data.description); - packet.EventData.Date = Utils.StringToBytes(data.date); - packet.EventData.DateUTC = data.dateUTC; - packet.EventData.Duration = data.duration; - packet.EventData.Cover = data.cover; - packet.EventData.Amount = data.amount; - packet.EventData.SimName = Utils.StringToBytes(data.simName); - packet.EventData.GlobalPos = new Vector3d(data.globalPos); - packet.EventData.EventFlags = data.eventFlags; + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); - OutPacket(packet, ThrottleOutPacketType.Task); + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); + + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; + + int count = 0; + int size = 0; + + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + + for (count = 0 ; count < max ; count++) + { + int length = 0; + m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } + + outPacket.ObjectData = + new ImprovedTerseObjectUpdatePacket. + ObjectDataBlock[count]; + + for (int index = 0 ; index < count ; index++) + { + outPacket.ObjectData[index] = m_primTerseUpdates[0]; + m_primTerseUpdates.RemoveAt(0); + } + + outPacket.Header.Reliable = false; + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + + if (m_primTerseUpdates.Count == 0) + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); + } } - public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) + public void FlushPrimUpdates() { - MapItemReplyPacket mirplk = new MapItemReplyPacket(); - mirplk.AgentData.AgentID = AgentId; - mirplk.RequestData.ItemType = mapitemtype; - mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; - for (int i = 0; i < replies.Length; i++) + while (m_primFullUpdates.Count > 0) { - MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); - mrdata.X = replies[i].x; - mrdata.Y = replies[i].y; - mrdata.ID = replies[i].id; - mrdata.Extra = replies[i].Extra; - mrdata.Extra2 = replies[i].Extra2; - mrdata.Name = Utils.StringToBytes(replies[i].name); - mirplk.Data[i] = mrdata; + ProcessPrimFullUpdates(this, null); + } + while (m_primTerseUpdates.Count > 0) + { + ProcessPrimTerseUpdates(this, null); + } + while (m_avatarTerseUpdates.Count > 0) + { + ProcessAvatarTerseUpdates(this, null); } - //m_log.Debug(mirplk.ToString()); - OutPacket(mirplk, ThrottleOutPacketType.Task); - } - public void SendOfferCallingCard(UUID srcID, UUID transactionID) + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) { - // a bit special, as this uses AgentID to store the source instead - // of the destination. The destination (the receiver) goes into destID - OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); - p.AgentData.AgentID = srcID; - p.AgentData.SessionID = UUID.Zero; - p.AgentBlock.DestID = AgentId; - p.AgentBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = AssetType; + newPack.AssetBlock.Success = Success; + newPack.AssetBlock.UUID = AssetFullID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - public void SendAcceptCallingCard(UUID transactionID) + public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) { - AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; - p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); - p.FolderData[0].FolderID = UUID.Zero; - OutPacket(p, ThrottleOutPacketType.Task); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = AssetType; + newPack.XferID.VFileID = vFileID; + newPack.XferID.FilePath = FilePath; + newPack.XferID.Filename = FileName; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - public void SendDeclineCallingCard(UUID transactionID) + public void SendConfirmXfer(ulong xferID, uint PacketID) { - DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.TransactionBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = PacketID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - - public void SendTerminateFriend(UUID exFriendID) + + public void SendInitiateDownload(string simFileName, string clientFileName) { - TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = SessionId; - p.ExBlock.OtherID = exFriendID; - OutPacket(p, ThrottleOutPacketType.Task); + InitiateDownloadPacket newPack = new InitiateDownloadPacket(); + newPack.AgentData.AgentID = AgentId; + newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); + newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); + OutPacket(newPack, ThrottleOutPacketType.Asset); } - - public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) + + public void SendImageFirstPart( + ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) { - AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = numParts; + im.ImageID.ID = ImageUUID; - p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; - p.AgentData.AvatarID = avatarID; + if (ImageSize > 0) + im.ImageID.Size = ImageSize; - p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; - int i = 0; - foreach (GroupMembershipData m in data) - { - p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); - p.GroupData[i].GroupPowers = m.GroupPowers; - p.GroupData[i].AcceptNotices = m.AcceptNotices; - p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); - p.GroupData[i].GroupID = m.GroupID; - p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); - p.GroupData[i].GroupInsigniaID = m.GroupPicture; - i++; - } + im.ImageData.Data = ImageData; + im.ImageID.Codec = imageCodec; + im.Header.Zerocoded = true; + OutPacket(im, ThrottleOutPacketType.Texture); + } - p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); - p.NewGroupData.ListInProfile = true; + public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) + { + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = partNumber; + im.ImageID.ID = imageUuid; + im.ImageData.Data = imageData; - OutPacket(p, ThrottleOutPacketType.Task); + OutPacket(im, ThrottleOutPacketType.Texture); } - public void SendJoinGroupReply(UUID groupID, bool success) + public void SendImageNotFound(UUID imageid) { - JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); + ImageNotInDatabasePacket notFoundPacket + = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); - p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + notFoundPacket.ImageID.ID = imageid; - p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); + } - OutPacket(p, ThrottleOutPacketType.Task); + public void SendShutdownConnectionNotice() + { + OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); } - public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) + public void SendSimStats(SimStats stats) { - EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); + SimStatsPacket pack = new SimStatsPacket(); + pack.Region = new SimStatsPacket.RegionBlock(); + pack.Region.RegionX = stats.RegionX; + pack.Region.RegionY = stats.RegionY; + pack.Region.RegionFlags = stats.RegionFlags; + pack.Region.ObjectCapacity = stats.ObjectCapacity; + //pack.Region = //stats.RegionBlock; + pack.Stat = stats.StatsBlock; - p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = agentID; + pack.Header.Reliable = false; - p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; + OutPacket(pack, ThrottleOutPacketType.Task); + } - p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); - p.EjectData.Success = success; + public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, + uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, + uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, + UUID LastOwnerID, string ObjectName, string Description) + { + ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); + // TODO: don't create new blocks if recycling an old packet - OutPacket(p, ThrottleOutPacketType.Task); + ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); + objPropDB.RequestFlags = RequestFlags; + objPropDB.ObjectID = ObjectUUID; + if (OwnerID == GroupID) + objPropDB.OwnerID = UUID.Zero; + else + objPropDB.OwnerID = OwnerID; + objPropDB.GroupID = GroupID; + objPropDB.BaseMask = BaseMask; + objPropDB.OwnerMask = OwnerMask; + objPropDB.GroupMask = GroupMask; + objPropDB.EveryoneMask = EveryoneMask; + objPropDB.NextOwnerMask = NextOwnerMask; + + // TODO: More properties are needed in SceneObjectPart! + objPropDB.OwnershipCost = OwnershipCost; + objPropDB.SaleType = SaleType; + objPropDB.SalePrice = SalePrice; + objPropDB.Category = Category; + objPropDB.LastOwnerID = LastOwnerID; + objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); + objPropDB.Description = LLUtil.StringToPacketBytes(Description); + objPropFamilyPack.ObjectData = objPropDB; + objPropFamilyPack.Header.Zerocoded = true; + OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); } - public void SendLeaveGroupReply(UUID groupID, bool success) + public void SendObjectPropertiesReply( + UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, + UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, + UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, + string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, + uint BaseMask, byte saleType, int salePrice) { - LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); + ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + // TODO: don't create new blocks if recycling an old packet - p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; + proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); + proper.ObjectData[0].ItemID = ItemID; + proper.ObjectData[0].CreationDate = CreationDate; + proper.ObjectData[0].CreatorID = CreatorUUID; + proper.ObjectData[0].FolderID = FolderUUID; + proper.ObjectData[0].FromTaskID = FromTaskUUID; + proper.ObjectData[0].GroupID = GroupUUID; + proper.ObjectData[0].InventorySerial = InventorySerial; - p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + proper.ObjectData[0].LastOwnerID = LastOwnerUUID; + // proper.ObjectData[0].LastOwnerID = UUID.Zero; - OutPacket(p, ThrottleOutPacketType.Task); + proper.ObjectData[0].ObjectID = ObjectUUID; + if (OwnerUUID == GroupUUID) + proper.ObjectData[0].OwnerID = UUID.Zero; + else + proper.ObjectData[0].OwnerID = OwnerUUID; + proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); + proper.ObjectData[0].TextureID = TextureID; + proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); + proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); + proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); + proper.ObjectData[0].OwnerMask = OwnerMask; + proper.ObjectData[0].NextOwnerMask = NextOwnerMask; + proper.ObjectData[0].GroupMask = GroupMask; + proper.ObjectData[0].EveryoneMask = EveryoneMask; + proper.ObjectData[0].BaseMask = BaseMask; + // proper.ObjectData[0].AggregatePerms = 53; + // proper.ObjectData[0].AggregatePermTextures = 0; + // proper.ObjectData[0].AggregatePermTexturesOwner = 0; + proper.ObjectData[0].SaleType = saleType; + proper.ObjectData[0].SalePrice = salePrice; + proper.Header.Zerocoded = true; + OutPacket(proper, ThrottleOutPacketType.Task); } - public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) - { - if (classifiedID.Length != name.Length) - return; - - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); + #endregion - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; + #region Estate Data Sending Methods - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; - int i; - for (i = 0; i < classifiedID.Length; i++) + private static bool convertParamStringToBool(byte[] field) + { + string s = Utils.BytesToString(field); + if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") { - ac.Data[i].ClassifiedID = classifiedID[i]; - ac.Data[i].Name = Utils.StringToBytes(name[i]); + return true; } - - OutPacket(ac, ThrottleOutPacketType.Task); + return false; } - public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) + public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) { - ClassifiedInfoReplyPacket cr = - (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ClassifiedInfoReply); + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); - cr.AgentData.AgentID = AgentId; + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; - cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); - cr.Data.ClassifiedID = classifiedID; - cr.Data.CreatorID = creatorID; - cr.Data.CreationDate = creationDate; - cr.Data.ExpirationDate = expirationDate; - cr.Data.Category = category; - cr.Data.Name = Utils.StringToBytes(name); - cr.Data.Desc = Utils.StringToBytes(description); - cr.Data.ParcelID = parcelID; - cr.Data.ParentEstate = parentEstate; - cr.Data.SnapshotID = snapshotID; - cr.Data.SimName = Utils.StringToBytes(simName); - cr.Data.PosGlobal = new Vector3d(globalPos); - cr.Data.ParcelName = Utils.StringToBytes(parcelName); - cr.Data.ClassifiedFlags = classifiedFlags; - cr.Data.PriceForListing = price; + for (int i = 0; i < (6 + EstateManagers.Length); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; - OutPacket(cr, ThrottleOutPacketType.Task); + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; + for (int i = 0; i < EstateManagers.Length; i++) + { + returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendAgentDropGroup(UUID groupID) + public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) { - AgentDropGroupPacket dg = - (AgentDropGroupPacket)PacketPool.Instance.GetPacket( - PacketType.AgentDropGroup); - - dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); - dg.AgentData.AgentID = AgentId; - dg.AgentData.GroupID = groupID; + ListBannedUsers = new List(); - OutPacket(dg, ThrottleOutPacketType.Task); - } + for (int i = 0; i < bl.Length; i++) + { + if (bl[i] == null) + continue; + if (bl[i].BannedUserID == UUID.Zero) + continue; + BannedUsers.Add(bl[i].BannedUserID); + } - public void SendAvatarNotesReply(UUID targetID, string text) - { - AvatarNotesReplyPacket an = - (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarNotesReply); - - an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); - an.AgentData.AgentID = AgentId; - - an.Data = new AvatarNotesReplyPacket.DataBlock(); - an.Data.TargetID = targetID; - an.Data.Notes = Utils.StringToBytes(text); - - OutPacket(an, ThrottleOutPacketType.Task); - } + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - public void SendAvatarPicksReply(UUID targetID, Dictionary picks) - { - AvatarPicksReplyPacket ap = - (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarPicksReply); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; - ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); - ap.AgentData.AgentID = AgentId; - ap.AgentData.TargetID = targetID; + for (int i = 0; i < (6 + BannedUsers.Count); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; - ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - int i = 0; - foreach (KeyValuePair pick in picks) + foreach (UUID banned in BannedUsers) { - ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); - ap.Data[i].PickID = pick.Key; - ap.Data[i].PickName = Utils.StringToBytes(pick.Value); - i++; + returnblock[j].Parameter = banned.GetBytes(); j++; } - - OutPacket(ap, ThrottleOutPacketType.Task); + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) { - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); - - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; + RegionInfoPacket rinfopack = new RegionInfoPacket(); + RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; + rinfoblk.BillableFactor = args.billableFactor; + rinfoblk.EstateID = args.estateID; + rinfoblk.MaxAgents = args.maxAgents; + rinfoblk.ObjectBonusFactor = args.objectBonusFactor; + rinfoblk.ParentEstateID = args.parentEstateID; + rinfoblk.PricePerMeter = args.pricePerMeter; + rinfoblk.RedirectGridX = args.redirectGridX; + rinfoblk.RedirectGridY = args.redirectGridY; + rinfoblk.RegionFlags = args.regionFlags; + rinfoblk.SimAccess = args.simAccess; + rinfoblk.SunHour = args.sunHour; + rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; + rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; + rinfoblk.UseEstateSun = args.useEstateSun; + rinfoblk.WaterHeight = args.waterHeight; + rinfoblk.SimName = Utils.StringToBytes(args.simName); + + rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); + rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; + rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; + rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; + rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; + rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; + rinfopack.HasVariableBlocks = true; + rinfopack.RegionInfo = rinfoblk; + rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; - int i = 0; - foreach (KeyValuePair classified in classifieds) - { - ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); - ac.Data[i].ClassifiedID = classified.Key; - ac.Data[i].Name = Utils.StringToBytes(classified.Value); - i++; - } - OutPacket(ac, ThrottleOutPacketType.Task); + OutPacket(rinfopack, ThrottleOutPacketType.Task); } - public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) + public void SendEstateCovenantInformation(UUID covenant) { - ParcelDwellReplyPacket pd = - (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ParcelDwellReply); - - pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); - pd.AgentData.AgentID = AgentId; - - pd.Data = new ParcelDwellReplyPacket.DataBlock(); - pd.Data.LocalID = localID; - pd.Data.ParcelID = parcelID; - pd.Data.Dwell = dwell; - - OutPacket(pd, ThrottleOutPacketType.Land); + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); + EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); + edata.CovenantID = covenant; + edata.CovenantTimestamp = 0; + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); + einfopack.Data = edata; + OutPacket(einfopack, ThrottleOutPacketType.Task); } - public void SendUserInfoReply(bool imViaEmail, bool visible, string email) + public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) { - UserInfoReplyPacket ur = - (UserInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.UserInfoReply); + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.MethodData.Invoice = invoice; + packet.AgentData.TransactionID = UUID.Random(); + packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; - string Visible = "hidden"; - if (visible) - Visible = "default"; + for (int i = 0; i < 10; i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } - ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); - ur.AgentData.AgentID = AgentId; + //Sending Estate Settings + returnblock[0].Parameter = Utils.StringToBytes(estateName); + // TODO: remove this cruft once MasterAvatar is fully deprecated + // + returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); + returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); - ur.UserData = new UserInfoReplyPacket.UserDataBlock(); - ur.UserData.IMViaEMail = imViaEmail; - ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); - ur.UserData.EMail = Utils.StringToBytes(email); + returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); + returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); + returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); + returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); + returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? + returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? + returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); - OutPacket(ur, ThrottleOutPacketType.Task); + packet.ParamList = returnblock; + packet.Header.Reliable = false; + //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendCreateGroupReply(UUID groupID, bool success, string message) - { - CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); - - createGroupReply.AgentData = - new CreateGroupReplyPacket.AgentDataBlock(); - createGroupReply.ReplyData = - new CreateGroupReplyPacket.ReplyDataBlock(); + #endregion - createGroupReply.AgentData.AgentID = AgentId; - createGroupReply.ReplyData.GroupID = groupID; + #region Land Data Sending Methods - createGroupReply.ReplyData.Success = success; - createGroupReply.ReplyData.Message = Utils.StringToBytes(message); - OutPacket(createGroupReply, ThrottleOutPacketType.Task); + public void SendLandParcelOverlay(byte[] data, int sequence_id) + { + ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); + packet.ParcelData.Data = data; + packet.ParcelData.SequenceID = sequence_id; + packet.Header.Zerocoded = true; + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendUseCachedMuteList() + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) { - UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); - - useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); - useCachedMuteList.AgentData.AgentID = AgentId; + ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); + // TODO: don't create new blocks if recycling an old packet - OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); - } + updatePacket.ParcelData.AABBMax = landData.AABBMax; + updatePacket.ParcelData.AABBMin = landData.AABBMin; + updatePacket.ParcelData.Area = landData.Area; + updatePacket.ParcelData.AuctionID = landData.AuctionID; + updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; - public void SendMuteListUpdate(string filename) - { - MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); + updatePacket.ParcelData.Bitmap = landData.Bitmap; - muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); - muteListUpdate.MuteData.AgentID = AgentId; - muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); + updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); + updatePacket.ParcelData.Category = (byte)landData.Category; + updatePacket.ParcelData.ClaimDate = landData.ClaimDate; + updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; + updatePacket.ParcelData.GroupID = landData.GroupID; + updatePacket.ParcelData.GroupPrims = landData.GroupPrims; + updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; + updatePacket.ParcelData.LandingType = landData.LandingType; + updatePacket.ParcelData.LocalID = landData.LocalID; - OutPacket(muteListUpdate, ThrottleOutPacketType.Task); - } + if (landData.Area > 0) + { + updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.MaxPrims = 0; + } - public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) - { - PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); + updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; + updatePacket.ParcelData.MediaID = landData.MediaID; + updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); + updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); + updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); + updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; + updatePacket.ParcelData.OtherCount = 0; //unemplemented + updatePacket.ParcelData.OtherPrims = landData.OtherPrims; + updatePacket.ParcelData.OwnerID = landData.OwnerID; + updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; + updatePacket.ParcelData.ParcelFlags = landData.Flags; + updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; + updatePacket.ParcelData.PassHours = landData.PassHours; + updatePacket.ParcelData.PassPrice = landData.PassPrice; + updatePacket.ParcelData.PublicCount = 0; //unemplemented - pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); - pickInfoReply.AgentData.AgentID = AgentId; + updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > + 0); + updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > + 0); + updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) > + 0); + updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) > + 0); - pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); - pickInfoReply.Data.PickID = pickID; - pickInfoReply.Data.CreatorID = creatorID; - pickInfoReply.Data.TopPick = topPick; - pickInfoReply.Data.ParcelID = parcelID; - pickInfoReply.Data.Name = Utils.StringToBytes(name); - pickInfoReply.Data.Desc = Utils.StringToBytes(desc); - pickInfoReply.Data.SnapshotID = snapshotID; - pickInfoReply.Data.User = Utils.StringToBytes(user); - pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); - pickInfoReply.Data.SimName = Utils.StringToBytes(simName); - pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); - pickInfoReply.Data.SortOrder = sortOrder; - pickInfoReply.Data.Enabled = enabled; + updatePacket.ParcelData.RentPrice = 0; + updatePacket.ParcelData.RequestResult = request_result; + updatePacket.ParcelData.SalePrice = landData.SalePrice; + updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; + updatePacket.ParcelData.SelfCount = 0; //unemplemented + updatePacket.ParcelData.SequenceID = sequence_id; + if (landData.SimwideArea > 0) + { + updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.SimWideMaxPrims = 0; + } + updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; + updatePacket.ParcelData.SnapSelection = snap_selection; + updatePacket.ParcelData.SnapshotID = landData.SnapshotID; + updatePacket.ParcelData.Status = (byte)landData.Status; + updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + + landData.SelectedPrims; + updatePacket.ParcelData.UserLocation = landData.UserLocation; + updatePacket.ParcelData.UserLookAt = landData.UserLookAt; + updatePacket.Header.Zerocoded = true; - OutPacket(pickInfoReply, ThrottleOutPacketType.Task); + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + eq.ParcelProperties(updatePacket, this.AgentId); + } + } + catch (Exception ex) + { + m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending parcel data via UDP"); + OutPacket(updatePacket, ThrottleOutPacketType.Task); + } } - #endregion Scene/Avatar to Client - - // Gesture - - #region Appearance/ Wearables Methods - - public void SendWearables(AvatarWearable[] wearables, int serial) + public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) { - AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); - aw.AgentData.AgentID = AgentId; - aw.AgentData.SerialNum = (uint)serial; - aw.AgentData.SessionID = m_sessionId; + ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); + replyPacket.Data.AgentID = AgentId; + replyPacket.Data.Flags = accessFlag; + replyPacket.Data.LocalID = localLandID; + replyPacket.Data.SequenceID = 0; - // TODO: don't create new blocks if recycling an old packet - aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; - AgentWearablesUpdatePacket.WearableDataBlock awb; - for (int i = 0; i < wearables.Length; i++) + List list = new List(); + foreach (UUID avatar in avatars) { - awb = new AgentWearablesUpdatePacket.WearableDataBlock(); - awb.WearableType = (byte)i; - awb.AssetID = wearables[i].AssetID; - awb.ItemID = wearables[i].ItemID; - aw.WearableData[i] = awb; - -// m_log.DebugFormat( -// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", -// awb.ItemID, awb.AssetID, i, Name); + ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); + block.Flags = accessFlag; + block.ID = avatar; + block.Time = 0; + list.Add(block); } - OutPacket(aw, ThrottleOutPacketType.Task); + replyPacket.List = list.ToArray(); + replyPacket.Header.Zerocoded = true; + OutPacket(replyPacket, ThrottleOutPacketType.Task); } - public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) + public void SendForceClientSelectObjects(List ObjectIDs) { - AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); - // TODO: don't create new blocks if recycling an old packet - avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; - avp.ObjectData.TextureEntry = textureEntry; - - AvatarAppearancePacket.VisualParamBlock avblock = null; - for (int i = 0; i < visualParams.Length; i++) + bool firstCall = true; + const int MAX_OBJECTS_PER_PACKET = 251; + ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); + ForceObjectSelectPacket.DataBlock[] data; + while (ObjectIDs.Count > 0) { - avblock = new AvatarAppearancePacket.VisualParamBlock(); - avblock.ParamValue = visualParams[i]; - avp.VisualParam[i] = avblock; + if (firstCall) + { + pack._Header.ResetList = true; + firstCall = false; + } + else + { + pack._Header.ResetList = false; + } + + if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) + { + data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; + } + else + { + data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; + } + + int i; + for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) + { + data[i] = new ForceObjectSelectPacket.DataBlock(); + data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); + ObjectIDs.RemoveAt(0); + } + pack.Data = data; + pack.Header.Zerocoded = true; + OutPacket(pack, ThrottleOutPacketType.Task); } + } - avp.Sender.IsTrial = false; - avp.Sender.ID = agentID; - OutPacket(avp, ThrottleOutPacketType.Task); + public void SendCameraConstraint(Vector4 ConstraintPlane) + { + CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); + cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); + cpack.CameraCollidePlane.Plane = ConstraintPlane; + //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); + OutPacket(cpack, ThrottleOutPacketType.Task); } - public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) { - //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); + - AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); - // TODO: don't create new blocks if recycling an old packet - ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; - ani.Sender = new AvatarAnimationPacket.SenderBlock(); - ani.Sender.ID = sourceAgentId; - ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; - ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; + int notifyCount = ownersAndCount.Count; + ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); - for (int i = 0; i < animations.Length; ++i) + if (notifyCount > 0) { - ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); - ani.AnimationList[i].AnimID = animations[i]; - ani.AnimationList[i].AnimSequenceID = seqs[i]; + if (notifyCount > 32) + { + m_log.InfoFormat( + "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" + + " - a developer might want to investigate whether this is a hard limit", 32); - ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); - ani.AnimationSourceList[i].ObjectID = objectIDs[i]; - if (objectIDs[i] == UUID.Zero) - ani.AnimationSourceList[i].ObjectID = sourceAgentId; - } - ani.Header.Reliable = false; - OutPacket(ani, ThrottleOutPacketType.Task); - } + notifyCount = 32; + } - #endregion + ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock + = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; - #region Avatar Packet/data sending Methods + int num = 0; + foreach (UUID owner in ownersAndCount.Keys) + { + dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); + dataBlock[num].Count = ownersAndCount[owner]; - /// - /// send a objectupdate packet with information about the clients avatar - /// - public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, - uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) - { - ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - // TODO: don't create new blocks if recycling an old packet - objupdate.RegionData.RegionHandle = regionHandle; - objupdate.RegionData.TimeDilation = ushort.MaxValue; - objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); + if (land.GroupID == owner || groups.Contains(owner)) + dataBlock[num].IsGroupOwned = true; - //give this avatar object a local id and assign the user a name - objupdate.ObjectData[0].ID = avatarLocalID; - objupdate.ObjectData[0].FullID = avatarID; - objupdate.ObjectData[0].ParentID = parentID; - objupdate.ObjectData[0].NameValue = - Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); + dataBlock[num].OnlineStatus = true; //TODO: fix me later + dataBlock[num].OwnerID = owner; - Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); - byte[] pb = pos2.GetBytes(); - Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + num++; - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); + if (num >= notifyCount) + { + break; + } + } - objupdate.Header.Zerocoded = true; - OutPacket(objupdate, ThrottleOutPacketType.Task); + pack.Data = dataBlock; + } + pack.Header.Zerocoded = true; + this.OutPacket(pack, ThrottleOutPacketType.Task); } - /// - /// Send a terse positional/rotation/velocity update about an avatar - /// to the client. This avatar can be that of the client itself. - /// - public virtual void SendAvatarTerseUpdate(ulong regionHandle, - ushort timeDilation, uint localID, Vector3 position, - Vector3 velocity, Quaternion rotation, UUID agentid) + #endregion + + #region Helper Methods + + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, + Vector3 velocity, + Quaternion rotation) { - if (rotation.X == rotation.Y && - rotation.Y == rotation.Z && - rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + byte[] bytes = new byte[60]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = - CreateAvatarImprovedBlock(localID, position, velocity,rotation); - - lock (m_avatarTerseUpdates) - { - m_avatarTerseUpdates.Add(terseBlock); + dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; - // If packet is full or own movement packet, send it. - if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) - { - ProcessAvatarTerseUpdates(this, null); - } - else if (m_avatarTerseUpdates.Count == 1) - { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Start(); - } - } - } - - private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) - { - lock (m_avatarTerseUpdates) - { - ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - - terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); - - terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; - terse.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); - - int max = m_avatarTerseUpdatesPerPacket; - if (max > m_avatarTerseUpdates.Count) - max = m_avatarTerseUpdates.Count; + uint ID = localID; - int count = 0; - int size = 0; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = 0; + bytes[i++] = 1; + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); - terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; + internDirec = internDirec / 128.0f; + internDirec.X += 1; + internDirec.Y += 1; + internDirec.Z += 1; - for (int i = 0 ; i < count ; i++) - { - terse.ObjectData[i] = m_avatarTerseUpdates[0]; - m_avatarTerseUpdates.RemoveAt(0); - } + ushort InternVelocityX = (ushort)(32768 * internDirec.X); + ushort InternVelocityY = (ushort)(32768 * internDirec.Y); + ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); - terse.Header.Reliable = false; - terse.Header.Zerocoded = true; - OutPacket(terse, ThrottleOutPacketType.Task); + ushort ac = 32767; + bytes[i++] = (byte)(InternVelocityX % 256); + bytes[i++] = (byte)((InternVelocityX >> 8) % 256); + bytes[i++] = (byte)(InternVelocityY % 256); + bytes[i++] = (byte)((InternVelocityY >> 8) % 256); + bytes[i++] = (byte)(InternVelocityZ % 256); + bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); - if (m_avatarTerseUpdates.Count == 0) - { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Stop(); - } - } - } + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - public void SendCoarseLocationUpdate(List users, List CoarseLocations) - { - if (!IsActive) return; // We don't need to update inactive clients. + //rotation + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); - // TODO: don't create new blocks if recycling an old packet - int total = CoarseLocations.Count; - CoarseLocationUpdatePacket.IndexBlock ib = - new CoarseLocationUpdatePacket.IndexBlock(); - loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; - loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - for (int i = 0; i < total; i++) - { - CoarseLocationUpdatePacket.LocationBlock lb = - new CoarseLocationUpdatePacket.LocationBlock(); - lb.X = (byte)CoarseLocations[i].X; - lb.Y = (byte)CoarseLocations[i].Y; + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); - loc.Location[i] = lb; - loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); - loc.AgentData[i].AgentID = users[i]; - } - ib.You = -1; - ib.Prey = -1; - loc.Index = ib; - loc.Header.Reliable = false; - loc.Header.Zerocoded = true; + dat.Data = bytes; - OutPacket(loc, ThrottleOutPacketType.Task); + return (dat); } - #endregion - - #region Primitive Packet/data Sending Methods - /// /// /// /// + /// /// - /// - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) + /// + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, + Vector3 position, + Quaternion rotation, + Vector3 velocity, + Vector3 rotationalvelocity, + byte state) { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; + uint ID = localID; + byte[] bytes = new byte[60]; - ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); - // TODO: don't create new blocks if recycling an old packet - attach.AgentData.AgentID = AgentId; - attach.AgentData.SessionID = m_sessionId; - attach.AgentData.AttachmentPoint = attachPoint; - attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; - attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); - attach.ObjectData[0].ObjectLocalID = localID; - attach.ObjectData[0].Rotation = rotation; - attach.Header.Zerocoded = true; - OutPacket(attach, ThrottleOutPacketType.Task); - } + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); + dat.TextureEntry = new byte[0]; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); + bytes[i++] = 0; - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, - uint flags, UUID objectID, UUID ownerID, string text, byte[] color, - uint parentID, byte[] particleSystem, byte clickAction, byte material) - { - byte[] textureanim = new byte[0]; + byte[] pb = position.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; - SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, - acc, rotation, rvel, flags, - objectID, ownerID, text, color, parentID, particleSystem, - clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); - } + ushort velx, vely, velz; + Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, - uint flags, - UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, - byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) - { + vel = vel / 128.0f; + vel.X += 1; + vel.Y += 1; + vel.Z += 1; + //vel + velx = (ushort)(32768 * (vel.X)); + vely = (ushort)(32768 * (vel.Y)); + velz = (ushort)(32768 * (vel.Z)); - if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) - return; + bytes[i++] = (byte)(velx % 256); + bytes[i++] = (byte)((velx >> 8) % 256); + bytes[i++] = (byte)(vely % 256); + bytes[i++] = (byte)((vely >> 8) % 256); + bytes[i++] = (byte)(velz % 256); + bytes[i++] = (byte)((velz >> 8) % 256); - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - objectData.ID = localID; - objectData.FullID = objectID; - objectData.OwnerID = ownerID; + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - objectData.Text = Util.StringToBytes256(text); - objectData.TextColor[0] = color[0]; - objectData.TextColor[1] = color[1]; - objectData.TextColor[2] = color[2]; - objectData.TextColor[3] = color[3]; - objectData.ParentID = parentID; - objectData.PSBlock = particleSystem; - objectData.ClickAction = clickAction; - objectData.Material = material; - objectData.Flags = 0; + //rotation vel + Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); - if (attachment) - { - // Necessary??? - objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); - objectData.JointPivot = new Vector3(0, 0, 0); + rvel = rvel / 128.0f; + rvel.X += 1; + rvel.Y += 1; + rvel.Z += 1; + //vel + ushort rvelx = (ushort)(32768 * (rvel.X)); + ushort rvely = (ushort)(32768 * (rvel.Y)); + ushort rvelz = (ushort)(32768 * (rvel.Z)); - // Item from inventory??? - objectData.NameValue = - Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); - objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); - } + bytes[i++] = (byte)(rvelx % 256); + bytes[i++] = (byte)((rvelx >> 8) % 256); + bytes[i++] = (byte)(rvely % 256); + bytes[i++] = (byte)((rvely >> 8) % 256); + bytes[i++] = (byte)(rvelz % 256); + bytes[i++] = (byte)((rvelz >> 8) % 256); + dat.Data = bytes; - // Xantor 20080528: Send sound info as well - // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again - objectData.Sound = SoundId; - if (SoundId == UUID.Zero) - { - objectData.OwnerID = UUID.Zero; - objectData.Gain = 0.0f; - objectData.Radius = 0.0f; - objectData.Flags = 0; - } - else + return dat; + } + + /// + /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + { + ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); + SetDefaultPrimPacketValues(objupdate); + objupdate.UpdateFlags = flags; + SetPrimPacketShapeData(objupdate, primShape); + + if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) { - objectData.OwnerID = ownerID; - objectData.Gain = (float)SoundGain; - objectData.Radius = (float)SoundRadius; - objectData.Flags = SoundFlags; + objupdate.Data = new byte[1]; + objupdate.Data[0] = primShape.State; } + return objupdate; + } - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); + protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) + { + objectData.TextureEntry = primData.TextureEntry; + objectData.PCode = primData.PCode; + objectData.State = primData.State; + objectData.PathBegin = primData.PathBegin; + objectData.PathEnd = primData.PathEnd; + objectData.PathScaleX = primData.PathScaleX; + objectData.PathScaleY = primData.PathScaleY; + objectData.PathShearX = primData.PathShearX; + objectData.PathShearY = primData.PathShearY; + objectData.PathSkew = primData.PathSkew; + objectData.ProfileBegin = primData.ProfileBegin; + objectData.ProfileEnd = primData.ProfileEnd; + objectData.Scale = primData.Scale; + objectData.PathCurve = primData.PathCurve; + objectData.ProfileCurve = primData.ProfileCurve; + objectData.ProfileHollow = primData.ProfileHollow; + objectData.PathRadiusOffset = primData.PathRadiusOffset; + objectData.PathRevolutions = primData.PathRevolutions; + objectData.PathTaperX = primData.PathTaperX; + objectData.PathTaperY = primData.PathTaperY; + objectData.PathTwist = primData.PathTwist; + objectData.PathTwistBegin = primData.PathTwistBegin; + objectData.ExtraParams = primData.ExtraParams; + } - byte[] vel = velocity.GetBytes(); - Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); + /// + /// Set some default values in a ObjectUpdatePacket + /// + /// + protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 3; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + objdata.State = 0; + objdata.Data = new byte[0]; - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); + objdata.ObjectData = new byte[60]; + objdata.ObjectData[46] = 128; + objdata.ObjectData[47] = 63; + } - byte[] rvel = rotational_velocity.GetBytes(); - Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); + /// + /// + /// + /// + public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + { + ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); + // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - if (textureanim.Length > 0) + SetDefaultAvatarPacketValues(ref objdata); + objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objdata.PathCurve = 16; + objdata.ProfileCurve = 1; + objdata.PathScaleX = 100; + objdata.PathScaleY = 100; + objdata.ParentID = 0; + objdata.OwnerID = UUID.Zero; + objdata.Scale = new Vector3(1, 1, 1); + objdata.PCode = (byte)PCode.Avatar; + if (textureEntry != null) { - objectData.TextureAnim = textureanim; + objdata.TextureEntry = textureEntry; } + Vector3 pos = new Vector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); + //Vector3 pos2 = new Vector3(100f, 100f, 23f); + //objdata.FullID=user.AgentId; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); - lock (m_primFullUpdates) - { - if (m_primFullUpdates.Count == 0) - m_primFullUpdateTimer.Start(); + return objdata; + } - m_primFullUpdates.Add(objectData); + /// + /// + /// + /// + protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 4; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); + objdata.TextureEntry = ntex.GetBytes(); - if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - ProcessPrimFullUpdates(this, null); - } + objdata.State = 0; + objdata.Data = new byte[0]; + + objdata.ObjectData = new byte[76]; + objdata.ObjectData[15] = 128; + objdata.ObjectData[16] = 63; + objdata.ObjectData[56] = 128; + objdata.ObjectData[61] = 102; + objdata.ObjectData[62] = 40; + objdata.ObjectData[63] = 61; + objdata.ObjectData[64] = 189; } - void HandleQueueEmpty(ThrottleOutPacketType queue) + public void SendNameReply(UUID profileId, string firstname, string lastname) { - switch (queue) - { - case ThrottleOutPacketType.Texture: - ProcessTextureRequests(); - break; - } + UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); + // TODO: don't create new blocks if recycling an old packet + packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; + packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); + packet.UUIDNameBlock[0].ID = profileId; + packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); + packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); + + OutPacket(packet, ThrottleOutPacketType.Task); } - void ProcessTextureRequests() + #endregion + + /// + /// This is a different way of processing packets then ProcessInPacket + /// + protected virtual void RegisterLocalPacketHandlers() { - if (m_imageManager != null) - m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); + AddLocalPacketHandler(PacketType.LogoutRequest, Logout); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); + AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); + AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); + AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); } - void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) + private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) { - lock (m_primFullUpdates) + MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; + // validate the agent owns the agentID and sessionID + if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && + money.AgentData.SessionID == sender.SessionId) { - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) + handlerMoneyTransferRequest = OnMoneyTransferRequest; + if (handlerMoneyTransferRequest != null) { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - - return; + handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, + money.MoneyData.Amount, money.MoneyData.TransactionType, + Util.FieldToString(money.MoneyData.Description)); } - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); - - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + return true; + } - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + return false; + } - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; - - for (count = 0 ; count < max ; count++) + private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) + { + ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; + if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) + { + handlerParcelBuy = OnParcelBuy; + if (handlerParcelBuy != null) { - int length = 0; - m_primFullUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; + handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, + parcel.Data.IsGroupOwned, + parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, + parcel.ParcelData.Price, + false); } + return true; + } + return false; + } - outPacket.ObjectData = - new ObjectUpdatePacket.ObjectDataBlock[count]; + private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) + { + UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; + - for (int index = 0 ; index < count ; index++) + for (int i = 0; i < upack.UUIDNameBlock.Length; i++) + { + handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; + if (handlerUUIDGroupNameRequest != null) { - outPacket.ObjectData[index] = m_primFullUpdates[0]; - m_primFullUpdates.RemoveAt(0); + handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); } - - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task); - - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); } + + return true; } - /// - /// - /// - public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, - Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) + public bool HandleGenericMessage(IClientAPI sender, Packet pack) { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; + GenericMessagePacket gmpack = (GenericMessagePacket) pack; + if (m_genericPacketHandlers.Count == 0) return false; + if (gmpack.AgentData.SessionID != SessionId) return false; - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + handlerGenericMessage = null; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = - CreatePrimImprovedBlock(localID, position, rotation, - velocity, rotationalvelocity, state); + string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); - lock (m_primTerseUpdates) + if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) { - if (m_primTerseUpdates.Count == 0) - m_primTerseUpdateTimer.Start(); - - m_primTerseUpdates.Add(objectData); + List msg = new List(); + List msgBytes = new List(); - if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - ProcessPrimTerseUpdates(this, null); + if (handlerGenericMessage != null) + { + foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) + { + msg.Add(Util.FieldToString(block.Parameter)); + msgBytes.Add(block.Parameter); + } + try + { + if (OnBinaryGenericMessage != null) + { + OnBinaryGenericMessage(this, method, msgBytes.ToArray()); + } + handlerGenericMessage(sender, method, msg); + return true; + } + catch (Exception e) + { + m_log.Error("[GENERICMESSAGE] " + e); + } + } } + m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); + return false; } - void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) + public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) { - lock (m_primTerseUpdates) + + ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; + if (ogpack.AgentData.SessionID != SessionId) return false; + + handlerObjectGroupRequest = OnObjectGroupRequest; + if (handlerObjectGroupRequest != null) { - if (m_primTerseUpdates.Count == 0) + for (int i = 0; i < ogpack.ObjectData.Length; i++) { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); - - return; + handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); } + } + return true; + } - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); - - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); - - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; - - int count = 0; - int size = 0; - - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; - - for (count = 0 ; count < max ; count++) + private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + { + ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; + if (viewer.AgentData.SessionID != SessionId) return false; + handlerViewerEffect = OnViewerEffect; + if (handlerViewerEffect != null) + { + int length = viewer.Effect.Length; + List args = new List(length); + for (int i = 0; i < length; i++) { - int length = 0; - m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; + //copy the effects block arguments into the event handler arg. + ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); + argument.AgentID = viewer.Effect[i].AgentID; + argument.Color = viewer.Effect[i].Color; + argument.Duration = viewer.Effect[i].Duration; + argument.ID = viewer.Effect[i].ID; + argument.Type = viewer.Effect[i].Type; + argument.TypeData = viewer.Effect[i].TypeData; + args.Add(argument); } - outPacket.ObjectData = - new ImprovedTerseObjectUpdatePacket. - ObjectDataBlock[count]; + handlerViewerEffect(sender, args); + } - for (int index = 0 ; index < count ; index++) - { - outPacket.ObjectData[index] = m_primTerseUpdates[0]; - m_primTerseUpdates.RemoveAt(0); - } + return true; + } - outPacket.Header.Reliable = false; - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task); + public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) + { + ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); + scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); + // TODO: don't create new blocks if recycling an old packet + scriptQuestion.Data.TaskID = taskID; + scriptQuestion.Data.ItemID = itemID; + scriptQuestion.Data.Questions = question; + scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); + scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); - if (m_primTerseUpdates.Count == 0) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); - } + OutPacket(scriptQuestion, ThrottleOutPacketType.Task); } - public void FlushPrimUpdates() + private void InitDefaultAnimations() { - while (m_primFullUpdates.Count > 0) - { - ProcessPrimFullUpdates(this, null); - } - while (m_primTerseUpdates.Count > 0) - { - ProcessPrimTerseUpdates(this, null); - } - while (m_avatarTerseUpdates.Count > 0) + using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) { - ProcessAvatarTerseUpdates(this, null); + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + if (doc.DocumentElement != null) + foreach (XmlNode nod in doc.DocumentElement.ChildNodes) + { + if (nod.Attributes["name"] != null) + { + string name = nod.Attributes["name"].Value.ToLower(); + string id = nod.InnerText; + m_defaultAnimations.Add(name, (UUID)id); + } + } } } - public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) + public UUID GetDefaultAnimation(string name) { - AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); - newPack.AssetBlock.Type = AssetType; - newPack.AssetBlock.Success = Success; - newPack.AssetBlock.UUID = AssetFullID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + if (m_defaultAnimations.ContainsKey(name)) + return m_defaultAnimations[name]; + return UUID.Zero; } - public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) + /// + /// Handler called when we receive a logout packet. + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client, Packet packet) { - RequestXferPacket newPack = new RequestXferPacket(); - newPack.XferID.ID = XferID; - newPack.XferID.VFileType = AssetType; - newPack.XferID.VFileID = vFileID; - newPack.XferID.FilePath = FilePath; - newPack.XferID.Filename = FileName; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + if (packet.Type == PacketType.LogoutRequest) + { + if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; + } + + return Logout(client); } - public void SendConfirmXfer(ulong xferID, uint PacketID) + /// + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client) { - ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); - newPack.XferID.ID = xferID; - newPack.XferID.Packet = PacketID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); - } - - public void SendInitiateDownload(string simFileName, string clientFileName) - { - InitiateDownloadPacket newPack = new InitiateDownloadPacket(); - newPack.AgentData.AgentID = AgentId; - newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); - newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); - OutPacket(newPack, ThrottleOutPacketType.Asset); - } - - public void SendImageFirstPart( - ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = numParts; - im.ImageID.ID = ImageUUID; + m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); - if (ImageSize > 0) - im.ImageID.Size = ImageSize; + handlerLogout = OnLogout; - im.ImageData.Data = ImageData; - im.ImageID.Codec = imageCodec; - im.Header.Zerocoded = true; - OutPacket(im, ThrottleOutPacketType.Texture); + if (handlerLogout != null) + { + handlerLogout(client); + } + + return true; } - public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) + /// + /// Send a response back to a client when it asks the asset server (via the region server) if it has + /// its appearance texture cached. + /// + /// At the moment, we always reply that there is no cached texture. + /// + /// + /// + /// + protected bool AgentTextureCached(IClientAPI simclient, Packet packet) { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = partNumber; - im.ImageID.ID = imageUuid; - im.ImageData.Data = imageData; + //m_log.Debug("texture cached: " + packet.ToString()); + AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); - OutPacket(im, ThrottleOutPacketType.Texture); - } + if (cachedtex.AgentData.SessionID != SessionId) return false; - public void SendImageNotFound(UUID imageid) - { - ImageNotInDatabasePacket notFoundPacket - = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); + // TODO: don't create new blocks if recycling an old packet + cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.SessionID = m_sessionId; + cachedresp.AgentData.SerialNum = m_cachedTextureSerial; + m_cachedTextureSerial++; + cachedresp.WearableData = + new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - notFoundPacket.ImageID.ID = imageid; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } - OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); + cachedresp.Header.Zerocoded = true; + OutPacket(cachedresp, ThrottleOutPacketType.Task); + + return true; } - public void SendShutdownConnectionNotice() + protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) { - OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); - } + MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; + if (multipleupdate.AgentData.SessionID != SessionId) return false; + // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + Scene tScene = (Scene)m_scene; - public void SendSimStats(SimStats stats) - { - SimStatsPacket pack = new SimStatsPacket(); - pack.Region = new SimStatsPacket.RegionBlock(); - pack.Region.RegionX = stats.RegionX; - pack.Region.RegionY = stats.RegionY; - pack.Region.RegionFlags = stats.RegionFlags; - pack.Region.ObjectCapacity = stats.ObjectCapacity; - //pack.Region = //stats.RegionBlock; - pack.Stat = stats.StatsBlock; + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; - pack.Header.Reliable = false; + // Can't act on Null Data + if (block.Data != null) + { + uint localId = block.ObjectLocalID; + SceneObjectPart part = tScene.GetSceneObjectPart(localId); - OutPacket(pack, ThrottleOutPacketType.Task); - } + if (part == null) + { + // It's a ghost! tell the client to delete it from view. + simClient.SendKillObject(Scene.RegionInfo.RegionHandle, + localId); + } + else + { + // UUID partId = part.UUID; + UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; - public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, - uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, - uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, - UUID LastOwnerID, string ObjectName, string Description) - { - ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); - // TODO: don't create new blocks if recycling an old packet + switch (block.Type) + { + case 1: + Vector3 pos1 = new Vector3(block.Data, 0); - ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); - objPropDB.RequestFlags = RequestFlags; - objPropDB.ObjectID = ObjectUUID; - if (OwnerID == GroupID) - objPropDB.OwnerID = UUID.Zero; - else - objPropDB.OwnerID = OwnerID; - objPropDB.GroupID = GroupID; - objPropDB.BaseMask = BaseMask; - objPropDB.OwnerMask = OwnerMask; - objPropDB.GroupMask = GroupMask; - objPropDB.EveryoneMask = EveryoneMask; - objPropDB.NextOwnerMask = NextOwnerMask; + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + handlerUpdatePrimSinglePosition(localId, pos1, this); + } + break; + case 2: + Quaternion rot1 = new Quaternion(block.Data, 0, true); - // TODO: More properties are needed in SceneObjectPart! - objPropDB.OwnershipCost = OwnershipCost; - objPropDB.SaleType = SaleType; - objPropDB.SalePrice = SalePrice; - objPropDB.Category = Category; - objPropDB.LastOwnerID = LastOwnerID; - objPropDB.Name = Util.StringToBytes256(ObjectName); - objPropDB.Description = Util.StringToBytes256(Description); - objPropFamilyPack.ObjectData = objPropDB; - objPropFamilyPack.Header.Zerocoded = true; - OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); - } + handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; + if (handlerUpdatePrimSingleRotation != null) + { + // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); + handlerUpdatePrimSingleRotation(localId, rot1, this); + } + break; + case 3: + Vector3 rotPos = new Vector3(block.Data, 0); + Quaternion rot2 = new Quaternion(block.Data, 12, true); - public void SendObjectPropertiesReply( - UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, - UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, - UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, - string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, - uint BaseMask, byte saleType, int salePrice) - { - ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); - // TODO: don't create new blocks if recycling an old packet + handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; + if (handlerUpdatePrimSingleRotationPosition != null) + { + // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); + // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); + handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); + } + break; + case 4: + case 20: + Vector3 scale4 = new Vector3(block.Data, 0); - proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; - proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); - proper.ObjectData[0].ItemID = ItemID; - proper.ObjectData[0].CreationDate = CreationDate; - proper.ObjectData[0].CreatorID = CreatorUUID; - proper.ObjectData[0].FolderID = FolderUUID; - proper.ObjectData[0].FromTaskID = FromTaskUUID; - proper.ObjectData[0].GroupID = GroupUUID; - proper.ObjectData[0].InventorySerial = InventorySerial; + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { +// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); + handlerUpdatePrimScale(localId, scale4, this); + } + break; + case 5: - proper.ObjectData[0].LastOwnerID = LastOwnerUUID; - // proper.ObjectData[0].LastOwnerID = UUID.Zero; + Vector3 scale1 = new Vector3(block.Data, 12); + Vector3 pos11 = new Vector3(block.Data, 0); - proper.ObjectData[0].ObjectID = ObjectUUID; - if (OwnerUUID == GroupUUID) - proper.ObjectData[0].OwnerID = UUID.Zero; - else - proper.ObjectData[0].OwnerID = OwnerUUID; - proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle); - proper.ObjectData[0].TextureID = TextureID; - proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle); - proper.ObjectData[0].Name = Util.StringToBytes256(ItemName); - proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription); - proper.ObjectData[0].OwnerMask = OwnerMask; - proper.ObjectData[0].NextOwnerMask = NextOwnerMask; - proper.ObjectData[0].GroupMask = GroupMask; - proper.ObjectData[0].EveryoneMask = EveryoneMask; - proper.ObjectData[0].BaseMask = BaseMask; - // proper.ObjectData[0].AggregatePerms = 53; - // proper.ObjectData[0].AggregatePermTextures = 0; - // proper.ObjectData[0].AggregatePermTexturesOwner = 0; - proper.ObjectData[0].SaleType = saleType; - proper.ObjectData[0].SalePrice = salePrice; - proper.Header.Zerocoded = true; - OutPacket(proper, ThrottleOutPacketType.Task); - } + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale1, this); - #endregion + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos11, this); + } + } + break; + case 9: + Vector3 pos2 = new Vector3(block.Data, 0); - #region Estate Data Sending Methods + handlerUpdateVector = OnUpdatePrimGroupPosition; - private static bool convertParamStringToBool(byte[] field) - { - string s = Utils.BytesToString(field); - if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") - { - return true; - } - return false; - } + if (handlerUpdateVector != null) + { - public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) - { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + handlerUpdateVector(localId, pos2, this); + } + break; + case 10: + Quaternion rot3 = new Quaternion(block.Data, 0, true); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; + handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + { + // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); + handlerUpdatePrimRotation(localId, rot3, this); + } + break; + case 11: + Vector3 pos3 = new Vector3(block.Data, 0); + Quaternion rot4 = new Quaternion(block.Data, 12, true); - for (int i = 0; i < (6 + EstateManagers.Length); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; + if (handlerUpdatePrimGroupRotation != null) + { + // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); + handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); + } + break; + case 12: + case 28: + Vector3 scale7 = new Vector3(block.Data, 0); - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; - for (int i = 0; i < EstateManagers.Length; i++) - { - returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; - } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); - } + handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { +// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); + handlerUpdatePrimGroupScale(localId, scale7, this); + } + break; + case 13: + Vector3 scale2 = new Vector3(block.Data, 12); + Vector3 pos4 = new Vector3(block.Data, 0); - public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) - { - ListBannedUsers = new List(); + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale2, this); - for (int i = 0; i < bl.Length; i++) - { - if (bl[i] == null) - continue; - if (bl[i].BannedUserID == UUID.Zero) - continue; - BannedUsers.Add(bl[i].BannedUserID); - } + // Change the position based on scale (for bug number 246) + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos4, this); + } + } + break; + case 29: + Vector3 scale5 = new Vector3(block.Data, 12); + Vector3 pos5 = new Vector3(block.Data, 0); - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimGroupScale(localId, scale5, this); + handlerUpdateVector = OnUpdatePrimGroupPosition; - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + if (handlerUpdateVector != null) + { + handlerUpdateVector(localId, pos5, this); + } + } + break; + case 21: + Vector3 scale6 = new Vector3(block.Data, 12); + Vector3 pos6 = new Vector3(block.Data, 0); - for (int i = 0; i < (6 + BannedUsers.Count); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale6, this); + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos6, this); + } + } + break; + default: + m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + break; + } + } + } } - int j = 0; + return true; + } - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + public void RequestMapLayer() + { + //should be getting the map layer from the grid server + //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) + MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); + // TODO: don't create new blocks if recycling an old packet + mapReply.AgentData.AgentID = AgentId; + mapReply.AgentData.Flags = 0; + mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + mapReply.LayerData[0].Bottom = 0; + mapReply.LayerData[0].Left = 0; + mapReply.LayerData[0].Top = 30000; + mapReply.LayerData[0].Right = 30000; + mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); + mapReply.Header.Zerocoded = true; + OutPacket(mapReply, ThrottleOutPacketType.Land); + } - foreach (UUID banned in BannedUsers) + public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) + { + /* + IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); + MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); + mbReply.AgentData.AgentId = AgentId; + int len; + if (simMapProfiles == null) + len = 0; + else + len = simMapProfiles.Count; + + mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; + int iii; + for (iii = 0; iii < len; iii++) { - returnblock[j].Parameter = banned.GetBytes(); j++; + Hashtable mp = (Hashtable)simMapProfiles[iii]; + mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); + mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); + mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); + mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); + mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); + mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); + mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); + mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); + mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + this.OutPacket(mbReply, ThrottleOutPacketType.Land); + */ } - public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) + /// + /// returns a byte array of the client set throttles Gets multiplied by the multiplier + /// + /// + /// non 1 multiplier for subdividing the throttles between individual regions + /// + public byte[] GetThrottlesPacked(float multiplier) { - RegionInfoPacket rinfopack = new RegionInfoPacket(); - RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; - rinfoblk.BillableFactor = args.billableFactor; - rinfoblk.EstateID = args.estateID; - rinfoblk.MaxAgents = args.maxAgents; - rinfoblk.ObjectBonusFactor = args.objectBonusFactor; - rinfoblk.ParentEstateID = args.parentEstateID; - rinfoblk.PricePerMeter = args.pricePerMeter; - rinfoblk.RedirectGridX = args.redirectGridX; - rinfoblk.RedirectGridY = args.redirectGridY; - rinfoblk.RegionFlags = args.regionFlags; - rinfoblk.SimAccess = args.simAccess; - rinfoblk.SunHour = args.sunHour; - rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; - rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; - rinfoblk.UseEstateSun = args.useEstateSun; - rinfoblk.WaterHeight = args.waterHeight; - rinfoblk.SimName = Utils.StringToBytes(args.simName); - - rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); - rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; - rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; - rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; - rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; - rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; - - rinfopack.HasVariableBlocks = true; - rinfopack.RegionInfo = rinfoblk; - rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; + return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier); + } + /// + /// sets the throttles from values supplied by the client + /// + /// + public void SetChildAgentThrottle(byte[] throttles) + { + m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); + } + /// + /// Method gets called when a new packet has arrived from the UDP + /// server. This happens after it's been decoded into a libsl object. + /// + /// object containing the packet. + public virtual void InPacket(object NewPack) + { + // Cast NewPack to Packet. + m_PacketHandler.InPacket((Packet) NewPack); + } - OutPacket(rinfopack, ThrottleOutPacketType.Task); + /// + /// This is the starting point for sending a simulator packet out to the client. + /// + /// Please do not call this from outside the LindenUDP client stack. + /// + /// + /// Corresponds to the type of data that is going out. Enum + public void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) + { + m_PacketHandler.OutPacket(NewPack, throttlePacketType); } - public void SendEstateCovenantInformation(UUID covenant) + public bool AddMoney(int debit) { - EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); - EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); - edata.CovenantID = covenant; - edata.CovenantTimestamp = 0; - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); - einfopack.Data = edata; - OutPacket(einfopack, ThrottleOutPacketType.Task); + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); + return true; + } + return false; } - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) + /// + /// Breaks down the genericMessagePacket into specific events + /// + /// + /// + /// + public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.MethodData.Invoice = invoice; - packet.AgentData.TransactionID = UUID.Random(); - packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; - - for (int i = 0; i < 10; i++) + switch (gmMethod) { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - - //Sending Estate Settings - returnblock[0].Parameter = Utils.StringToBytes(estateName); - // TODO: remove this cruft once MasterAvatar is fully deprecated - // - returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); - returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); + case "autopilot": + float locx; + float locy; + float locz; - returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); - returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); - returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); - returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); - returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? - returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? - returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); + try + { + uint regionX; + uint regionY; + Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; + locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; + locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); + } + catch (InvalidCastException) + { + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; + } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); - OutPacket(packet, ThrottleOutPacketType.Task); - } + handlerAutoPilotGo = OnAutoPilotGo; + if (handlerAutoPilotGo != null) + { + handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); + } + m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); - #endregion - #region Land Data Sending Methods + break; + default: + m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); + for (int hi = 0; hi < gmParams.Length; hi++) + { + Console.WriteLine(gmParams[hi].ToString()); + } + //gmpack.MethodData. + break; - public void SendLandParcelOverlay(byte[] data, int sequence_id) - { - ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); - packet.ParcelData.Data = data; - packet.ParcelData.SequenceID = sequence_id; - packet.Header.Zerocoded = true; - OutPacket(packet, ThrottleOutPacketType.Task); + } } - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + /// + /// Entryway from the client to the simulator. All UDP packets from the client will end up here + /// + /// OpenMetaverse.packet + public void ProcessInPacket(Packet Pack) { - ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); - // TODO: don't create new blocks if recycling an old packet - - updatePacket.ParcelData.AABBMax = landData.AABBMax; - updatePacket.ParcelData.AABBMin = landData.AABBMin; - updatePacket.ParcelData.Area = landData.Area; - updatePacket.ParcelData.AuctionID = landData.AuctionID; - updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; - - updatePacket.ParcelData.Bitmap = landData.Bitmap; - - updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); - updatePacket.ParcelData.Category = (byte)landData.Category; - updatePacket.ParcelData.ClaimDate = landData.ClaimDate; - updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; - updatePacket.ParcelData.GroupID = landData.GroupID; - updatePacket.ParcelData.GroupPrims = landData.GroupPrims; - updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; - updatePacket.ParcelData.LandingType = landData.LandingType; - updatePacket.ParcelData.LocalID = landData.LocalID; - if (landData.Area > 0) - { - updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; - } - else + if (ProcessPacketMethod(Pack)) { - updatePacket.ParcelData.MaxPrims = 0; + return; } - updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; - updatePacket.ParcelData.MediaID = landData.MediaID; - updatePacket.ParcelData.MediaURL = Util.StringToBytes256(landData.MediaURL); - updatePacket.ParcelData.MusicURL = Util.StringToBytes256(landData.MusicURL); - updatePacket.ParcelData.Name = Util.StringToBytes256(landData.Name); - updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; - updatePacket.ParcelData.OtherCount = 0; //TODO: Unimplemented - updatePacket.ParcelData.OtherPrims = landData.OtherPrims; - updatePacket.ParcelData.OwnerID = landData.OwnerID; - updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; - updatePacket.ParcelData.ParcelFlags = landData.Flags; - updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; - updatePacket.ParcelData.PassHours = landData.PassHours; - updatePacket.ParcelData.PassPrice = landData.PassPrice; - updatePacket.ParcelData.PublicCount = 0; //TODO: Unimplemented - - updatePacket.ParcelData.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0; - updatePacket.ParcelData.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0; - updatePacket.ParcelData.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0; - updatePacket.ParcelData.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0; + const bool m_checkPackets = true; - updatePacket.ParcelData.RentPrice = 0; - updatePacket.ParcelData.RequestResult = request_result; - updatePacket.ParcelData.SalePrice = landData.SalePrice; - updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; - updatePacket.ParcelData.SelfCount = 0; //TODO: Unimplemented - updatePacket.ParcelData.SequenceID = sequence_id; - if (landData.SimwideArea > 0) - { - updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; - } - else + // Main packet processing conditional + switch (Pack.Type) { - updatePacket.ParcelData.SimWideMaxPrims = 0; - } - updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; - updatePacket.ParcelData.SnapSelection = snap_selection; - updatePacket.ParcelData.SnapshotID = landData.SnapshotID; - updatePacket.ParcelData.Status = (byte)landData.Status; - updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + - landData.SelectedPrims; - updatePacket.ParcelData.UserLocation = landData.UserLocation; - updatePacket.ParcelData.UserLookAt = landData.UserLookAt; - updatePacket.Header.Zerocoded = true; + #region Scene/Avatar - try - { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - eq.ParcelProperties(updatePacket, this.AgentId); - } - } - catch (Exception ex) - { - m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending parcel data via UDP"); - OutPacket(updatePacket, ThrottleOutPacketType.Task); - } - } + case PacketType.AvatarPropertiesRequest: + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; - public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) - { - ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); - replyPacket.Data.AgentID = AgentId; - replyPacket.Data.Flags = accessFlag; - replyPacket.Data.LocalID = localLandID; - replyPacket.Data.SequenceID = 0; + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarProperties.AgentData.SessionID != SessionId || + avatarProperties.AgentData.AgentID != AgentId) + break; + } + #endregion - List list = new List(); - foreach (UUID avatar in avatars) - { - ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); - block.Flags = accessFlag; - block.ID = avatar; - block.Time = 0; - list.Add(block); - } + handlerRequestAvatarProperties = OnRequestAvatarProperties; + if (handlerRequestAvatarProperties != null) + { + handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); + } - replyPacket.List = list.ToArray(); - replyPacket.Header.Zerocoded = true; - OutPacket(replyPacket, ThrottleOutPacketType.Task); - } + break; - public void SendForceClientSelectObjects(List ObjectIDs) - { - bool firstCall = true; - const int MAX_OBJECTS_PER_PACKET = 251; - ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); - ForceObjectSelectPacket.DataBlock[] data; - while (ObjectIDs.Count > 0) - { - if (firstCall) - { - pack._Header.ResetList = true; - firstCall = false; - } - else - { - pack._Header.ResetList = false; - } + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; - if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) - { - data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; - } - else - { - data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (inchatpack.AgentData.SessionID != SessionId || + inchatpack.AgentData.AgentID != AgentId) + break; + } + #endregion - int i; - for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) - { - data[i] = new ForceObjectSelectPacket.DataBlock(); - data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); - ObjectIDs.RemoveAt(0); - } - pack.Data = data; - pack.Header.Zerocoded = true; - OutPacket(pack, ThrottleOutPacketType.Task); - } - } - - public void SendCameraConstraint(Vector4 ConstraintPlane) - { - CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); - cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); - cpack.CameraCollidePlane.Plane = ConstraintPlane; - //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); - OutPacket(cpack, ThrottleOutPacketType.Task); - } + string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; + byte[] message = inchatpack.ChatData.Message; + byte type = inchatpack.ChatData.Type; + Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; + // UUID fromAgentID = AgentId; - public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) - { - + int channel = inchatpack.ChatData.Channel; - int notifyCount = ownersAndCount.Count; - ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); + if (OnChatFromClient != null) + { + OSChatMessage args = new OSChatMessage(); + args.Channel = channel; + args.From = fromName; + args.Message = Utils.BytesToString(message); + args.Type = (ChatTypeEnum)type; + args.Position = fromPos; - if (notifyCount > 0) - { - if (notifyCount > 32) - { - m_log.InfoFormat( - "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" - + " - a developer might want to investigate whether this is a hard limit", 32); + args.Scene = Scene; + args.Sender = this; + args.SenderUUID = this.AgentId; - notifyCount = 32; - } + handlerChatFromClient = OnChatFromClient; + if (handlerChatFromClient != null) + handlerChatFromClient(this, args); + } + break; - ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock - = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; + case PacketType.AvatarPropertiesUpdate: + AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; - int num = 0; - foreach (UUID owner in ownersAndCount.Keys) - { - dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); - dataBlock[num].Count = ownersAndCount[owner]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarProps.AgentData.SessionID != SessionId || + avatarProps.AgentData.AgentID != AgentId) + break; + } + #endregion - if (land.GroupID == owner || groups.Contains(owner)) - dataBlock[num].IsGroupOwned = true; + handlerUpdateAvatarProperties = OnUpdateAvatarProperties; + if (handlerUpdateAvatarProperties != null) + { + AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; + UserProfileData UserProfile = new UserProfileData(); + UserProfile.ID = AgentId; + UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); + UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); + UserProfile.FirstLifeImage = Properties.FLImageID; + UserProfile.Image = Properties.ImageID; + UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); - dataBlock[num].OnlineStatus = true; //TODO: fix me later - dataBlock[num].OwnerID = owner; + handlerUpdateAvatarProperties(this, UserProfile); + } + break; - num++; + case PacketType.ScriptDialogReply: + ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; - if (num >= notifyCount) + #region Packet Session and User Check + if (m_checkPackets) { - break; + if (rdialog.AgentData.SessionID != SessionId || + rdialog.AgentData.AgentID != AgentId) + break; } - } + #endregion - pack.Data = dataBlock; - } - pack.Header.Zerocoded = true; - this.OutPacket(pack, ThrottleOutPacketType.Task); - } + int ch = rdialog.Data.ChatChannel; + byte[] msg = rdialog.Data.ButtonLabel; + if (OnChatFromClient != null) + { + OSChatMessage args = new OSChatMessage(); + args.Channel = ch; + args.From = String.Empty; + args.Message = Utils.BytesToString(msg); + args.Type = ChatTypeEnum.Shout; + args.Position = new Vector3(); + args.Scene = Scene; + args.Sender = this; + handlerChatFromClient2 = OnChatFromClient; + if (handlerChatFromClient2 != null) + handlerChatFromClient2(this, args); + } - #endregion + break; - #region Helper Methods + case PacketType.ImprovedInstantMessage: + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, - Vector3 velocity, - Quaternion rotation) - { - byte[] bytes = new byte[60]; - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (msgpack.AgentData.SessionID != SessionId || + msgpack.AgentData.AgentID != AgentId) + break; + } + #endregion - dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); + handlerInstantMessage = OnInstantMessage; - uint ID = localID; + if (handlerInstantMessage != null) + { + GridInstantMessage im = new GridInstantMessage(Scene, + msgpack.AgentData.AgentID, + IMfromName, + msgpack.MessageBlock.ToAgentID, + msgpack.MessageBlock.Dialog, + msgpack.MessageBlock.FromGroup, + IMmessage, + msgpack.MessageBlock.ID, + msgpack.MessageBlock.Offline != 0 ? true : false, + msgpack.MessageBlock.Position, + msgpack.MessageBlock.BinaryBucket); - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = 0; - bytes[i++] = 1; - i += 14; - bytes[i++] = 128; - bytes[i++] = 63; + handlerInstantMessage(this, im); + } + break; - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; + case PacketType.AcceptFriendship: + AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; - Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); + #region Packet Session and User Check + if (m_checkPackets) + { + if (afriendpack.AgentData.SessionID != SessionId || + afriendpack.AgentData.AgentID != AgentId) + break; + } + #endregion - internDirec = internDirec / 128.0f; - internDirec.X += 1; - internDirec.Y += 1; - internDirec.Z += 1; + // My guess is this is the folder to stick the calling card into + List callingCardFolders = new List(); - ushort InternVelocityX = (ushort)(32768 * internDirec.X); - ushort InternVelocityY = (ushort)(32768 * internDirec.Y); - ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); + UUID agentID = afriendpack.AgentData.AgentID; + UUID transactionID = afriendpack.TransactionBlock.TransactionID; - ushort ac = 32767; - bytes[i++] = (byte)(InternVelocityX % 256); - bytes[i++] = (byte)((InternVelocityX >> 8) % 256); - bytes[i++] = (byte)(InternVelocityY % 256); - bytes[i++] = (byte)((InternVelocityY >> 8) % 256); - bytes[i++] = (byte)(InternVelocityZ % 256); - bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); + for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) + { + callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); + } - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + handlerApproveFriendRequest = OnApproveFriendRequest; + if (handlerApproveFriendRequest != null) + { + handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + } + break; - //rotation - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + case PacketType.DeclineFriendship: + DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + #region Packet Session and User Check + if (m_checkPackets) + { + if (dfriendpack.AgentData.SessionID != SessionId || + dfriendpack.AgentData.AgentID != AgentId) + break; + } + #endregion - //rotation vel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + if (OnDenyFriendRequest != null) + { + OnDenyFriendRequest(this, + dfriendpack.AgentData.AgentID, + dfriendpack.TransactionBlock.TransactionID, + null); + } + break; - dat.Data = bytes; + case PacketType.TerminateFriendship: + TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; - return (dat); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (tfriendpack.AgentData.SessionID != SessionId || + tfriendpack.AgentData.AgentID != AgentId) + break; + } + #endregion - /// - /// - /// - /// - /// - /// - /// - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, - Vector3 position, - Quaternion rotation, - Vector3 velocity, - Vector3 rotationalvelocity, - byte state) - { - uint ID = localID; - byte[] bytes = new byte[60]; + UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; + UUID exFriendID = tfriendpack.ExBlock.OtherID; - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - dat.TextureEntry = new byte[0]; - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); - bytes[i++] = 0; + handlerTerminateFriendship = OnTerminateFriendship; + if (handlerTerminateFriendship != null) + { + handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); + } + break; - byte[] pb = position.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; - ushort ac = 32767; + case PacketType.RezObject: + RezObjectPacket rezPacket = (RezObjectPacket)Pack; - ushort velx, vely, velz; - Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); + #region Packet Session and User Check + if (m_checkPackets) + { + if (rezPacket.AgentData.SessionID != SessionId || + rezPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - vel = vel / 128.0f; - vel.X += 1; - vel.Y += 1; - vel.Z += 1; - //vel - velx = (ushort)(32768 * (vel.X)); - vely = (ushort)(32768 * (vel.Y)); - velz = (ushort)(32768 * (vel.Z)); + handlerRezObject = OnRezObject; + if (handlerRezObject != null) + { + handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, + rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, + rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, + rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, + rezPacket.RezData.FromTaskID); + } + break; - bytes[i++] = (byte)(velx % 256); - bytes[i++] = (byte)((velx >> 8) % 256); - bytes[i++] = (byte)(vely % 256); - bytes[i++] = (byte)((vely >> 8) % 256); - bytes[i++] = (byte)(velz % 256); - bytes[i++] = (byte)((velz >> 8) % 256); + case PacketType.DeRezObject: + DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + #region Packet Session and User Check + if (m_checkPackets) + { + if (DeRezPacket.AgentData.SessionID != SessionId || + DeRezPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + handlerDeRezObject = OnDeRezObject; + if (handlerDeRezObject != null) + { + List deRezIDs = new List(); - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + foreach (DeRezObjectPacket.ObjectDataBlock data in + DeRezPacket.ObjectData) + { + deRezIDs.Add(data.ObjectLocalID); + } + // It just so happens that the values on the DeRezAction enumerator match the Destination + // values given by a Second Life client + handlerDeRezObject(this, deRezIDs, + DeRezPacket.AgentBlock.GroupID, + (DeRezAction)DeRezPacket.AgentBlock.Destination, + DeRezPacket.AgentBlock.DestinationID); + + } + break; - //rotation vel - Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); + case PacketType.ModifyLand: + ModifyLandPacket modify = (ModifyLandPacket)Pack; - rvel = rvel / 128.0f; - rvel.X += 1; - rvel.Y += 1; - rvel.Z += 1; - //vel - ushort rvelx = (ushort)(32768 * (rvel.X)); - ushort rvely = (ushort)(32768 * (rvel.Y)); - ushort rvelz = (ushort)(32768 * (rvel.Z)); + #region Packet Session and User Check + if (m_checkPackets) + { + if (modify.AgentData.SessionID != SessionId || + modify.AgentData.AgentID != AgentId) + break; + } - bytes[i++] = (byte)(rvelx % 256); - bytes[i++] = (byte)((rvelx >> 8) % 256); - bytes[i++] = (byte)(rvely % 256); - bytes[i++] = (byte)((rvely >> 8) % 256); - bytes[i++] = (byte)(rvelz % 256); - bytes[i++] = (byte)((rvelz >> 8) % 256); - dat.Data = bytes; + #endregion + //m_log.Info("[LAND]: LAND:" + modify.ToString()); + if (modify.ParcelData.Length > 0) + { + if (OnModifyTerrain != null) + { + for (int i = 0; i < modify.ParcelData.Length; i++) + { + handlerModifyTerrain = OnModifyTerrain; + if (handlerModifyTerrain != null) + { + handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, + modify.ModifyBlock.BrushSize, + modify.ModifyBlock.Action, modify.ParcelData[i].North, + modify.ParcelData[i].West, modify.ParcelData[i].South, + modify.ParcelData[i].East, AgentId); + } + } + } + } - return dat; - } + break; - /// - /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) - /// - /// - /// - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) - { - ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); - SetDefaultPrimPacketValues(objupdate); - objupdate.UpdateFlags = flags; - SetPrimPacketShapeData(objupdate, primShape); + case PacketType.RegionHandshakeReply: - if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) - { - objupdate.Data = new byte[1]; - objupdate.Data[0] = primShape.State; - } - return objupdate; - } + handlerRegionHandShakeReply = OnRegionHandShakeReply; + if (handlerRegionHandShakeReply != null) + { + handlerRegionHandShakeReply(this); + } - protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) - { - objectData.TextureEntry = primData.TextureEntry; - objectData.PCode = primData.PCode; - objectData.State = primData.State; - objectData.PathBegin = primData.PathBegin; - objectData.PathEnd = primData.PathEnd; - objectData.PathScaleX = primData.PathScaleX; - objectData.PathScaleY = primData.PathScaleY; - objectData.PathShearX = primData.PathShearX; - objectData.PathShearY = primData.PathShearY; - objectData.PathSkew = primData.PathSkew; - objectData.ProfileBegin = primData.ProfileBegin; - objectData.ProfileEnd = primData.ProfileEnd; - objectData.Scale = primData.Scale; - objectData.PathCurve = primData.PathCurve; - objectData.ProfileCurve = primData.ProfileCurve; - objectData.ProfileHollow = primData.ProfileHollow; - objectData.PathRadiusOffset = primData.PathRadiusOffset; - objectData.PathRevolutions = primData.PathRevolutions; - objectData.PathTaperX = primData.PathTaperX; - objectData.PathTaperY = primData.PathTaperY; - objectData.PathTwist = primData.PathTwist; - objectData.PathTwistBegin = primData.PathTwistBegin; - objectData.ExtraParams = primData.ExtraParams; - } + break; - /// - /// Set some default values in a ObjectUpdatePacket - /// - /// - protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) - { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 3; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - objdata.State = 0; - objdata.Data = new byte[0]; + case PacketType.AgentWearablesRequest: + handlerRequestWearables = OnRequestWearables; - objdata.ObjectData = new byte[60]; - objdata.ObjectData[46] = 128; - objdata.ObjectData[47] = 63; - } + if (handlerRequestWearables != null) + { + handlerRequestWearables(); + } - /// - /// - /// - /// - public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) - { - ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); - // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - - SetDefaultAvatarPacketValues(ref objdata); - objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); - objdata.PathCurve = 16; - objdata.ProfileCurve = 1; - objdata.PathScaleX = 100; - objdata.PathScaleY = 100; - objdata.ParentID = 0; - objdata.OwnerID = UUID.Zero; - objdata.Scale = new Vector3(1, 1, 1); - objdata.PCode = (byte)PCode.Avatar; - if (textureEntry != null) - { - objdata.TextureEntry = textureEntry; - } - Vector3 pos = new Vector3(objdata.ObjectData, 16); - pos.X = 100f; - objdata.ID = 8880000; - objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); - //Vector3 pos2 = new Vector3(100f, 100f, 23f); - //objdata.FullID=user.AgentId; - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + handlerRequestAvatarsData = OnRequestAvatarsData; - return objdata; - } + if (handlerRequestAvatarsData != null) + { + handlerRequestAvatarsData(this); + } - /// - /// - /// - /// - protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) - { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 4; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); - objdata.TextureEntry = ntex.GetBytes(); + break; - objdata.State = 0; - objdata.Data = new byte[0]; + case PacketType.AgentSetAppearance: + AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; - objdata.ObjectData = new byte[76]; - objdata.ObjectData[15] = 128; - objdata.ObjectData[16] = 63; - objdata.ObjectData[56] = 128; - objdata.ObjectData[61] = 102; - objdata.ObjectData[62] = 40; - objdata.ObjectData[63] = 61; - objdata.ObjectData[64] = 189; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (appear.AgentData.SessionID != SessionId || + appear.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendNameReply(UUID profileId, string firstname, string lastname) - { - UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); - // TODO: don't create new blocks if recycling an old packet - packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; - packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); - packet.UUIDNameBlock[0].ID = profileId; - packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); - packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); + handlerSetAppearance = OnSetAppearance; + if (handlerSetAppearance != null) + { + // Temporarily protect ourselves from the mantis #951 failure. + // However, we could do this for several other handlers where a failure isn't terminal + // for the client session anyway, in order to protect ourselves against bad code in plugins + try + { + byte[] visualparams = new byte[appear.VisualParam.Length]; + for (int i = 0; i < appear.VisualParam.Length; i++) + visualparams[i] = appear.VisualParam[i].ParamValue; - OutPacket(packet, ThrottleOutPacketType.Task); - } + Primitive.TextureEntry te = null; + if (appear.ObjectData.TextureEntry.Length > 1) + te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - public ulong GetGroupPowers(UUID groupID) - { - if (groupID == m_activeGroupID) - return m_activeGroupPowers; + handlerSetAppearance(te, visualparams); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", + e); + } + } - if (m_groupPowers.ContainsKey(groupID)) - return m_groupPowers[groupID]; + break; + + case PacketType.AgentIsNowWearing: + if (OnAvatarNowWearing != null) + { + AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; - return 0; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (nowWearing.AgentData.SessionID != SessionId || + nowWearing.AgentData.AgentID != AgentId) + break; + } + #endregion - /// - /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. - /// - public bool ChildAgentStatus() - { - return m_scene.PresenceChildStatus(AgentId); - } + AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); + for (int i = 0; i < nowWearing.WearableData.Length; i++) + { + AvatarWearingArgs.Wearable wearable = + new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, + nowWearing.WearableData[i].WearableType); + wearingArgs.NowWearing.Add(wearable); + } - #endregion + handlerAvatarNowWearing = OnAvatarNowWearing; + if (handlerAvatarNowWearing != null) + { + handlerAvatarNowWearing(this, wearingArgs); + } + } + break; - /// - /// This is a different way of processing packets then ProcessInPacket - /// - protected virtual void RegisterLocalPacketHandlers() - { - AddLocalPacketHandler(PacketType.LogoutRequest, Logout); - AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); - AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); - AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); - AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); - AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); - AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); - } + case PacketType.RezSingleAttachmentFromInv: + handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; + if (handlerRezSingleAttachment != null) + { + RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; - #region Packet Handlers + #region Packet Session and User Check + if (m_checkPackets) + { + if (rez.AgentData.SessionID != SessionId || + rez.AgentData.AgentID != AgentId) + break; + } + #endregion - private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) - { - MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; - // validate the agent owns the agentID and sessionID - if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && - money.AgentData.SessionID == sender.SessionId) - { - MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest; - if (handlerMoneyTransferRequest != null) - { - handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, - money.MoneyData.Amount, money.MoneyData.TransactionType, - Util.FieldToString(money.MoneyData.Description)); - } + handlerRezSingleAttachment(this, rez.ObjectData.ItemID, + rez.ObjectData.AttachmentPt); + } - return true; - } + break; - return false; - } + case PacketType.RezMultipleAttachmentsFromInv: + handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; + if (handlerRezMultipleAttachments != null) + { + RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; + handlerRezMultipleAttachments(this, rez.HeaderData, + rez.ObjectData); + } - private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) - { - ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; - if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) - { - ParcelBuy handlerParcelBuy = OnParcelBuy; - if (handlerParcelBuy != null) - { - handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, - parcel.Data.IsGroupOwned, - parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, - parcel.ParcelData.Price, - false); - } - return true; - } - return false; - } + break; - private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) - { - UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; - + case PacketType.DetachAttachmentIntoInv: + handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; + if (handlerDetachAttachmentIntoInv != null) + { + DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; - for (int i = 0; i < upack.UUIDNameBlock.Length; i++) - { - UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; - if (handlerUUIDGroupNameRequest != null) - { - handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); - } - } + #region Packet Session and User Check + // UNSUPPORTED ON THIS PACKET + #endregion - return true; - } + UUID itemID = detachtoInv.ObjectData.ItemID; + // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; - public bool HandleGenericMessage(IClientAPI sender, Packet pack) - { - GenericMessagePacket gmpack = (GenericMessagePacket) pack; - if (m_genericPacketHandlers.Count == 0) return false; - if (gmpack.AgentData.SessionID != SessionId) return false; + handlerDetachAttachmentIntoInv(itemID, this); + } + break; - GenericMessage handlerGenericMessage = null; + case PacketType.ObjectAttach: + if (OnObjectAttach != null) + { + ObjectAttachPacket att = (ObjectAttachPacket)Pack; - string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (att.AgentData.SessionID != SessionId || + att.AgentData.AgentID != AgentId) + break; + } + #endregion - if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) - { - List msg = new List(); - List msgBytes = new List(); + handlerObjectAttach = OnObjectAttach; - if (handlerGenericMessage != null) - { - foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) - { - msg.Add(Util.FieldToString(block.Parameter)); - msgBytes.Add(block.Parameter); - } - try - { - if (OnBinaryGenericMessage != null) + if (handlerObjectAttach != null) { - OnBinaryGenericMessage(this, method, msgBytes.ToArray()); + if (att.ObjectData.Length > 0) + { + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); + } } - handlerGenericMessage(sender, method, msg); - return true; - } - catch (Exception e) - { - m_log.Error("[GENERICMESSAGE] " + e); } - } - } - m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); - return false; - } - - public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) - { - - ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; - if (ogpack.AgentData.SessionID != SessionId) return false; - - RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest; - if (handlerObjectGroupRequest != null) - { - for (int i = 0; i < ogpack.ObjectData.Length; i++) - { - handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); - } - } - return true; - } + break; - private bool HandleViewerEffect(IClientAPI sender, Packet Pack) - { - ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; - if (viewer.AgentData.SessionID != SessionId) return false; - ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect; - if (handlerViewerEffect != null) - { - int length = viewer.Effect.Length; - List args = new List(length); - for (int i = 0; i < length; i++) - { - //copy the effects block arguments into the event handler arg. - ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); - argument.AgentID = viewer.Effect[i].AgentID; - argument.Color = viewer.Effect[i].Color; - argument.Duration = viewer.Effect[i].Duration; - argument.ID = viewer.Effect[i].ID; - argument.Type = viewer.Effect[i].Type; - argument.TypeData = viewer.Effect[i].TypeData; - args.Add(argument); - } + case PacketType.ObjectDetach: + ObjectDetachPacket dett = (ObjectDetachPacket)Pack; - handlerViewerEffect(sender, args); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (dett.AgentData.SessionID != SessionId || + dett.AgentData.AgentID != AgentId) + break; + } + #endregion - return true; - } + for (int j = 0; j < dett.ObjectData.Length; j++) + { + uint obj = dett.ObjectData[j].ObjectLocalID; + handlerObjectDetach = OnObjectDetach; + if (handlerObjectDetach != null) + { + handlerObjectDetach(obj, this); + } - #endregion Packet Handlers + } + break; - public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) - { - ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); - scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); - // TODO: don't create new blocks if recycling an old packet - scriptQuestion.Data.TaskID = taskID; - scriptQuestion.Data.ItemID = itemID; - scriptQuestion.Data.Questions = question; - scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); - scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); + case PacketType.ObjectDrop: + ObjectDropPacket dropp = (ObjectDropPacket)Pack; - OutPacket(scriptQuestion, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (dropp.AgentData.SessionID != SessionId || + dropp.AgentData.AgentID != AgentId) + break; + } + #endregion - private void InitDefaultAnimations() - { - using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) - { - XmlDocument doc = new XmlDocument(); - doc.Load(reader); - if (doc.DocumentElement != null) - foreach (XmlNode nod in doc.DocumentElement.ChildNodes) + for (int j = 0; j < dropp.ObjectData.Length; j++) { - if (nod.Attributes["name"] != null) + uint obj = dropp.ObjectData[j].ObjectLocalID; + handlerObjectDrop = OnObjectDrop; + if (handlerObjectDrop != null) { - string name = nod.Attributes["name"].Value.ToLower(); - string id = nod.InnerText; - m_defaultAnimations.Add(name, (UUID)id); + handlerObjectDrop(obj, this); } } - } - } - - public UUID GetDefaultAnimation(string name) - { - if (m_defaultAnimations.ContainsKey(name)) - return m_defaultAnimations[name]; - return UUID.Zero; - } + break; - /// - /// Handler called when we receive a logout packet. - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client, Packet packet) - { - if (packet.Type == PacketType.LogoutRequest) - { - if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; - } - - return Logout(client); - } + case PacketType.SetAlwaysRun: + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; - /// - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client) - { - m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); + #region Packet Session and User Check + if (m_checkPackets) + { + if (run.AgentData.SessionID != SessionId || + run.AgentData.AgentID != AgentId) + break; + } + #endregion - Action handlerLogout = OnLogout; + handlerSetAlwaysRun = OnSetAlwaysRun; + if (handlerSetAlwaysRun != null) + handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); - if (handlerLogout != null) - { - handlerLogout(client); - } + break; - return true; - } + case PacketType.CompleteAgentMovement: + handlerCompleteMovementToRegion = OnCompleteMovementToRegion; + if (handlerCompleteMovementToRegion != null) + { + handlerCompleteMovementToRegion(); + } + handlerCompleteMovementToRegion = null; - /// - /// Send a response back to a client when it asks the asset server (via the region server) if it has - /// its appearance texture cached. - /// - /// At the moment, we always reply that there is no cached texture. - /// - /// - /// - /// - protected bool AgentTextureCached(IClientAPI simclient, Packet packet) - { - //m_log.Debug("texture cached: " + packet.ToString()); - AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; - AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + break; - if (cachedtex.AgentData.SessionID != SessionId) return false; + case PacketType.AgentUpdate: + if (OnAgentUpdate != null) + { + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; - // TODO: don't create new blocks if recycling an old packet - cachedresp.AgentData.AgentID = AgentId; - cachedresp.AgentData.SessionID = m_sessionId; - cachedresp.AgentData.SerialNum = m_cachedTextureSerial; - m_cachedTextureSerial++; - cachedresp.WearableData = - new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (agenUpdate.AgentData.SessionID != SessionId || + agenUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - for (int i = 0; i < cachedtex.WearableData.Length; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - cachedresp.WearableData[i].HostName = new byte[0]; - } + AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - cachedresp.Header.Zerocoded = true; - OutPacket(cachedresp, ThrottleOutPacketType.Task); - - return true; - } + // We can only check when we have something to check + // against. - protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) - { - MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); - Scene tScene = (Scene)m_scene; + if (lastarg != null) + { + update = + ( + (x.BodyRotation != lastarg.BodyRotation) || + (x.CameraAtAxis != lastarg.CameraAtAxis) || + (x.CameraCenter != lastarg.CameraCenter) || + (x.CameraLeftAxis != lastarg.CameraLeftAxis) || + (x.CameraUpAxis != lastarg.CameraUpAxis) || + (x.ControlFlags != lastarg.ControlFlags) || + (x.Far != lastarg.Far) || + (x.Flags != lastarg.Flags) || + (x.State != lastarg.State) || + (x.HeadRotation != lastarg.HeadRotation) || + (x.SessionID != lastarg.SessionID) || + (x.AgentID != lastarg.AgentID) + ); + } + else + update = true; - for (int i = 0; i < multipleupdate.ObjectData.Length; i++) - { - MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. - // Can't act on Null Data - if (block.Data != null) - { - uint localId = block.ObjectLocalID; - SceneObjectPart part = tScene.GetSceneObjectPart(localId); + if (update) + { + AgentUpdateArgs arg = new AgentUpdateArgs(); + arg.AgentID = x.AgentID; + arg.BodyRotation = x.BodyRotation; + arg.CameraAtAxis = x.CameraAtAxis; + arg.CameraCenter = x.CameraCenter; + arg.CameraLeftAxis = x.CameraLeftAxis; + arg.CameraUpAxis = x.CameraUpAxis; + arg.ControlFlags = x.ControlFlags; + arg.Far = x.Far; + arg.Flags = x.Flags; + arg.HeadRotation = x.HeadRotation; + arg.SessionID = x.SessionID; + arg.State = x.State; + handlerAgentUpdate = OnAgentUpdate; + lastarg = arg; // save this set of arguments for nexttime + if (handlerAgentUpdate != null) + OnAgentUpdate(this, arg); + + handlerAgentUpdate = null; + } - if (part == null) - { - // It's a ghost! tell the client to delete it from view. - simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); } - else + break; + + case PacketType.AgentAnimation: + AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - // UUID partId = part.UUID; - UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; + if (AgentAni.AgentData.SessionID != SessionId || + AgentAni.AgentData.AgentID != AgentId) + break; + } + #endregion - switch (block.Type) + handlerStartAnim = null; + handlerStopAnim = null; + + for (int i = 0; i < AgentAni.AnimationList.Length; i++) + { + if (AgentAni.AnimationList[i].StartAnim) { - case 1: - Vector3 pos1 = new Vector3(block.Data, 0); + handlerStartAnim = OnStartAnim; + if (handlerStartAnim != null) + { + handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); + } + } + else + { + handlerStopAnim = OnStopAnim; + if (handlerStopAnim != null) + { + handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); + } + } + } + break; - UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - handlerUpdatePrimSinglePosition(localId, pos1, this); - } - break; - case 2: - Quaternion rot1 = new Quaternion(block.Data, 0, true); + case PacketType.AgentRequestSit: + if (OnAgentRequestSit != null) + { + AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; - UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; - if (handlerUpdatePrimSingleRotation != null) - { - // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); - handlerUpdatePrimSingleRotation(localId, rot1, this); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (agentRequestSit.AgentData.SessionID != SessionId || + agentRequestSit.AgentData.AgentID != AgentId) break; - case 3: - Vector3 rotPos = new Vector3(block.Data, 0); - Quaternion rot2 = new Quaternion(block.Data, 12, true); + } + #endregion - UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; - if (handlerUpdatePrimSingleRotationPosition != null) - { - // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); - // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); - handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); - } - break; - case 4: - case 20: - Vector3 scale4 = new Vector3(block.Data, 0); + handlerAgentRequestSit = OnAgentRequestSit; + if (handlerAgentRequestSit != null) + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + } + break; - UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { -// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); - handlerUpdatePrimScale(localId, scale4, this); - } + case PacketType.AgentSit: + if (OnAgentSit != null) + { + AgentSitPacket agentSit = (AgentSitPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (agentSit.AgentData.SessionID != SessionId || + agentSit.AgentData.AgentID != AgentId) break; - case 5: + } + #endregion - Vector3 scale1 = new Vector3(block.Data, 12); - Vector3 pos11 = new Vector3(block.Data, 0); + handlerAgentSit = OnAgentSit; + if (handlerAgentSit != null) + { + OnAgentSit(this, agentSit.AgentData.AgentID); + } + } + break; - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale1, this); + case PacketType.SoundTrigger: + SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos11, this); - } - } - break; - case 9: - Vector3 pos2 = new Vector3(block.Data, 0); + #region Packet Session and User Check + if (m_checkPackets) + { + // UNSUPPORTED ON THIS PACKET + } + #endregion - UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; + handlerSoundTrigger = OnSoundTrigger; + if (handlerSoundTrigger != null) + { + handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, + soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, + soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, + soundTriggerPacket.SoundData.Handle); - if (handlerUpdateVector != null) - { + } + break; - handlerUpdateVector(localId, pos2, this); - } - break; - case 10: - Quaternion rot3 = new Quaternion(block.Data, 0, true); + case PacketType.AvatarPickerRequest: + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; - UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - { - // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); - handlerUpdatePrimRotation(localId, rot3, this); - } - break; - case 11: - Vector3 pos3 = new Vector3(block.Data, 0); - Quaternion rot4 = new Quaternion(block.Data, 12, true); + #region Packet Session and User Check + if (m_checkPackets) + { + if (avRequestQuery.AgentData.SessionID != SessionId || + avRequestQuery.AgentData.AgentID != AgentId) + break; + } + #endregion - handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; - if (handlerUpdatePrimGroupRotation != null) - { - // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); - handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); - } - break; - case 12: - case 28: - Vector3 scale7 = new Vector3(block.Data, 0); + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); - UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { -// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); - handlerUpdatePrimGroupScale(localId, scale7, this); - } - break; - case 13: - Vector3 scale2 = new Vector3(block.Data, 12); - Vector3 pos4 = new Vector3(block.Data, 0); + handlerAvatarPickerRequest = OnAvatarPickerRequest; + if (handlerAvatarPickerRequest != null) + { + handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, + Utils.BytesToString(querydata.Name)); + } + break; - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale2, this); + case PacketType.AgentDataUpdateRequest: + AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; - // Change the position based on scale (for bug number 246) - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos4, this); - } - } - break; - case 29: - Vector3 scale5 = new Vector3(block.Data, 12); - Vector3 pos5 = new Vector3(block.Data, 0); - - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimGroupScale(localId, scale5, this); - handlerUpdateVector = OnUpdatePrimGroupPosition; - - if (handlerUpdateVector != null) - { - handlerUpdateVector(localId, pos5, this); - } - } - break; - case 21: - Vector3 scale6 = new Vector3(block.Data, 12); - Vector3 pos6 = new Vector3(block.Data, 0); - - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale6, this); - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos6, this); - } - } - break; - default: - m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); - break; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || + avRequestDataUpdatePacket.AgentData.AgentID != AgentId) + break; } - } - } - return true; - } - - public void RequestMapLayer() - { - //should be getting the map layer from the grid server - //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) - MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); - // TODO: don't create new blocks if recycling an old packet - mapReply.AgentData.AgentID = AgentId; - mapReply.AgentData.Flags = 0; - mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; - mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); - mapReply.LayerData[0].Bottom = 0; - mapReply.LayerData[0].Left = 0; - mapReply.LayerData[0].Top = 30000; - mapReply.LayerData[0].Right = 30000; - mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); - mapReply.Header.Zerocoded = true; - OutPacket(mapReply, ThrottleOutPacketType.Land); - } - - public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) - { - /* - IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); - MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); - mbReply.AgentData.AgentId = AgentId; - int len; - if (simMapProfiles == null) - len = 0; - else - len = simMapProfiles.Count; - - mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; - int iii; - for (iii = 0; iii < len; iii++) - { - Hashtable mp = (Hashtable)simMapProfiles[iii]; - mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); - mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); - mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); - mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); - mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); - mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); - mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); - mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); - mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); - } - this.OutPacket(mbReply, ThrottleOutPacketType.Land); - */ - } - - /// - /// Sets the throttles from values supplied by the client - /// - /// - public void SetChildAgentThrottle(byte[] throttles) - { - m_udpClient.SetThrottles(throttles); - } - - /// - /// Get the current throttles for this client as a packed byte array - /// - /// Unused - /// - public byte[] GetThrottlesPacked(float multiplier) - { - return m_udpClient.GetThrottlesPacked(); - } - - /// - /// Cruft? - /// - public virtual void InPacket(object NewPack) - { - throw new NotImplementedException(); - } - - /// - /// This is the starting point for sending a simulator packet out to the client - /// - /// Packet to send - /// Throttling category for the packet - private void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) - { - m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); - } - - public bool AddMoney(int debit) - { - if (m_moneyBalance + debit >= 0) - { - m_moneyBalance += debit; - SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); - return true; - } - return false; - } + #endregion - /// - /// Breaks down the genericMessagePacket into specific events - /// - /// - /// - /// - public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) - { - switch (gmMethod) - { - case "autopilot": - float locx; - float locy; - float locz; + handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; - try - { - uint regionX; - uint regionY; - Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; - locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; - locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); - } - catch (InvalidCastException) + if (handlerAgentDataUpdateRequest != null) { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; + handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); } - UpdateVector handlerAutoPilotGo = OnAutoPilotGo; - if (handlerAutoPilotGo != null) + break; + + case PacketType.UserInfoRequest: + handlerUserInfoRequest = OnUserInfoRequest; + if (handlerUserInfoRequest != null) { - handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); + handlerUserInfoRequest(this); } - m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); - - - break; - default: - m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); - for (int hi = 0; hi < gmParams.Length; hi++) + else { - Console.WriteLine(gmParams[hi].ToString()); + SendUserInfoReply(false, true, ""); } - //gmpack.MethodData. break; - - } - } - - /// - /// Entryway from the client to the simulator. All UDP packets from the client will end up here - /// - /// OpenMetaverse.packet - public void ProcessInPacket(Packet Pack) - { - - if (ProcessPacketMethod(Pack)) - { - return; - } - - const bool m_checkPackets = true; - - // Main packet processing conditional - switch (Pack.Type) - { - #region Scene/Avatar - - case PacketType.AvatarPropertiesRequest: - AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; + + case PacketType.UpdateUserInfo: + UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avatarProperties.AgentData.SessionID != SessionId || - avatarProperties.AgentData.AgentID != AgentId) + if (updateUserInfo.AgentData.SessionID != SessionId || + updateUserInfo.AgentData.AgentID != AgentId) break; } #endregion - RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties; - if (handlerRequestAvatarProperties != null) + handlerUpdateUserInfo = OnUpdateUserInfo; + if (handlerUpdateUserInfo != null) { - handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); - } + bool visible = true; + string DirectoryVisibility = + Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); + if (DirectoryVisibility == "hidden") + visible = false; + handlerUpdateUserInfo( + updateUserInfo.UserData.IMViaEMail, + visible, this); + } break; - - case PacketType.ChatFromViewer: - ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + + case PacketType.SetStartLocationRequest: + SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (inchatpack.AgentData.SessionID != SessionId || - inchatpack.AgentData.AgentID != AgentId) + if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || + avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) break; } #endregion - string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; - byte[] message = inchatpack.ChatData.Message; - byte type = inchatpack.ChatData.Type; - Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; - // UUID fromAgentID = AgentId; - - int channel = inchatpack.ChatData.Channel; - - if (OnChatFromClient != null) + if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) { - OSChatMessage args = new OSChatMessage(); - args.Channel = channel; - args.From = fromName; - args.Message = Utils.BytesToString(message); - args.Type = (ChatTypeEnum)type; - args.Position = fromPos; - - args.Scene = Scene; - args.Sender = this; - args.SenderUUID = this.AgentId; - - ChatMessage handlerChatFromClient = OnChatFromClient; - if (handlerChatFromClient != null) - handlerChatFromClient(this, args); + handlerSetStartLocationRequest = OnSetStartLocationRequest; + if (handlerSetStartLocationRequest != null) + { + handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, + avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, + avSetStartLocationRequestPacket.StartLocationData.LocationID); + } } break; - case PacketType.AvatarPropertiesUpdate: - AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; + case PacketType.AgentThrottle: + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avatarProps.AgentData.SessionID != SessionId || - avatarProps.AgentData.AgentID != AgentId) + if (atpack.AgentData.SessionID != SessionId || + atpack.AgentData.AgentID != AgentId) break; } #endregion - UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties; - if (handlerUpdateAvatarProperties != null) - { - AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; - UserProfileData UserProfile = new UserProfileData(); - UserProfile.ID = AgentId; - UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); - UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); - UserProfile.FirstLifeImage = Properties.FLImageID; - UserProfile.Image = Properties.ImageID; - UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); + m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles); + break; - handlerUpdateAvatarProperties(this, UserProfile); + case PacketType.AgentPause: + m_probesWithNoIngressPackets = 0; + m_clientBlocked = true; + break; + + case PacketType.AgentResume: + m_probesWithNoIngressPackets = 0; + m_clientBlocked = false; + SendStartPingCheck(0); + + break; + + case PacketType.ForceScriptControlRelease: + handlerForceReleaseControls = OnForceReleaseControls; + if (handlerForceReleaseControls != null) + { + handlerForceReleaseControls(this, AgentId); } break; - case PacketType.ScriptDialogReply: - ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; + #endregion + + #region Objects/m_sceneObjects + + case PacketType.ObjectLink: + ObjectLinkPacket link = (ObjectLinkPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rdialog.AgentData.SessionID != SessionId || - rdialog.AgentData.AgentID != AgentId) + if (link.AgentData.SessionID != SessionId || + link.AgentData.AgentID != AgentId) break; } #endregion - int ch = rdialog.Data.ChatChannel; - byte[] msg = rdialog.Data.ButtonLabel; - if (OnChatFromClient != null) + uint parentprimid = 0; + List childrenprims = new List(); + if (link.ObjectData.Length > 1) { - OSChatMessage args = new OSChatMessage(); - args.Channel = ch; - args.From = String.Empty; - args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; - args.Position = new Vector3(); - args.Scene = Scene; - args.Sender = this; - ChatMessage handlerChatFromClient2 = OnChatFromClient; - if (handlerChatFromClient2 != null) - handlerChatFromClient2(this, args); - } + parentprimid = link.ObjectData[0].ObjectLocalID; + for (int i = 1; i < link.ObjectData.Length; i++) + { + childrenprims.Add(link.ObjectData[i].ObjectLocalID); + } + } + handlerLinkObjects = OnLinkObjects; + if (handlerLinkObjects != null) + { + handlerLinkObjects(this, parentprimid, childrenprims); + } break; - - case PacketType.ImprovedInstantMessage: - ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; + + case PacketType.ObjectDelink: + ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (msgpack.AgentData.SessionID != SessionId || - msgpack.AgentData.AgentID != AgentId) + if (delink.AgentData.SessionID != SessionId || + delink.AgentData.AgentID != AgentId) break; } #endregion - string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); - string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); - ImprovedInstantMessage handlerInstantMessage = OnInstantMessage; + // It appears the prim at index 0 is not always the root prim (for + // instance, when one prim of a link set has been edited independently + // of the others). Therefore, we'll pass all the ids onto the delink + // method for it to decide which is the root. + List prims = new List(); + for (int i = 0; i < delink.ObjectData.Length; i++) + { + prims.Add(delink.ObjectData[i].ObjectLocalID); + } + handlerDelinkObjects = OnDelinkObjects; + if (handlerDelinkObjects != null) + { + handlerDelinkObjects(prims); + } - if (handlerInstantMessage != null) + break; + + case PacketType.ObjectAdd: + if (OnAddPrim != null) { - GridInstantMessage im = new GridInstantMessage(Scene, - msgpack.AgentData.AgentID, - IMfromName, - msgpack.MessageBlock.ToAgentID, - msgpack.MessageBlock.Dialog, - msgpack.MessageBlock.FromGroup, - IMmessage, - msgpack.MessageBlock.ID, - msgpack.MessageBlock.Offline != 0 ? true : false, - msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + ObjectAddPacket addPacket = (ObjectAddPacket)Pack; - handlerInstantMessage(this, im); + #region Packet Session and User Check + if (m_checkPackets) + { + if (addPacket.AgentData.SessionID != SessionId || + addPacket.AgentData.AgentID != AgentId) + break; + } + #endregion + + PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); + // m_log.Info("[REZData]: " + addPacket.ToString()); + //BypassRaycast: 1 + //RayStart: <69.79469, 158.2652, 98.40343> + //RayEnd: <61.97724, 141.995, 92.58341> + //RayTargetID: 00000000-0000-0000-0000-000000000000 + + //Check to see if adding the prim is allowed; useful for any module wanting to restrict the + //object from rezing initially + + handlerAddPrim = OnAddPrim; + if (handlerAddPrim != null) + handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); } break; - - case PacketType.AcceptFriendship: - AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; + + case PacketType.ObjectShape: + ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (afriendpack.AgentData.SessionID != SessionId || - afriendpack.AgentData.AgentID != AgentId) + if (shapePacket.AgentData.SessionID != SessionId || + shapePacket.AgentData.AgentID != AgentId) break; } #endregion - // My guess is this is the folder to stick the calling card into - List callingCardFolders = new List(); - - UUID agentID = afriendpack.AgentData.AgentID; - UUID transactionID = afriendpack.TransactionBlock.TransactionID; - - for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) + handlerUpdatePrimShape = null; + for (int i = 0; i < shapePacket.ObjectData.Length; i++) { - callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); - } + handlerUpdatePrimShape = OnUpdatePrimShape; + if (handlerUpdatePrimShape != null) + { + UpdateShapeArgs shapeData = new UpdateShapeArgs(); + shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; + shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; + shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; + shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; + shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; + shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; + shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; + shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; + shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; + shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; + shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; + shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; + shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; + shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; + shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; + shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; + shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; + shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; + shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; - FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; - if (handlerApproveFriendRequest != null) - { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, + shapeData); + } } break; - - case PacketType.DeclineFriendship: - DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; + + case PacketType.ObjectExtraParams: + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dfriendpack.AgentData.SessionID != SessionId || - dfriendpack.AgentData.AgentID != AgentId) + if (extraPar.AgentData.SessionID != SessionId || + extraPar.AgentData.AgentID != AgentId) break; } #endregion - if (OnDenyFriendRequest != null) + handlerUpdateExtraParams = OnUpdateExtraParams; + if (handlerUpdateExtraParams != null) { - OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, - dfriendpack.TransactionBlock.TransactionID, - null); + for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) + { + handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, + extraPar.ObjectData[i].ParamType, + extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); + } } break; - - case PacketType.TerminateFriendship: - TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (tfriendpack.AgentData.SessionID != SessionId || - tfriendpack.AgentData.AgentID != AgentId) + if (dupe.AgentData.SessionID != SessionId || + dupe.AgentData.AgentID != AgentId) break; } #endregion - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; - UUID exFriendID = tfriendpack.ExBlock.OtherID; + ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; - FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship; - if (handlerTerminateFriendship != null) + handlerObjectDuplicate = null; + + for (int i = 0; i < dupe.ObjectData.Length; i++) { - handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); + handlerObjectDuplicate = OnObjectDuplicate; + if (handlerObjectDuplicate != null) + { + handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, + dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, + AgentandGroupData.GroupID); + } } + break; - case PacketType.RezObject: - RezObjectPacket rezPacket = (RezObjectPacket)Pack; + case PacketType.RequestMultipleObjects: + RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rezPacket.AgentData.SessionID != SessionId || - rezPacket.AgentData.AgentID != AgentId) + if (incomingRequest.AgentData.SessionID != SessionId || + incomingRequest.AgentData.AgentID != AgentId) break; } #endregion - RezObject handlerRezObject = OnRezObject; - if (handlerRezObject != null) - { - handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, - rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, - rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, - rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, - rezPacket.RezData.FromTaskID); + handlerObjectRequest = null; + + for (int i = 0; i < incomingRequest.ObjectData.Length; i++) + { + handlerObjectRequest = OnObjectRequest; + if (handlerObjectRequest != null) + { + handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); + } } break; - - case PacketType.DeRezObject: - DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; + case PacketType.ObjectSelect: + ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (DeRezPacket.AgentData.SessionID != SessionId || - DeRezPacket.AgentData.AgentID != AgentId) + if (incomingselect.AgentData.SessionID != SessionId || + incomingselect.AgentData.AgentID != AgentId) break; } #endregion - DeRezObject handlerDeRezObject = OnDeRezObject; - if (handlerDeRezObject != null) - { - List deRezIDs = new List(); + handlerObjectSelect = null; - foreach (DeRezObjectPacket.ObjectDataBlock data in - DeRezPacket.ObjectData) + for (int i = 0; i < incomingselect.ObjectData.Length; i++) + { + handlerObjectSelect = OnObjectSelect; + if (handlerObjectSelect != null) { - deRezIDs.Add(data.ObjectLocalID); + handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); } - // It just so happens that the values on the DeRezAction enumerator match the Destination - // values given by a Second Life client - handlerDeRezObject(this, deRezIDs, - DeRezPacket.AgentBlock.GroupID, - (DeRezAction)DeRezPacket.AgentBlock.Destination, - DeRezPacket.AgentBlock.DestinationID); - } break; - - case PacketType.ModifyLand: - ModifyLandPacket modify = (ModifyLandPacket)Pack; + case PacketType.ObjectDeselect: + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (modify.AgentData.SessionID != SessionId || - modify.AgentData.AgentID != AgentId) + if (incomingdeselect.AgentData.SessionID != SessionId || + incomingdeselect.AgentData.AgentID != AgentId) break; } - #endregion - //m_log.Info("[LAND]: LAND:" + modify.ToString()); - if (modify.ParcelData.Length > 0) + + handlerObjectDeselect = null; + + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) { - if (OnModifyTerrain != null) + handlerObjectDeselect = OnObjectDeselect; + if (handlerObjectDeselect != null) { - for (int i = 0; i < modify.ParcelData.Length; i++) - { - ModifyTerrain handlerModifyTerrain = OnModifyTerrain; - if (handlerModifyTerrain != null) - { - handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, - modify.ModifyBlock.BrushSize, - modify.ModifyBlock.Action, modify.ParcelData[i].North, - modify.ParcelData[i].West, modify.ParcelData[i].South, - modify.ParcelData[i].East, AgentId); - } - } + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); } } - break; + case PacketType.ObjectPosition: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectPositionPacket position = (ObjectPositionPacket)Pack; - case PacketType.RegionHandshakeReply: + #region Packet Session and User Check + if (m_checkPackets) + { + if (position.AgentData.SessionID != SessionId || + position.AgentData.AgentID != AgentId) + break; + } + #endregion - Action handlerRegionHandShakeReply = OnRegionHandShakeReply; - if (handlerRegionHandShakeReply != null) + + for (int i = 0; i < position.ObjectData.Length; i++) { - handlerRegionHandShakeReply(this); + handlerUpdateVector = OnUpdatePrimGroupPosition; + if (handlerUpdateVector != null) + handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); } break; + case PacketType.ObjectScale: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectScalePacket scale = (ObjectScalePacket)Pack; - case PacketType.AgentWearablesRequest: - GenericCall2 handlerRequestWearables = OnRequestWearables; - - if (handlerRequestWearables != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerRequestWearables(); + if (scale.AgentData.SessionID != SessionId || + scale.AgentData.AgentID != AgentId) + break; } + #endregion - Action handlerRequestAvatarsData = OnRequestAvatarsData; - - if (handlerRequestAvatarsData != null) + for (int i = 0; i < scale.ObjectData.Length; i++) { - handlerRequestAvatarsData(this); + handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); } break; - - case PacketType.AgentSetAppearance: - AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + case PacketType.ObjectRotation: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (appear.AgentData.SessionID != SessionId || - appear.AgentData.AgentID != AgentId) + if (rotation.AgentData.SessionID != SessionId || + rotation.AgentData.AgentID != AgentId) break; } #endregion - SetAppearance handlerSetAppearance = OnSetAppearance; - if (handlerSetAppearance != null) + for (int i = 0; i < rotation.ObjectData.Length; i++) { - // Temporarily protect ourselves from the mantis #951 failure. - // However, we could do this for several other handlers where a failure isn't terminal - // for the client session anyway, in order to protect ourselves against bad code in plugins - try - { - byte[] visualparams = new byte[appear.VisualParam.Length]; - for (int i = 0; i < appear.VisualParam.Length; i++) - visualparams[i] = appear.VisualParam[i].ParamValue; - - Primitive.TextureEntry te = null; - if (appear.ObjectData.TextureEntry.Length > 1) - te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - - handlerSetAppearance(te, visualparams); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", - e); - } + handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); } break; - - case PacketType.AgentIsNowWearing: - if (OnAvatarNowWearing != null) + case PacketType.ObjectFlagUpdate: + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; + if (flags.AgentData.SessionID != SessionId || + flags.AgentData.AgentID != AgentId) + break; + } + #endregion - #region Packet Session and User Check - if (m_checkPackets) - { - if (nowWearing.AgentData.SessionID != SessionId || - nowWearing.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerUpdatePrimFlags = OnUpdatePrimFlags; - AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); - for (int i = 0; i < nowWearing.WearableData.Length; i++) - { - AvatarWearingArgs.Wearable wearable = - new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, - nowWearing.WearableData[i].WearableType); - wearingArgs.NowWearing.Add(wearable); - } + if (handlerUpdatePrimFlags != null) + { + byte[] data = Pack.ToBytes(); + // 46,47,48 are special positions within the packet + // This may change so perhaps we need a better way + // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) + bool UsePhysics = (data[46] != 0) ? true : false; + bool IsTemporary = (data[47] != 0) ? true : false; + bool IsPhantom = (data[48] != 0) ? true : false; + handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); + } + break; + case PacketType.ObjectImage: + ObjectImagePacket imagePack = (ObjectImagePacket)Pack; - AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing; - if (handlerAvatarNowWearing != null) + handlerUpdatePrimTexture = null; + for (int i = 0; i < imagePack.ObjectData.Length; i++) + { + handlerUpdatePrimTexture = OnUpdatePrimTexture; + if (handlerUpdatePrimTexture != null) { - handlerAvatarNowWearing(this, wearingArgs); + handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, + imagePack.ObjectData[i].TextureEntry, this); } } break; + case PacketType.ObjectGrab: + ObjectGrabPacket grab = (ObjectGrabPacket)Pack; - case PacketType.RezSingleAttachmentFromInv: - RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; - if (handlerRezSingleAttachment != null) + #region Packet Session and User Check + if (m_checkPackets) { - RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; + if (grab.AgentData.SessionID != SessionId || + grab.AgentData.AgentID != AgentId) + break; + } + #endregion - #region Packet Session and User Check - if (m_checkPackets) + handlerGrabObject = OnGrabObject; + + if (handlerGrabObject != null) + { + List touchArgs = new List(); + if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) { - if (rez.AgentData.SessionID != SessionId || - rez.AgentData.AgentID != AgentId) - break; + foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } } - #endregion - - handlerRezSingleAttachment(this, rez.ObjectData.ItemID, - rez.ObjectData.AttachmentPt); + handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); } - break; + case PacketType.ObjectGrabUpdate: + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; - case PacketType.RezMultipleAttachmentsFromInv: - RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; - if (handlerRezMultipleAttachments != null) + #region Packet Session and User Check + if (m_checkPackets) { - RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; - handlerRezMultipleAttachments(this, rez.HeaderData, - rez.ObjectData); + if (grabUpdate.AgentData.SessionID != SessionId || + grabUpdate.AgentData.AgentID != AgentId) + break; } + #endregion - break; + handlerGrabUpdate = OnGrabUpdate; - case PacketType.DetachAttachmentIntoInv: - UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; - if (handlerDetachAttachmentIntoInv != null) + if (handlerGrabUpdate != null) { - DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; - - #region Packet Session and User Check - // UNSUPPORTED ON THIS PACKET - #endregion - - UUID itemID = detachtoInv.ObjectData.ItemID; - // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; - - handlerDetachAttachmentIntoInv(itemID, this); + List touchArgs = new List(); + if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) + { + foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } + } + handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, + grabUpdate.ObjectData.GrabPosition, this, touchArgs); } break; + case PacketType.ObjectDeGrab: + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; - case PacketType.ObjectAttach: - if (OnObjectAttach != null) + #region Packet Session and User Check + if (m_checkPackets) { - ObjectAttachPacket att = (ObjectAttachPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (att.AgentData.SessionID != SessionId || - att.AgentData.AgentID != AgentId) - break; - } - #endregion - - ObjectAttach handlerObjectAttach = OnObjectAttach; + if (deGrab.AgentData.SessionID != SessionId || + deGrab.AgentData.AgentID != AgentId) + break; + } + #endregion - if (handlerObjectAttach != null) + handlerDeGrabObject = OnDeGrabObject; + if (handlerDeGrabObject != null) + { + List touchArgs = new List(); + if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) { - if (att.ObjectData.Length > 0) + foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) { - handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); } } + handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); } break; - - case PacketType.ObjectDetach: - ObjectDetachPacket dett = (ObjectDetachPacket)Pack; + case PacketType.ObjectSpinStart: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); + ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dett.AgentData.SessionID != SessionId || - dett.AgentData.AgentID != AgentId) + if (spinStart.AgentData.SessionID != SessionId || + spinStart.AgentData.AgentID != AgentId) break; } #endregion - for (int j = 0; j < dett.ObjectData.Length; j++) + handlerSpinStart = OnSpinStart; + if (handlerSpinStart != null) { - uint obj = dett.ObjectData[j].ObjectLocalID; - ObjectDeselect handlerObjectDetach = OnObjectDetach; - if (handlerObjectDetach != null) - { - handlerObjectDetach(obj, this); - } - + handlerSpinStart(spinStart.ObjectData.ObjectID, this); } break; + case PacketType.ObjectSpinUpdate: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); + ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; - case PacketType.ObjectDrop: - ObjectDropPacket dropp = (ObjectDropPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (spinUpdate.AgentData.SessionID != SessionId || + spinUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion + + Vector3 axis; + float angle; + spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); + //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); + + handlerSpinUpdate = OnSpinUpdate; + if (handlerSpinUpdate != null) + { + handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); + } + break; + case PacketType.ObjectSpinStop: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); + ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dropp.AgentData.SessionID != SessionId || - dropp.AgentData.AgentID != AgentId) + if (spinStop.AgentData.SessionID != SessionId || + spinStop.AgentData.AgentID != AgentId) break; } #endregion - for (int j = 0; j < dropp.ObjectData.Length; j++) + handlerSpinStop = OnSpinStop; + if (handlerSpinStop != null) { - uint obj = dropp.ObjectData[j].ObjectLocalID; - ObjectDrop handlerObjectDrop = OnObjectDrop; - if (handlerObjectDrop != null) - { - handlerObjectDrop(obj, this); - } + handlerSpinStop(spinStop.ObjectData.ObjectID, this); } break; - case PacketType.SetAlwaysRun: - SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; + case PacketType.ObjectDescription: + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (run.AgentData.SessionID != SessionId || - run.AgentData.AgentID != AgentId) + if (objDes.AgentData.SessionID != SessionId || + objDes.AgentData.AgentID != AgentId) break; } #endregion - SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun; - if (handlerSetAlwaysRun != null) - handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); + handlerObjectDescription = null; + for (int i = 0; i < objDes.ObjectData.Length; i++) + { + handlerObjectDescription = OnObjectDescription; + if (handlerObjectDescription != null) + { + handlerObjectDescription(this, objDes.ObjectData[i].LocalID, + Util.FieldToString(objDes.ObjectData[i].Description)); + } + } break; - - case PacketType.CompleteAgentMovement: - GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; - if (handlerCompleteMovementToRegion != null) + case PacketType.ObjectName: + ObjectNamePacket objName = (ObjectNamePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerCompleteMovementToRegion(); + if (objName.AgentData.SessionID != SessionId || + objName.AgentData.AgentID != AgentId) + break; + } + #endregion + + handlerObjectName = null; + for (int i = 0; i < objName.ObjectData.Length; i++) + { + handlerObjectName = OnObjectName; + if (handlerObjectName != null) + { + handlerObjectName(this, objName.ObjectData[i].LocalID, + Util.FieldToString(objName.ObjectData[i].Name)); + } } - handlerCompleteMovementToRegion = null; - break; - - case PacketType.AgentUpdate: - if (OnAgentUpdate != null) + case PacketType.ObjectPermissions: + if (OnObjectPermissions != null) { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (agenUpdate.AgentData.SessionID != SessionId || - agenUpdate.AgentData.AgentID != AgentId) + if (newobjPerms.AgentData.SessionID != SessionId || + newobjPerms.AgentData.AgentID != AgentId) break; } #endregion - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; + UUID AgentID = newobjPerms.AgentData.AgentID; + UUID SessionID = newobjPerms.AgentData.SessionID; - // We can only check when we have something to check - // against. + handlerObjectPermissions = null; - if (lastarg != null) + for (int i = 0; i < newobjPerms.ObjectData.Length; i++) { - update = - ( - (x.BodyRotation != lastarg.BodyRotation) || - (x.CameraAtAxis != lastarg.CameraAtAxis) || - (x.CameraCenter != lastarg.CameraCenter) || - (x.CameraLeftAxis != lastarg.CameraLeftAxis) || - (x.CameraUpAxis != lastarg.CameraUpAxis) || - (x.ControlFlags != lastarg.ControlFlags) || - (x.Far != lastarg.Far) || - (x.Flags != lastarg.Flags) || - (x.State != lastarg.State) || - (x.HeadRotation != lastarg.HeadRotation) || - (x.SessionID != lastarg.SessionID) || - (x.AgentID != lastarg.AgentID) - ); - } - else - update = true; + ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. + byte field = permChanges.Field; + uint localID = permChanges.ObjectLocalID; + uint mask = permChanges.Mask; + byte set = permChanges.Set; - if (update) - { - AgentUpdateArgs arg = new AgentUpdateArgs(); - arg.AgentID = x.AgentID; - arg.BodyRotation = x.BodyRotation; - arg.CameraAtAxis = x.CameraAtAxis; - arg.CameraCenter = x.CameraCenter; - arg.CameraLeftAxis = x.CameraLeftAxis; - arg.CameraUpAxis = x.CameraUpAxis; - arg.ControlFlags = x.ControlFlags; - arg.Far = x.Far; - arg.Flags = x.Flags; - arg.HeadRotation = x.HeadRotation; - arg.SessionID = x.SessionID; - arg.State = x.State; - UpdateAgent handlerAgentUpdate = OnAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime - if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + handlerObjectPermissions = OnObjectPermissions; - handlerAgentUpdate = null; + if (handlerObjectPermissions != null) + handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); } - } + + // Here's our data, + // PermField contains the field the info goes into + // PermField determines which mask we're changing + // + // chmask is the mask of the change + // setTF is whether we're adding it or taking it away + // + // objLocalID is the localID of the object. + + // Unfortunately, we have to pass the event the packet because objData is an array + // That means multiple object perms may be updated in a single packet. + break; - case PacketType.AgentAnimation: - AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + case PacketType.Undo: + UndoPacket undoitem = (UndoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (AgentAni.AgentData.SessionID != SessionId || - AgentAni.AgentData.AgentID != AgentId) + if (undoitem.AgentData.SessionID != SessionId || + undoitem.AgentData.AgentID != AgentId) break; } #endregion - StartAnim handlerStartAnim = null; - StopAnim handlerStopAnim = null; - - for (int i = 0; i < AgentAni.AnimationList.Length; i++) + if (undoitem.ObjectData.Length > 0) { - if (AgentAni.AnimationList[i].StartAnim) - { - handlerStartAnim = OnStartAnim; - if (handlerStartAnim != null) - { - handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); - } - } - else + for (int i = 0; i < undoitem.ObjectData.Length; i++) { - handlerStopAnim = OnStopAnim; - if (handlerStopAnim != null) + UUID objiD = undoitem.ObjectData[i].ObjectID; + handlerOnUndo = OnUndo; + if (handlerOnUndo != null) { - handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); + handlerOnUndo(this, objiD); } - } - } - break; - - case PacketType.AgentRequestSit: - if (OnAgentRequestSit != null) - { - AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentRequestSit.AgentData.SessionID != SessionId || - agentRequestSit.AgentData.AgentID != AgentId) - break; - } - #endregion - AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; - if (handlerAgentRequestSit != null) - handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, - agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); - } - break; - - case PacketType.AgentSit: - if (OnAgentSit != null) - { - AgentSitPacket agentSit = (AgentSitPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentSit.AgentData.SessionID != SessionId || - agentSit.AgentData.AgentID != AgentId) - break; - } - #endregion - - AgentSit handlerAgentSit = OnAgentSit; - if (handlerAgentSit != null) - { - OnAgentSit(this, agentSit.AgentData.AgentID); } } break; - - case PacketType.SoundTrigger: - SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; + case PacketType.ObjectDuplicateOnRay: + ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - // UNSUPPORTED ON THIS PACKET + if (dupeOnRay.AgentData.SessionID != SessionId || + dupeOnRay.AgentData.AgentID != AgentId) + break; } #endregion - SoundTrigger handlerSoundTrigger = OnSoundTrigger; - if (handlerSoundTrigger != null) - { - handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, - soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, - soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, - soundTriggerPacket.SoundData.Handle); + handlerObjectDuplicateOnRay = null; + + for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) + { + handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; + if (handlerObjectDuplicateOnRay != null) + { + handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, + dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, + dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); + } } - break; - case PacketType.AvatarPickerRequest: - AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + break; + case PacketType.RequestObjectPropertiesFamily: + //This powers the little tooltip that appears when you move your mouse over an object + RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avRequestQuery.AgentData.SessionID != SessionId || - avRequestQuery.AgentData.AgentID != AgentId) + if (packToolTip.AgentData.SessionID != SessionId || + packToolTip.AgentData.AgentID != AgentId) break; } #endregion - AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; - AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; - //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; - AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest; - if (handlerAvatarPickerRequest != null) + handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; + + if (handlerRequestObjectPropertiesFamily != null) { - handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, - Utils.BytesToString(querydata.Name)); + handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, + packObjBlock.ObjectID); } - break; - case PacketType.AgentDataUpdateRequest: - AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; + break; + case PacketType.ObjectIncludeInSearch: + //This lets us set objects to appear in search (stuff like DataSnapshot, etc) + ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; + handlerObjectIncludeInSearch = null; #region Packet Session and User Check if (m_checkPackets) { - if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || - avRequestDataUpdatePacket.AgentData.AgentID != AgentId) + if (packInSearch.AgentData.SessionID != SessionId || + packInSearch.AgentData.AgentID != AgentId) break; } #endregion - FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; - - if (handlerAgentDataUpdateRequest != null) + foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) { - handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); - } + bool inSearch = objData.IncludeInSearch; + uint localID = objData.ObjectLocalID; - break; - - case PacketType.UserInfoRequest: - UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest; - if (handlerUserInfoRequest != null) - { - handlerUserInfoRequest(this); - } - else - { - SendUserInfoReply(false, true, ""); + handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + + if (handlerObjectIncludeInSearch != null) + { + handlerObjectIncludeInSearch(this, inSearch, localID); + } } break; - - case PacketType.UpdateUserInfo: - UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; + + case PacketType.ScriptAnswerYes: + ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (updateUserInfo.AgentData.SessionID != SessionId || - updateUserInfo.AgentData.AgentID != AgentId) + if (scriptAnswer.AgentData.SessionID != SessionId || + scriptAnswer.AgentData.AgentID != AgentId) break; } #endregion - UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo; - if (handlerUpdateUserInfo != null) + handlerScriptAnswer = OnScriptAnswer; + if (handlerScriptAnswer != null) { - bool visible = true; - string DirectoryVisibility = - Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); - if (DirectoryVisibility == "hidden") - visible = false; - - handlerUpdateUserInfo( - updateUserInfo.UserData.IMViaEMail, - visible, this); + handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); } break; - - case PacketType.SetStartLocationRequest: - SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; + + case PacketType.ObjectClickAction: + ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || - avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) + if (ocpacket.AgentData.SessionID != SessionId || + ocpacket.AgentData.AgentID != AgentId) break; } #endregion - if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) + handlerObjectClickAction = OnObjectClickAction; + if (handlerObjectClickAction != null) { - TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest; - if (handlerSetStartLocationRequest != null) + foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) { - handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, - avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, - avSetStartLocationRequestPacket.StartLocationData.LocationID); + byte action = odata.ClickAction; + uint localID = odata.ObjectLocalID; + handlerObjectClickAction(this, localID, action.ToString()); } } break; - case PacketType.AgentThrottle: - AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + case PacketType.ObjectMaterial: + ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (atpack.AgentData.SessionID != SessionId || - atpack.AgentData.AgentID != AgentId) + if (ompacket.AgentData.SessionID != SessionId || + ompacket.AgentData.AgentID != AgentId) break; } #endregion - m_udpClient.SetThrottles(atpack.Throttle.Throttles); - break; - - case PacketType.AgentPause: - m_udpClient.IsPaused = true; - break; - - case PacketType.AgentResume: - m_udpClient.IsPaused = false; - SendStartPingCheck(m_udpClient.CurrentPingSequence++); - - break; - - case PacketType.ForceScriptControlRelease: - ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls; - if (handlerForceReleaseControls != null) + handlerObjectMaterial = OnObjectMaterial; + if (handlerObjectMaterial != null) { - handlerForceReleaseControls(this, AgentId); + foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) + { + byte material = odata.Material; + uint localID = odata.ObjectLocalID; + handlerObjectMaterial(this, localID, material.ToString()); + } } break; #endregion - #region Objects/m_sceneObjects - - case PacketType.ObjectLink: - ObjectLinkPacket link = (ObjectLinkPacket)Pack; + #region Inventory/Asset/Other related packets + case PacketType.RequestImage: + RequestImagePacket imageRequest = (RequestImagePacket)Pack; + //m_log.Debug("image request: " + Pack.ToString()); + #region Packet Session and User Check if (m_checkPackets) { - if (link.AgentData.SessionID != SessionId || - link.AgentData.AgentID != AgentId) + if (imageRequest.AgentData.SessionID != SessionId || + imageRequest.AgentData.AgentID != AgentId) break; } #endregion - uint parentprimid = 0; - List childrenprims = new List(); - if (link.ObjectData.Length > 1) - { - parentprimid = link.ObjectData[0].ObjectLocalID; + //handlerTextureRequest = null; - for (int i = 1; i < link.ObjectData.Length; i++) + for (int i = 0; i < imageRequest.RequestImage.Length; i++) + { + if (OnRequestTexture != null) { - childrenprims.Add(link.ObjectData[i].ObjectLocalID); + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = imageRequest.RequestImage[i].Image; + args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + args.PacketNumber = imageRequest.RequestImage[i].Packet; + args.Priority = imageRequest.RequestImage[i].DownloadPriority; + args.requestSequence = imageRequest.Header.Sequence; + + //handlerTextureRequest = OnRequestTexture; + + //if (handlerTextureRequest != null) + //OnRequestTexture(this, args); + + // in the end, we null this, so we have to check if it's null + if (m_imageManager != null) + { + m_imageManager.EnqueueReq(args); + } } } - LinkObjects handlerLinkObjects = OnLinkObjects; - if (handlerLinkObjects != null) - { - handlerLinkObjects(this, parentprimid, childrenprims); - } break; - - case PacketType.ObjectDelink: - ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (delink.AgentData.SessionID != SessionId || - delink.AgentData.AgentID != AgentId) - break; - } - #endregion + case PacketType.TransferRequest: + //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); - // It appears the prim at index 0 is not always the root prim (for - // instance, when one prim of a link set has been edited independently - // of the others). Therefore, we'll pass all the ids onto the delink - // method for it to decide which is the root. - List prims = new List(); - for (int i = 0; i < delink.ObjectData.Length; i++) - { - prims.Add(delink.ObjectData[i].ObjectLocalID); - } - DelinkObjects handlerDelinkObjects = OnDelinkObjects; - if (handlerDelinkObjects != null) + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + //m_log.Debug("Transfer Request: " + transfer.ToString()); + // Validate inventory transfers + // Has to be done here, because AssetCache can't do it + // + + if (transfer.TransferInfo.SourceType == 3) { - handlerDelinkObjects(prims); - } + UUID taskID = new UUID(transfer.TransferInfo.Params, 48); + UUID itemID = new UUID(transfer.TransferInfo.Params, 64); + UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + if (!(((Scene)m_scene).Permissions.BypassPermissions())) + { + if (taskID != UUID.Zero) // Prim + { + SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + if (part == null) + break; - break; - - case PacketType.ObjectAdd: - if (OnAddPrim != null) - { - ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + if (part.OwnerID != AgentId) + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (addPacket.AgentData.SessionID != SessionId || - addPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + break; - PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); - // m_log.Info("[REZData]: " + addPacket.ToString()); - //BypassRaycast: 1 - //RayStart: <69.79469, 158.2652, 98.40343> - //RayEnd: <61.97724, 141.995, 92.58341> - //RayTargetID: 00000000-0000-0000-0000-000000000000 + TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); + if (ti == null) + break; - //Check to see if adding the prim is allowed; useful for any module wanting to restrict the - //object from rezing initially + if (ti.OwnerID != AgentId) + break; - AddNewPrim handlerAddPrim = OnAddPrim; - if (handlerAddPrim != null) - handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); - } - break; - - case PacketType.ObjectShape: - ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (shapePacket.AgentData.SessionID != SessionId || - shapePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + if (ti.AssetID != requestID) + break; + } + else // Agent + { + IInventoryService invService = m_scene.RequestModuleInterface(); + InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); + assetRequestItem = invService.GetItem(assetRequestItem); + if (assetRequestItem == null) + { + assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); + if (assetRequestItem == null) + return; + } - UpdateShape handlerUpdatePrimShape = null; - for (int i = 0; i < shapePacket.ObjectData.Length; i++) - { - handlerUpdatePrimShape = OnUpdatePrimShape; - if (handlerUpdatePrimShape != null) - { - UpdateShapeArgs shapeData = new UpdateShapeArgs(); - shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; - shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; - shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; - shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; - shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; - shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; - shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; - shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; - shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; - shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; - shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; - shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; - shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; - shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; - shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; - shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; - shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; - shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; - shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; + // At this point, we need to apply perms + // only to notecards and scripts. All + // other asset types are always available + // + if (assetRequestItem.AssetType == 10) + { + if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view script", false); + break; + } + } + else if (assetRequestItem.AssetType == 7) + { + if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view notecard", false); + break; + } + } - handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, - shapeData); + if (assetRequestItem.AssetID != requestID) + break; + } } } + + //m_assetCache.AddAssetRequest(this, transfer); + + MakeAssetRequest(transfer); + + /* RequestAsset = OnRequestAsset; + if (RequestAsset != null) + { + RequestAsset(this, transfer); + }*/ break; - - case PacketType.ObjectExtraParams: - ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + case PacketType.AssetUploadRequest: + AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (extraPar.AgentData.SessionID != SessionId || - extraPar.AgentData.AgentID != AgentId) - break; - } - #endregion + + // m_log.Debug("upload request " + request.ToString()); + // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); + UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); - ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams; - if (handlerUpdateExtraParams != null) + handlerAssetUploadRequest = OnAssetUploadRequest; + + if (handlerAssetUploadRequest != null) { - for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) - { - handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, - extraPar.ObjectData[i].ParamType, - extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); - } + handlerAssetUploadRequest(this, temp, + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, + request.AssetBlock.Tempfile); } break; - case PacketType.ObjectDuplicate: - ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + case PacketType.RequestXfer: + RequestXferPacket xferReq = (RequestXferPacket)Pack; + + handlerRequestXfer = OnRequestXfer; - #region Packet Session and User Check - if (m_checkPackets) + if (handlerRequestXfer != null) { - if (dupe.AgentData.SessionID != SessionId || - dupe.AgentData.AgentID != AgentId) - break; + handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); } - #endregion - - ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; - - ObjectDuplicate handlerObjectDuplicate = null; + break; + case PacketType.SendXferPacket: + SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; - for (int i = 0; i < dupe.ObjectData.Length; i++) + handlerXferReceive = OnXferReceive; + if (handlerXferReceive != null) { - handlerObjectDuplicate = OnObjectDuplicate; - if (handlerObjectDuplicate != null) - { - handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, - dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, - AgentandGroupData.GroupID); - } + handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); } - break; - - case PacketType.RequestMultipleObjects: - RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + case PacketType.ConfirmXferPacket: + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; + + handlerConfirmXfer = OnConfirmXfer; + if (handlerConfirmXfer != null) { - if (incomingRequest.AgentData.SessionID != SessionId || - incomingRequest.AgentData.AgentID != AgentId) - break; + handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); } - #endregion - - ObjectRequest handlerObjectRequest = null; - - for (int i = 0; i < incomingRequest.ObjectData.Length; i++) + break; + case PacketType.AbortXfer: + AbortXferPacket abortXfer = (AbortXferPacket)Pack; + handlerAbortXfer = OnAbortXfer; + if (handlerAbortXfer != null) { - handlerObjectRequest = OnObjectRequest; - if (handlerObjectRequest != null) - { - handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); - } + handlerAbortXfer(this, abortXfer.XferID.ID); } + break; - case PacketType.ObjectSelect: - ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; + case PacketType.CreateInventoryFolder: + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (incomingselect.AgentData.SessionID != SessionId || - incomingselect.AgentData.AgentID != AgentId) + if (invFolder.AgentData.SessionID != SessionId || + invFolder.AgentData.AgentID != AgentId) break; } #endregion - ObjectSelect handlerObjectSelect = null; - - for (int i = 0; i < incomingselect.ObjectData.Length; i++) + handlerCreateInventoryFolder = OnCreateNewInventoryFolder; + if (handlerCreateInventoryFolder != null) { - handlerObjectSelect = OnObjectSelect; - if (handlerObjectSelect != null) + handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort)invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + break; + case PacketType.UpdateInventoryFolder: + if (OnUpdateInventoryFolder != null) + { + UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); + if (invFolderx.AgentData.SessionID != SessionId || + invFolderx.AgentData.AgentID != AgentId) + break; + } + #endregion + + handlerUpdateInventoryFolder = null; + + for (int i = 0; i < invFolderx.FolderData.Length; i++) + { + handlerUpdateInventoryFolder = OnUpdateInventoryFolder; + if (handlerUpdateInventoryFolder != null) + { + OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, + (ushort)invFolderx.FolderData[i].Type, + Util.FieldToString(invFolderx.FolderData[i].Name), + invFolderx.FolderData[i].ParentID); + } } } break; - case PacketType.ObjectDeselect: - ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; + case PacketType.MoveInventoryFolder: + if (OnMoveInventoryFolder != null) + { + MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFoldery.AgentData.SessionID != SessionId || + invFoldery.AgentData.AgentID != AgentId) + break; + } + #endregion + + handlerMoveInventoryFolder = null; + for (int i = 0; i < invFoldery.InventoryData.Length; i++) + { + handlerMoveInventoryFolder = OnMoveInventoryFolder; + if (handlerMoveInventoryFolder != null) + { + OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, + invFoldery.InventoryData[i].ParentID); + } + } + } + break; + case PacketType.CreateInventoryItem: + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (incomingdeselect.AgentData.SessionID != SessionId || - incomingdeselect.AgentData.AgentID != AgentId) + if (createItem.AgentData.SessionID != SessionId || + createItem.AgentData.AgentID != AgentId) break; } #endregion - ObjectDeselect handlerObjectDeselect = null; - - for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) + handlerCreateNewInventoryItem = OnCreateNewInventoryItem; + if (handlerCreateNewInventoryItem != null) { - handlerObjectDeselect = OnObjectDeselect; - if (handlerObjectDeselect != null) + handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, + createItem.InventoryBlock.FolderID, + createItem.InventoryBlock.CallbackID, + Util.FieldToString(createItem.InventoryBlock.Description), + Util.FieldToString(createItem.InventoryBlock.Name), + createItem.InventoryBlock.InvType, + createItem.InventoryBlock.Type, + createItem.InventoryBlock.WearableType, + createItem.InventoryBlock.NextOwnerMask, + Util.UnixTimeSinceEpoch()); + } + break; + case PacketType.FetchInventory: + if (OnFetchInventory != null) + { + FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); + if (FetchInventoryx.AgentData.SessionID != SessionId || + FetchInventoryx.AgentData.AgentID != AgentId) + break; + } + #endregion + + handlerFetchInventory = null; + + for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) + { + handlerFetchInventory = OnFetchInventory; + + if (handlerFetchInventory != null) + { + OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, + FetchInventoryx.InventoryData[i].OwnerID); + } } } break; - case PacketType.ObjectPosition: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectPositionPacket position = (ObjectPositionPacket)Pack; + case PacketType.FetchInventoryDescendents: + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (position.AgentData.SessionID != SessionId || - position.AgentData.AgentID != AgentId) + if (Fetch.AgentData.SessionID != SessionId || + Fetch.AgentData.AgentID != AgentId) break; } #endregion - - for (int i = 0; i < position.ObjectData.Length; i++) + handlerFetchInventoryDescendents = OnFetchInventoryDescendents; + if (handlerFetchInventoryDescendents != null) { - UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; - if (handlerUpdateVector != null) - handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); + handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); } - break; - case PacketType.ObjectScale: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectScalePacket scale = (ObjectScalePacket)Pack; + case PacketType.PurgeInventoryDescendents: + PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scale.AgentData.SessionID != SessionId || - scale.AgentData.AgentID != AgentId) + if (Purge.AgentData.SessionID != SessionId || + Purge.AgentData.AgentID != AgentId) break; } #endregion - for (int i = 0; i < scale.ObjectData.Length; i++) + handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; + if (handlerPurgeInventoryDescendents != null) { - UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); + handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); } - break; - case PacketType.ObjectRotation: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; - + case PacketType.UpdateInventoryItem: + UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (rotation.AgentData.SessionID != SessionId || - rotation.AgentData.AgentID != AgentId) + if (inventoryItemUpdate.AgentData.SessionID != SessionId || + inventoryItemUpdate.AgentData.AgentID != AgentId) break; } #endregion - for (int i = 0; i < rotation.ObjectData.Length; i++) + if (OnUpdateInventoryItem != null) { - UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); - } + handlerUpdateInventoryItem = null; + for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + { + handlerUpdateInventoryItem = OnUpdateInventoryItem; + if (handlerUpdateInventoryItem != null) + { + InventoryItemBase itemUpd = new InventoryItemBase(); + itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; + itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); + itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); + itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; + itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; + itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; + itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; + itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; + itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; + itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; + itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; + itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; + itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; + itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; + /* + OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, + inventoryItemUpdate.InventoryData[i].ItemID, + Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name), + Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description), + inventoryItemUpdate.InventoryData[i].NextOwnerMask); + */ + OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, + inventoryItemUpdate.InventoryData[i].ItemID, + itemUpd); + } + } + } + //m_log.Debug(Pack.ToString()); + /*for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + { + if (inventoryItemUpdate.InventoryData[i].TransactionID != UUID.Zero) + { + AssetBase asset = m_assetCache.GetAsset(inventoryItemUpdate.InventoryData[i].TransactionID.Combine(this.SecureSessionId)); + if (asset != null) + { + // m_log.Debug("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); + } + else + { + asset = this.UploadAssets.AddUploadToAssetCache(inventoryItemUpdate.InventoryData[i].TransactionID); + if (asset != null) + { + //m_log.Debug("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); + } + else + { + //m_log.Debug("trying to update inventory item, but asset is null"); + } + } + } + else + { + m_inventoryCache.UpdateInventoryItemDetails(this, inventoryItemUpdate.InventoryData[i].ItemID, inventoryItemUpdate.InventoryData[i]); ; + } + }*/ break; - case PacketType.ObjectFlagUpdate: - ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + case PacketType.CopyInventoryItem: + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (flags.AgentData.SessionID != SessionId || - flags.AgentData.AgentID != AgentId) + if (copyitem.AgentData.SessionID != SessionId || + copyitem.AgentData.AgentID != AgentId) break; } #endregion - UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags; - - if (handlerUpdatePrimFlags != null) - { - byte[] data = Pack.ToBytes(); - // 46,47,48 are special positions within the packet - // This may change so perhaps we need a better way - // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) - bool UsePhysics = (data[46] != 0) ? true : false; - bool IsTemporary = (data[47] != 0) ? true : false; - bool IsPhantom = (data[48] != 0) ? true : false; - handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); - } - break; - case PacketType.ObjectImage: - ObjectImagePacket imagePack = (ObjectImagePacket)Pack; - - UpdatePrimTexture handlerUpdatePrimTexture = null; - for (int i = 0; i < imagePack.ObjectData.Length; i++) + handlerCopyInventoryItem = null; + if (OnCopyInventoryItem != null) { - handlerUpdatePrimTexture = OnUpdatePrimTexture; - if (handlerUpdatePrimTexture != null) + foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) { - handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, - imagePack.ObjectData[i].TextureEntry, this); + handlerCopyInventoryItem = OnCopyInventoryItem; + if (handlerCopyInventoryItem != null) + { + handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, + datablock.OldItemID, datablock.NewFolderID, + Util.FieldToString(datablock.NewName)); + } } } break; - case PacketType.ObjectGrab: - ObjectGrabPacket grab = (ObjectGrabPacket)Pack; + case PacketType.MoveInventoryItem: + MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (grab.AgentData.SessionID != SessionId || - grab.AgentData.AgentID != AgentId) + if (moveitem.AgentData.SessionID != SessionId || + moveitem.AgentData.AgentID != AgentId) break; } #endregion - GrabObject handlerGrabObject = OnGrabObject; - - if (handlerGrabObject != null) + if (OnMoveInventoryItem != null) { - List touchArgs = new List(); - if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) + handlerMoveInventoryItem = null; + InventoryItemBase itm = null; + List items = new List(); + foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) { - foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } + itm = new InventoryItemBase(datablock.ItemID, AgentId); + itm.Folder = datablock.FolderID; + itm.Name = Util.FieldToString(datablock.NewName); + // weird, comes out as empty string + //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); + items.Add(itm); + } + handlerMoveInventoryItem = OnMoveInventoryItem; + if (handlerMoveInventoryItem != null) + { + handlerMoveInventoryItem(this, items); } - handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); } break; - case PacketType.ObjectGrabUpdate: - ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; + case PacketType.RemoveInventoryItem: + RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (grabUpdate.AgentData.SessionID != SessionId || - grabUpdate.AgentData.AgentID != AgentId) + if (removeItem.AgentData.SessionID != SessionId || + removeItem.AgentData.AgentID != AgentId) break; } #endregion - MoveObject handlerGrabUpdate = OnGrabUpdate; - - if (handlerGrabUpdate != null) + if (OnRemoveInventoryItem != null) { - List touchArgs = new List(); - if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) + handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) { - foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } + uuids.Add(datablock.ItemID); } - handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, - grabUpdate.ObjectData.GrabPosition, this, touchArgs); + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } + } break; - case PacketType.ObjectDeGrab: - ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + case PacketType.RemoveInventoryFolder: + RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deGrab.AgentData.SessionID != SessionId || - deGrab.AgentData.AgentID != AgentId) + if (removeFolder.AgentData.SessionID != SessionId || + removeFolder.AgentData.AgentID != AgentId) break; } #endregion - DeGrabObject handlerDeGrabObject = OnDeGrabObject; - if (handlerDeGrabObject != null) + if (OnRemoveInventoryFolder != null) { - List touchArgs = new List(); - if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) + handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) { - foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); } - handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); } break; - case PacketType.ObjectSpinStart: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); - ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; - + case PacketType.RemoveInventoryObjects: + RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStart.AgentData.SessionID != SessionId || - spinStart.AgentData.AgentID != AgentId) + if (removeObject.AgentData.SessionID != SessionId || + removeObject.AgentData.AgentID != AgentId) break; } #endregion + if (OnRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) + { + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); + } + } - SpinStart handlerSpinStart = OnSpinStart; - if (handlerSpinStart != null) + if (OnRemoveInventoryItem != null) { - handlerSpinStart(spinStart.ObjectData.ObjectID, this); + handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) + { + uuids.Add(datablock.ItemID); + } + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } } break; - case PacketType.ObjectSpinUpdate: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); - ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; + case PacketType.RequestTaskInventory: + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinUpdate.AgentData.SessionID != SessionId || - spinUpdate.AgentData.AgentID != AgentId) + if (requesttask.AgentData.SessionID != SessionId || + requesttask.AgentData.AgentID != AgentId) break; } #endregion - Vector3 axis; - float angle; - spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); - //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); - - SpinObject handlerSpinUpdate = OnSpinUpdate; - if (handlerSpinUpdate != null) + handlerRequestTaskInventory = OnRequestTaskInventory; + if (handlerRequestTaskInventory != null) { - handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); + handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); } break; - case PacketType.ObjectSpinStop: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); - ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; + case PacketType.UpdateTaskInventory: + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStop.AgentData.SessionID != SessionId || - spinStop.AgentData.AgentID != AgentId) + if (updatetask.AgentData.SessionID != SessionId || + updatetask.AgentData.AgentID != AgentId) break; } #endregion - SpinStop handlerSpinStop = OnSpinStop; - if (handlerSpinStop != null) + if (OnUpdateTaskInventory != null) { - handlerSpinStop(spinStop.ObjectData.ObjectID, this); + if (updatetask.UpdateData.Key == 0) + { + handlerUpdateTaskInventory = OnUpdateTaskInventory; + if (handlerUpdateTaskInventory != null) + { + TaskInventoryItem newTaskItem = new TaskInventoryItem(); + newTaskItem.ItemID = updatetask.InventoryData.ItemID; + newTaskItem.ParentID = updatetask.InventoryData.FolderID; + newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; + newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; + newTaskItem.GroupID = updatetask.InventoryData.GroupID; + newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; + newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; + newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; + newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; + newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; + newTaskItem.Type = updatetask.InventoryData.Type; + newTaskItem.InvType = updatetask.InventoryData.InvType; + newTaskItem.Flags = updatetask.InventoryData.Flags; + //newTaskItem.SaleType=updatetask.InventoryData.SaleType; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); + newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); + newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; + handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, + newTaskItem, updatetask.UpdateData.LocalID); + } + } } + break; - case PacketType.ObjectDescription: - ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; + case PacketType.RemoveTaskInventory: + + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objDes.AgentData.SessionID != SessionId || - objDes.AgentData.AgentID != AgentId) + if (removeTask.AgentData.SessionID != SessionId || + removeTask.AgentData.AgentID != AgentId) break; } #endregion - GenericCall7 handlerObjectDescription = null; + handlerRemoveTaskItem = OnRemoveTaskItem; - for (int i = 0; i < objDes.ObjectData.Length; i++) + if (handlerRemoveTaskItem != null) { - handlerObjectDescription = OnObjectDescription; - if (handlerObjectDescription != null) - { - handlerObjectDescription(this, objDes.ObjectData[i].LocalID, - Util.FieldToString(objDes.ObjectData[i].Description)); - } + handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); } + break; - case PacketType.ObjectName: - ObjectNamePacket objName = (ObjectNamePacket)Pack; - + + case PacketType.MoveTaskInventory: + + MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (objName.AgentData.SessionID != SessionId || - objName.AgentData.AgentID != AgentId) + if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || + moveTaskInventoryPacket.AgentData.AgentID != AgentId) break; } #endregion - - GenericCall7 handlerObjectName = null; - for (int i = 0; i < objName.ObjectData.Length; i++) - { - handlerObjectName = OnObjectName; - if (handlerObjectName != null) - { - handlerObjectName(this, objName.ObjectData[i].LocalID, - Util.FieldToString(objName.ObjectData[i].Name)); - } - } - break; - case PacketType.ObjectPermissions: - if (OnObjectPermissions != null) - { - ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (newobjPerms.AgentData.SessionID != SessionId || - newobjPerms.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerMoveTaskItem = OnMoveTaskItem; - UUID AgentID = newobjPerms.AgentData.AgentID; - UUID SessionID = newobjPerms.AgentData.SessionID; + if (handlerMoveTaskItem != null) + { + handlerMoveTaskItem( + this, moveTaskInventoryPacket.AgentData.FolderID, + moveTaskInventoryPacket.InventoryData.LocalID, + moveTaskInventoryPacket.InventoryData.ItemID); + } - ObjectPermissions handlerObjectPermissions = null; + break; - for (int i = 0; i < newobjPerms.ObjectData.Length; i++) - { - ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; + case PacketType.RezScript: + //m_log.Debug(Pack.ToString()); + RezScriptPacket rezScriptx = (RezScriptPacket)Pack; - byte field = permChanges.Field; - uint localID = permChanges.ObjectLocalID; - uint mask = permChanges.Mask; - byte set = permChanges.Set; - - handlerObjectPermissions = OnObjectPermissions; - - if (handlerObjectPermissions != null) - handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (rezScriptx.AgentData.SessionID != SessionId || + rezScriptx.AgentData.AgentID != AgentId) + break; } + #endregion - // Here's our data, - // PermField contains the field the info goes into - // PermField determines which mask we're changing - // - // chmask is the mask of the change - // setTF is whether we're adding it or taking it away - // - // objLocalID is the localID of the object. - - // Unfortunately, we have to pass the event the packet because objData is an array - // That means multiple object perms may be updated in a single packet. + handlerRezScript = OnRezScript; + InventoryItemBase item = new InventoryItemBase(); + item.ID = rezScriptx.InventoryBlock.ItemID; + item.Folder = rezScriptx.InventoryBlock.FolderID; + item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); + item.Owner = rezScriptx.InventoryBlock.OwnerID; + item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; + item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; + item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; + item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; + item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; + item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; + item.GroupID = rezScriptx.InventoryBlock.GroupID; + item.AssetType = rezScriptx.InventoryBlock.Type; + item.InvType = rezScriptx.InventoryBlock.InvType; + item.Flags = rezScriptx.InventoryBlock.Flags; + item.SaleType = rezScriptx.InventoryBlock.SaleType; + item.SalePrice = rezScriptx.InventoryBlock.SalePrice; + item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); + item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); + item.CreationDate = rezScriptx.InventoryBlock.CreationDate; + if (handlerRezScript != null) + { + handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); + } break; - case PacketType.Undo: - UndoPacket undoitem = (UndoPacket)Pack; + case PacketType.MapLayerRequest: + RequestMapLayer(); + break; + case PacketType.MapBlockRequest: + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (undoitem.AgentData.SessionID != SessionId || - undoitem.AgentData.AgentID != AgentId) + if (MapRequest.AgentData.SessionID != SessionId || + MapRequest.AgentData.AgentID != AgentId) break; } #endregion - if (undoitem.ObjectData.Length > 0) + handlerRequestMapBlocks = OnRequestMapBlocks; + if (handlerRequestMapBlocks != null) { - for (int i = 0; i < undoitem.ObjectData.Length; i++) - { - UUID objiD = undoitem.ObjectData[i].ObjectID; - AgentSit handlerOnUndo = OnUndo; - if (handlerOnUndo != null) - { - handlerOnUndo(this, objiD); - } - - } + handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); } break; - case PacketType.ObjectDuplicateOnRay: - ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; + case PacketType.MapNameRequest: + MapNameRequestPacket map = (MapNameRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dupeOnRay.AgentData.SessionID != SessionId || - dupeOnRay.AgentData.AgentID != AgentId) + if (map.AgentData.SessionID != SessionId || + map.AgentData.AgentID != AgentId) break; } #endregion - ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null; - - for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) + string mapName = Util.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + handlerMapNameRequest = OnMapNameRequest; + if (handlerMapNameRequest != null) { - handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; - if (handlerObjectDuplicateOnRay != null) - { - handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, - dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, - dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); - } + handlerMapNameRequest(this, mapName); } - break; - case PacketType.RequestObjectPropertiesFamily: - //This powers the little tooltip that appears when you move your mouse over an object - RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; + case PacketType.TeleportLandmarkRequest: + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (packToolTip.AgentData.SessionID != SessionId || - packToolTip.AgentData.AgentID != AgentId) + if (tpReq.Info.SessionID != SessionId || + tpReq.Info.AgentID != AgentId) break; } #endregion - RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + UUID lmid = tpReq.Info.LandmarkID; + AssetLandmark lm; + if (lmid != UUID.Zero) + { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); + AssetBase lma = m_assetService.Get(lmid.ToString()); - RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; + if (lma == null) + { + // Failed to find landmark + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } - if (handlerRequestObjectPropertiesFamily != null) + try + { + lm = new AssetLandmark(lma); + } + catch (NullReferenceException) + { + // asset not found generates null ref inside the assetlandmark constructor. + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + break; + } + } + else { - handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, - packObjBlock.ObjectID); + // Teleport home request + handlerTeleportHomeRequest = OnTeleportHomeRequest; + if (handlerTeleportHomeRequest != null) + { + handlerTeleportHomeRequest(AgentId, this); + } + break; + } + + handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; + if (handlerTeleportLandmarkRequest != null) + { + handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); } + else + { + //no event handler so cancel request + + + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } break; - case PacketType.ObjectIncludeInSearch: - //This lets us set objects to appear in search (stuff like DataSnapshot, etc) - ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; - ObjectIncludeInSearch handlerObjectIncludeInSearch = null; + + case PacketType.TeleportLocationRequest: + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; + // m_log.Debug(tpLocReq.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (packInSearch.AgentData.SessionID != SessionId || - packInSearch.AgentData.AgentID != AgentId) + if (tpLocReq.AgentData.SessionID != SessionId || + tpLocReq.AgentData.AgentID != AgentId) break; } #endregion - foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) + handlerTeleportLocationRequest = OnTeleportLocationRequest; + if (handlerTeleportLocationRequest != null) { - bool inSearch = objData.IncludeInSearch; - uint localID = objData.ObjectLocalID; + handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, + tpLocReq.Info.LookAt, 16); + } + else + { + //no event handler so cancel request + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; + tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; - handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + #endregion - if (handlerObjectIncludeInSearch != null) + case PacketType.UUIDNameRequest: + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + handlerNameRequest = OnNameFromUUIDRequest; + if (handlerNameRequest != null) { - handlerObjectIncludeInSearch(this, inSearch, localID); + handlerNameRequest(UUIDBlock.ID, this); } } break; - case PacketType.ScriptAnswerYes: - ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; + #region Parcel related packets + + case PacketType.RegionHandleRequest: + RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; + + handlerRegionHandleRequest = OnRegionHandleRequest; + if (handlerRegionHandleRequest != null) + { + handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); + } + break; + + case PacketType.ParcelInfoRequest: + ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scriptAnswer.AgentData.SessionID != SessionId || - scriptAnswer.AgentData.AgentID != AgentId) + if (pirPack.AgentData.SessionID != SessionId || + pirPack.AgentData.AgentID != AgentId) break; } #endregion - ScriptAnswer handlerScriptAnswer = OnScriptAnswer; - if (handlerScriptAnswer != null) + handlerParcelInfoRequest = OnParcelInfoRequest; + if (handlerParcelInfoRequest != null) { - handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); + handlerParcelInfoRequest(this, pirPack.Data.ParcelID); } break; - case PacketType.ObjectClickAction: - ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; + case PacketType.ParcelAccessListRequest: + ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ocpacket.AgentData.SessionID != SessionId || - ocpacket.AgentData.AgentID != AgentId) + if (requestPacket.AgentData.SessionID != SessionId || + requestPacket.AgentData.AgentID != AgentId) break; } #endregion - GenericCall7 handlerObjectClickAction = OnObjectClickAction; - if (handlerObjectClickAction != null) + handlerParcelAccessListRequest = OnParcelAccessListRequest; + + if (handlerParcelAccessListRequest != null) { - foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) - { - byte action = odata.ClickAction; - uint localID = odata.ObjectLocalID; - handlerObjectClickAction(this, localID, action.ToString()); - } + handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, + requestPacket.Data.Flags, requestPacket.Data.SequenceID, + requestPacket.Data.LocalID, this); } break; - case PacketType.ObjectMaterial: - ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; + case PacketType.ParcelAccessListUpdate: + ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ompacket.AgentData.SessionID != SessionId || - ompacket.AgentData.AgentID != AgentId) + if (updatePacket.AgentData.SessionID != SessionId || + updatePacket.AgentData.AgentID != AgentId) break; } #endregion - GenericCall7 handlerObjectMaterial = OnObjectMaterial; - if (handlerObjectMaterial != null) + List entries = new List(); + foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) { - foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) - { - byte material = odata.Material; - uint localID = odata.ObjectLocalID; - handlerObjectMaterial(this, localID, material.ToString()); - } + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = block.ID; + entry.Flags = (AccessList)block.Flags; + entry.Time = new DateTime(); + entries.Add(entry); } - break; - #endregion + handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; + if (handlerParcelAccessListUpdateRequest != null) + { + handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, + updatePacket.AgentData.SessionID, updatePacket.Data.Flags, + updatePacket.Data.LocalID, entries, this); + } + break; + case PacketType.ParcelPropertiesRequest: - #region Inventory/Asset/Other related packets + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; - case PacketType.RequestImage: - RequestImagePacket imageRequest = (RequestImagePacket)Pack; - //m_log.Debug("image request: " + Pack.ToString()); - #region Packet Session and User Check if (m_checkPackets) { - if (imageRequest.AgentData.SessionID != SessionId || - imageRequest.AgentData.AgentID != AgentId) + if (propertiesRequest.AgentData.SessionID != SessionId || + propertiesRequest.AgentData.AgentID != AgentId) break; } #endregion - //handlerTextureRequest = null; - - for (int i = 0; i < imageRequest.RequestImage.Length; i++) + handlerParcelPropertiesRequest = OnParcelPropertiesRequest; + if (handlerParcelPropertiesRequest != null) { - if (OnRequestTexture != null) - { - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = imageRequest.RequestImage[i].Image; - args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; - args.PacketNumber = imageRequest.RequestImage[i].Packet; - args.Priority = imageRequest.RequestImage[i].DownloadPriority; - args.requestSequence = imageRequest.Header.Sequence; - - //handlerTextureRequest = OnRequestTexture; - - //if (handlerTextureRequest != null) - //OnRequestTexture(this, args); - - // in the end, we null this, so we have to check if it's null - if (m_imageManager != null) - { - m_imageManager.EnqueueReq(args); - } - } + handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), + (int)Math.Round(propertiesRequest.ParcelData.South), + (int)Math.Round(propertiesRequest.ParcelData.East), + (int)Math.Round(propertiesRequest.ParcelData.North), + propertiesRequest.ParcelData.SequenceID, + propertiesRequest.ParcelData.SnapSelection, this); } break; + case PacketType.ParcelDivide: + ParcelDividePacket landDivide = (ParcelDividePacket)Pack; - case PacketType.TransferRequest: - //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); - - TransferRequestPacket transfer = (TransferRequestPacket)Pack; - //m_log.Debug("Transfer Request: " + transfer.ToString()); - // Validate inventory transfers - // Has to be done here, because AssetCache can't do it - // - - if (transfer.TransferInfo.SourceType == 3) + #region Packet Session and User Check + if (m_checkPackets) { - UUID taskID = new UUID(transfer.TransferInfo.Params, 48); - UUID itemID = new UUID(transfer.TransferInfo.Params, 64); - UUID requestID = new UUID(transfer.TransferInfo.Params, 80); - if (!(((Scene)m_scene).Permissions.BypassPermissions())) - { - if (taskID != UUID.Zero) // Prim - { - SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); - if (part == null) - break; - - if (part.OwnerID != AgentId) - break; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - break; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); - if (ti == null) - break; - - if (ti.OwnerID != AgentId) - break; - - if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - break; - - if (ti.AssetID != requestID) - break; - } - else // Agent - { - IInventoryService invService = m_scene.RequestModuleInterface(); - InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); - assetRequestItem = invService.GetItem(assetRequestItem); - if (assetRequestItem == null) - { - assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); - if (assetRequestItem == null) - return; - } - - // At this point, we need to apply perms - // only to notecards and scripts. All - // other asset types are always available - // - if (assetRequestItem.AssetType == 10) - { - if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view script", false); - break; - } - } - else if (assetRequestItem.AssetType == 7) - { - if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view notecard", false); - break; - } - } - - if (assetRequestItem.AssetID != requestID) - break; - } - } + if (landDivide.AgentData.SessionID != SessionId || + landDivide.AgentData.AgentID != AgentId) + break; } + #endregion - //m_assetCache.AddAssetRequest(this, transfer); - - MakeAssetRequest(transfer); - - /* RequestAsset = OnRequestAsset; - if (RequestAsset != null) - { - RequestAsset(this, transfer); - }*/ - break; - case PacketType.AssetUploadRequest: - AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - - - // m_log.Debug("upload request " + request.ToString()); - // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); - UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); - - UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest; - - if (handlerAssetUploadRequest != null) + handlerParcelDivideRequest = OnParcelDivideRequest; + if (handlerParcelDivideRequest != null) { - handlerAssetUploadRequest(this, temp, - request.AssetBlock.TransactionID, request.AssetBlock.Type, - request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, - request.AssetBlock.Tempfile); + handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), + (int)Math.Round(landDivide.ParcelData.South), + (int)Math.Round(landDivide.ParcelData.East), + (int)Math.Round(landDivide.ParcelData.North), this); } break; - case PacketType.RequestXfer: - RequestXferPacket xferReq = (RequestXferPacket)Pack; - - RequestXfer handlerRequestXfer = OnRequestXfer; + case PacketType.ParcelJoin: + ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; - if (handlerRequestXfer != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + if (landJoin.AgentData.SessionID != SessionId || + landJoin.AgentData.AgentID != AgentId) + break; } - break; - case PacketType.SendXferPacket: - SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; + #endregion - XferReceive handlerXferReceive = OnXferReceive; - if (handlerXferReceive != null) + handlerParcelJoinRequest = OnParcelJoinRequest; + + if (handlerParcelJoinRequest != null) { - handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), + (int)Math.Round(landJoin.ParcelData.South), + (int)Math.Round(landJoin.ParcelData.East), + (int)Math.Round(landJoin.ParcelData.North), this); } break; - case PacketType.ConfirmXferPacket: - ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; - - ConfirmXfer handlerConfirmXfer = OnConfirmXfer; - if (handlerConfirmXfer != null) + case PacketType.ParcelPropertiesUpdate: + ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); + if (parcelPropertiesPacket.AgentData.SessionID != SessionId || + parcelPropertiesPacket.AgentData.AgentID != AgentId) + break; } - break; - case PacketType.AbortXfer: - AbortXferPacket abortXfer = (AbortXferPacket)Pack; - AbortXfer handlerAbortXfer = OnAbortXfer; - if (handlerAbortXfer != null) + #endregion + + handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; + + if (handlerParcelPropertiesUpdateRequest != null) { - handlerAbortXfer(this, abortXfer.XferID.ID); - } + LandUpdateArgs args = new LandUpdateArgs(); + args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; + args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; + args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); + args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; + args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; + args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; + args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; + args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); + args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); + args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); + args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; + args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; + args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; + args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; + args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; + args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; + args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; + handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); + } break; - case PacketType.CreateInventoryFolder: - CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; + case PacketType.ParcelSelectObjects: + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFolder.AgentData.SessionID != SessionId || - invFolder.AgentData.AgentID != AgentId) + if (selectPacket.AgentData.SessionID != SessionId || + selectPacket.AgentData.AgentID != AgentId) break; } #endregion - CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder; - if (handlerCreateInventoryFolder != null) + List returnIDs = new List(); + + foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in + selectPacket.ReturnIDs) { - handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, - (ushort)invFolder.FolderData.Type, - Util.FieldToString(invFolder.FolderData.Name), - invFolder.FolderData.ParentID); + returnIDs.Add(rb.ReturnID); } - break; - case PacketType.UpdateInventoryFolder: - if (OnUpdateInventoryFolder != null) - { - UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (invFolderx.AgentData.SessionID != SessionId || - invFolderx.AgentData.AgentID != AgentId) - break; - } - #endregion - UpdateInventoryFolder handlerUpdateInventoryFolder = null; + handlerParcelSelectObjects = OnParcelSelectObjects; - for (int i = 0; i < invFolderx.FolderData.Length; i++) - { - handlerUpdateInventoryFolder = OnUpdateInventoryFolder; - if (handlerUpdateInventoryFolder != null) - { - OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, - (ushort)invFolderx.FolderData[i].Type, - Util.FieldToString(invFolderx.FolderData[i].Name), - invFolderx.FolderData[i].ParentID); - } - } - } - break; - case PacketType.MoveInventoryFolder: - if (OnMoveInventoryFolder != null) + if (handlerParcelSelectObjects != null) { - MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (invFoldery.AgentData.SessionID != SessionId || - invFoldery.AgentData.AgentID != AgentId) - break; - } - #endregion - - MoveInventoryFolder handlerMoveInventoryFolder = null; - - for (int i = 0; i < invFoldery.InventoryData.Length; i++) - { - handlerMoveInventoryFolder = OnMoveInventoryFolder; - if (handlerMoveInventoryFolder != null) - { - OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, - invFoldery.InventoryData[i].ParentID); - } - } + handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); } break; - case PacketType.CreateInventoryItem: - CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; - + case PacketType.ParcelObjectOwnersRequest: + //m_log.Debug(Pack.ToString()); + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (createItem.AgentData.SessionID != SessionId || - createItem.AgentData.AgentID != AgentId) + if (reqPacket.AgentData.SessionID != SessionId || + reqPacket.AgentData.AgentID != AgentId) break; } #endregion - CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem; - if (handlerCreateNewInventoryItem != null) + handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; + + if (handlerParcelObjectOwnerRequest != null) { - handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, - createItem.InventoryBlock.FolderID, - createItem.InventoryBlock.CallbackID, - Util.FieldToString(createItem.InventoryBlock.Description), - Util.FieldToString(createItem.InventoryBlock.Name), - createItem.InventoryBlock.InvType, - createItem.InventoryBlock.Type, - createItem.InventoryBlock.WearableType, - createItem.InventoryBlock.NextOwnerMask, - Util.UnixTimeSinceEpoch()); + handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); } break; - case PacketType.FetchInventory: - if (OnFetchInventory != null) - { - FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (FetchInventoryx.AgentData.SessionID != SessionId || - FetchInventoryx.AgentData.AgentID != AgentId) - break; - } - #endregion - - FetchInventory handlerFetchInventory = null; + case PacketType.ParcelGodForceOwner: + ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; - for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) - { - handlerFetchInventory = OnFetchInventory; + #region Packet Session and User Check + if (m_checkPackets) + { + if (godForceOwnerPacket.AgentData.SessionID != SessionId || + godForceOwnerPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - if (handlerFetchInventory != null) - { - OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, - FetchInventoryx.InventoryData[i].OwnerID); - } - } + handlerParcelGodForceOwner = OnParcelGodForceOwner; + if (handlerParcelGodForceOwner != null) + { + handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); } break; - case PacketType.FetchInventoryDescendents: - FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + case PacketType.ParcelRelease: + ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Fetch.AgentData.SessionID != SessionId || - Fetch.AgentData.AgentID != AgentId) + if (releasePacket.AgentData.SessionID != SessionId || + releasePacket.AgentData.AgentID != AgentId) break; } #endregion - FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents; - if (handlerFetchInventoryDescendents != null) + handlerParcelAbandonRequest = OnParcelAbandonRequest; + if (handlerParcelAbandonRequest != null) { - handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, - Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, - Fetch.InventoryData.SortOrder); + handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); } break; - case PacketType.PurgeInventoryDescendents: - PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + case PacketType.ParcelReclaim: + ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Purge.AgentData.SessionID != SessionId || - Purge.AgentData.AgentID != AgentId) + if (reclaimPacket.AgentData.SessionID != SessionId || + reclaimPacket.AgentData.AgentID != AgentId) break; } #endregion - PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; - if (handlerPurgeInventoryDescendents != null) + handlerParcelReclaim = OnParcelReclaim; + if (handlerParcelReclaim != null) { - handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + handlerParcelReclaim(reclaimPacket.Data.LocalID, this); } break; - case PacketType.UpdateInventoryItem: - UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; - + case PacketType.ParcelReturnObjects: + + + ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (inventoryItemUpdate.AgentData.SessionID != SessionId || - inventoryItemUpdate.AgentData.AgentID != AgentId) + if (parcelReturnObjects.AgentData.SessionID != SessionId || + parcelReturnObjects.AgentData.AgentID != AgentId) break; } #endregion - if (OnUpdateInventoryItem != null) - { - UpdateInventoryItem handlerUpdateInventoryItem = null; - for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) - { - handlerUpdateInventoryItem = OnUpdateInventoryItem; + UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; + for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) + puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; - if (handlerUpdateInventoryItem != null) - { - InventoryItemBase itemUpd = new InventoryItemBase(); - itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; - itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); - itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); - itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; - itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; - itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; - itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; - itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; - itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; - itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; - itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; - itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; - itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; - itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; + UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; + + for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) + puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; + + handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; + if (handlerParcelReturnObjectsRequest != null) + { + handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); - OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, - inventoryItemUpdate.InventoryData[i].ItemID, - itemUpd); - } - } } break; - case PacketType.CopyInventoryItem: - CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; + + case PacketType.ParcelSetOtherCleanTime: + ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (copyitem.AgentData.SessionID != SessionId || - copyitem.AgentData.AgentID != AgentId) + if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || + parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) break; } #endregion - CopyInventoryItem handlerCopyInventoryItem = null; - if (OnCopyInventoryItem != null) + handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; + if (handlerParcelSetOtherCleanTime != null) { - foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) - { - handlerCopyInventoryItem = OnCopyInventoryItem; - if (handlerCopyInventoryItem != null) - { - handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, - datablock.OldItemID, datablock.NewFolderID, - Util.FieldToString(datablock.NewName)); - } - } + handlerParcelSetOtherCleanTime(this, + parcelSetOtherCleanTimePacket.ParcelData.LocalID, + parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); } break; - case PacketType.MoveInventoryItem: - MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; + + case PacketType.LandStatRequest: + LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moveitem.AgentData.SessionID != SessionId || - moveitem.AgentData.AgentID != AgentId) + if (lsrp.AgentData.SessionID != SessionId || + lsrp.AgentData.AgentID != AgentId) break; } #endregion - if (OnMoveInventoryItem != null) + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) { - MoveInventoryItem handlerMoveInventoryItem = null; - InventoryItemBase itm = null; - List items = new List(); - foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) - { - itm = new InventoryItemBase(datablock.ItemID, AgentId); - itm.Folder = datablock.FolderID; - itm.Name = Util.FieldToString(datablock.NewName); - // weird, comes out as empty string - //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); - items.Add(itm); - } - handlerMoveInventoryItem = OnMoveInventoryItem; - if (handlerMoveInventoryItem != null) - { - handlerMoveInventoryItem(this, items); - } + handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); } break; - case PacketType.RemoveInventoryItem: - RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; + + case PacketType.ParcelDwellRequest: + ParcelDwellRequestPacket dwellrq = + (ParcelDwellRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeItem.AgentData.SessionID != SessionId || - removeItem.AgentData.AgentID != AgentId) + if (dwellrq.AgentData.SessionID != SessionId || + dwellrq.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryItem != null) + handlerParcelDwellRequest = OnParcelDwellRequest; + if (handlerParcelDwellRequest != null) { - RemoveInventoryItem handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) - { - handlerRemoveInventoryItem(this, uuids); - } - + handlerParcelDwellRequest(dwellrq.Data.LocalID, this); } break; - case PacketType.RemoveInventoryFolder: - RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (removeFolder.AgentData.SessionID != SessionId || - removeFolder.AgentData.AgentID != AgentId) - break; - } #endregion - if (OnRemoveInventoryFolder != null) - { - RemoveInventoryFolder handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder(this, uuids); - } - } - break; - case PacketType.RemoveInventoryObjects: - RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (removeObject.AgentData.SessionID != SessionId || - removeObject.AgentData.AgentID != AgentId) - break; - } - #endregion - if (OnRemoveInventoryFolder != null) - { - RemoveInventoryFolder handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder(this, uuids); - } - } + #region Estate Packets - if (OnRemoveInventoryItem != null) - { - RemoveInventoryItem handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) - { - handlerRemoveInventoryItem(this, uuids); - } - } - break; - case PacketType.RequestTaskInventory: - RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; + case PacketType.EstateOwnerMessage: + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; + //m_log.Debug(messagePacket.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (requesttask.AgentData.SessionID != SessionId || - requesttask.AgentData.AgentID != AgentId) + if (messagePacket.AgentData.SessionID != SessionId || + messagePacket.AgentData.AgentID != AgentId) break; } #endregion - RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory; - if (handlerRequestTaskInventory != null) - { - handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); - } - break; - case PacketType.UpdateTaskInventory: - UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + switch (Utils.BytesToString(messagePacket.MethodData.Method)) { - if (updatetask.AgentData.SessionID != SessionId || - updatetask.AgentData.AgentID != AgentId) + case "getinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); + } break; - } - #endregion - - if (OnUpdateTaskInventory != null) - { - if (updatetask.UpdateData.Key == 0) - { - UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory; - if (handlerUpdateTaskInventory != null) + case "setregioninfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) { - TaskInventoryItem newTaskItem = new TaskInventoryItem(); - newTaskItem.ItemID = updatetask.InventoryData.ItemID; - newTaskItem.ParentID = updatetask.InventoryData.FolderID; - newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; - newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; - newTaskItem.GroupID = updatetask.InventoryData.GroupID; - newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; - newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; - newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; - newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; - newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; - //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; - newTaskItem.Type = updatetask.InventoryData.Type; - newTaskItem.InvType = updatetask.InventoryData.InvType; - newTaskItem.Flags = updatetask.InventoryData.Flags; - //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; - newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); - newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); - newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; - handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, - newTaskItem, updatetask.UpdateData.LocalID); + OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), + convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), + Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), + (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), + Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), + convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); } - } - } - - break; - - case PacketType.RemoveTaskInventory: - - RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (removeTask.AgentData.SessionID != SessionId || - removeTask.AgentData.AgentID != AgentId) break; - } - #endregion +// case "texturebase": +// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) +// { +// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) +// { +// string s = Utils.BytesToString(block.Parameter); +// string[] splitField = s.Split(' '); +// if (splitField.Length == 2) +// { +// UUID tempUUID = new UUID(splitField[1]); +// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); +// } +// } +// } +// break; + case "texturedetail": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 2) + { + Int16 corner = Convert.ToInt16(splitField[0]); + UUID textureUUID = new UUID(splitField[1]); - RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem; + OnSetEstateTerrainDetailTexture(this, corner, textureUUID); + } + } + } - if (handlerRemoveTaskItem != null) - { - handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); - } + break; + case "textureheights": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 3) + { + Int16 corner = Convert.ToInt16(splitField[0]); + float lowValue = (float)Convert.ToDecimal(splitField[1]); + float highValue = (float)Convert.ToDecimal(splitField[2]); - break; + OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); + } + } + } + break; + case "texturecommit": + OnCommitEstateTerrainTextureRequest(this); + break; + case "setregionterrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length != 9) + { + m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); + } + else + { + try + { + string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float WaterHeight = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); + bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); + bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); + float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); + bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); + bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); + float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); - case PacketType.MoveTaskInventory: + OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); - MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; + } + catch (Exception ex) + { + m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); + } + } + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || - moveTaskInventoryPacket.AgentData.AgentID != AgentId) break; - } - #endregion - - MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem; - - if (handlerMoveTaskItem != null) - { - handlerMoveTaskItem( - this, moveTaskInventoryPacket.AgentData.FolderID, - moveTaskInventoryPacket.InventoryData.LocalID, - moveTaskInventoryPacket.InventoryData.ItemID); - } + case "restart": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + float timeSeconds; + Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); + timeSeconds = (int)timeSeconds; + OnEstateRestartSimRequest(this, (int)timeSeconds); - break; + } + } + break; + case "estatechangecovenantid": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); + OnEstateChangeCovenantRequest(this, newCovenantID); + } + } + break; + case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); - case PacketType.RezScript: - //m_log.Debug(Pack.ToString()); - RezScriptPacket rezScriptx = (RezScriptPacket)Pack; + } + break; + case "simulatormessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "instantmessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length < 5) + break; + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "setregiondebug": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); + bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); + bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); - #region Packet Session and User Check - if (m_checkPackets) - { - if (rezScriptx.AgentData.SessionID != SessionId || - rezScriptx.AgentData.AgentID != AgentId) + OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); + } break; - } - #endregion + case "teleporthomeuser": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UUID Prey; - RezScript handlerRezScript = OnRezScript; - InventoryItemBase item = new InventoryItemBase(); - item.ID = rezScriptx.InventoryBlock.ItemID; - item.Folder = rezScriptx.InventoryBlock.FolderID; - item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); - item.Owner = rezScriptx.InventoryBlock.OwnerID; - item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; - item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; - item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; - item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; - item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; - item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; - item.GroupID = rezScriptx.InventoryBlock.GroupID; - item.AssetType = rezScriptx.InventoryBlock.Type; - item.InvType = rezScriptx.InventoryBlock.InvType; - item.Flags = rezScriptx.InventoryBlock.Flags; - item.SaleType = rezScriptx.InventoryBlock.SaleType; - item.SalePrice = rezScriptx.InventoryBlock.SalePrice; - item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); - item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); - item.CreationDate = rezScriptx.InventoryBlock.CreationDate; + UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); - if (handlerRezScript != null) - { - handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + } + break; + case "teleporthomeallusers": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); + } + break; + case "colliders": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 1, 0, "", this); + } + break; + case "scripts": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 0, 0, "", this); + } + break; + case "terrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length > 0) + { + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") + { + handlerBakeTerrain = OnBakeTerrain; + if (handlerBakeTerrain != null) + { + handlerBakeTerrain(this); + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") + { + if (messagePacket.ParamList.Length > 1) + { + handlerRequestTerrain = OnRequestTerrain; + if (handlerRequestTerrain != null) + { + handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") + { + if (messagePacket.ParamList.Length > 1) + { + handlerUploadTerrain = OnUploadTerrain; + if (handlerUploadTerrain != null) + { + handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } + + } + + + } + break; + + case "estatechangeinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + + handlerEstateChangeInfo = OnEstateChangeInfo; + if (handlerEstateChangeInfo != null) + { + handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); + } + } + break; + + default: + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + break; } - break; + + //int parcelID, uint reportType, uint requestflags, string filter + + //lsrp.RequestData.ParcelLocalID; + //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts + //lsrp.RequestData.RequestFlags; + //lsrp.RequestData.Filter; - case PacketType.MapLayerRequest: - RequestMapLayer(); break; - case PacketType.MapBlockRequest: - MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; + + case PacketType.RequestRegionInfo: + RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; #region Packet Session and User Check if (m_checkPackets) { - if (MapRequest.AgentData.SessionID != SessionId || - MapRequest.AgentData.AgentID != AgentId) + if (mPacket.SessionID != SessionId || + mPacket.AgentID != AgentId) break; } #endregion - RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks; - if (handlerRequestMapBlocks != null) + handlerRegionInfoRequest = OnRegionInfoRequest; + if (handlerRegionInfoRequest != null) { - handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, - MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); + handlerRegionInfoRequest(this); } break; - case PacketType.MapNameRequest: - MapNameRequestPacket map = (MapNameRequestPacket)Pack; + case PacketType.EstateCovenantRequest: - #region Packet Session and User Check - if (m_checkPackets) + //EstateCovenantRequestPacket.AgentDataBlock epack = + // ((EstateCovenantRequestPacket)Pack).AgentData; + + handlerEstateCovenantRequest = OnEstateCovenantRequest; + if (handlerEstateCovenantRequest != null) { - if (map.AgentData.SessionID != SessionId || - map.AgentData.AgentID != AgentId) - break; + handlerEstateCovenantRequest(this); } + break; + #endregion - string mapName = Util.UTF8.GetString(map.NameData.Name, 0, - map.NameData.Name.Length - 1); - RequestMapName handlerMapNameRequest = OnMapNameRequest; - if (handlerMapNameRequest != null) + #region GodPackets + + case PacketType.RequestGodlikePowers: + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + UUID token = rblock.Token; + + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + + handlerReqGodlikePowers = OnRequestGodlikePowers; + + if (handlerReqGodlikePowers != null) { - handlerMapNameRequest(this, mapName); + handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); } + break; - case PacketType.TeleportLandmarkRequest: - TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; + case PacketType.GodKickUser: + GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) + if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) { - if (tpReq.Info.SessionID != SessionId || - tpReq.Info.AgentID != AgentId) - break; - } - #endregion - - UUID lmid = tpReq.Info.LandmarkID; - AssetLandmark lm; - if (lmid != UUID.Zero) - { - //AssetBase lma = m_assetCache.GetAsset(lmid, false); - AssetBase lma = m_assetService.Get(lmid.ToString()); - - if (lma == null) - { - // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - } - - try - { - lm = new AssetLandmark(lma); - } - catch (NullReferenceException) + handlerGodKickUser = OnGodKickUser; + if (handlerGodKickUser != null) { - // asset not found generates null ref inside the assetlandmark constructor. - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - break; + handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, + gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); } } else { - // Teleport home request - UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest; - if (handlerTeleportHomeRequest != null) - { - handlerTeleportHomeRequest(AgentId, this); - } - break; + SendAgentAlertMessage("Kick request denied", false); } + //KickUserPacket kupack = new KickUserPacket(); + //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; - TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; - if (handlerTeleportLandmarkRequest != null) + //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; + //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; + + //kupack.TargetBlock.TargetIP = (uint)0; + //kupack.TargetBlock.TargetPort = (ushort)0; + //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; + + //OutPacket(kupack, ThrottleOutPacketType.Task); + break; + + #endregion + + #region Economy/Transaction Packets + + case PacketType.MoneyBalanceRequest: + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + if (moneybalancerequestpacket.AgentData.SessionID != SessionId || + moneybalancerequestpacket.AgentData.AgentID != AgentId) + break; } - else + #endregion + + handlerMoneyBalanceRequest = OnMoneyBalanceRequest; + + if (handlerMoneyBalanceRequest != null) { - //no event handler so cancel request + handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + } + break; + case PacketType.EconomyDataRequest: - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.AgentID = tpReq.Info.AgentID; - tpCancel.Info.SessionID = tpReq.Info.SessionID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + + handlerEconomoyDataRequest = OnEconomyDataRequest; + if (handlerEconomoyDataRequest != null) + { + handlerEconomoyDataRequest(AgentId); + } + break; + case PacketType.RequestPayPrice: + RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + handlerRequestPayPrice = OnRequestPayPrice; + if (handlerRequestPayPrice != null) + { + handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); } break; - case PacketType.TeleportLocationRequest: - TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; - // m_log.Debug(tpLocReq.ToString()); + case PacketType.ObjectSaleInfo: + ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (tpLocReq.AgentData.SessionID != SessionId || - tpLocReq.AgentData.AgentID != AgentId) + if (objectSaleInfoPacket.AgentData.SessionID != SessionId || + objectSaleInfoPacket.AgentData.AgentID != AgentId) break; } #endregion - TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; - if (handlerTeleportLocationRequest != null) - { - handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, - tpLocReq.Info.LookAt, 16); - } - else + handlerObjectSaleInfo = OnObjectSaleInfo; + if (handlerObjectSaleInfo != null) { - //no event handler so cancel request - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; - tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + foreach (ObjectSaleInfoPacket.ObjectDataBlock d + in objectSaleInfoPacket.ObjectData) + { + handlerObjectSaleInfo(this, + objectSaleInfoPacket.AgentData.AgentID, + objectSaleInfoPacket.AgentData.SessionID, + d.LocalID, + d.SaleType, + d.SalePrice); + } } break; + case PacketType.ObjectBuy: + ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objectBuyPacket.AgentData.SessionID != SessionId || + objectBuyPacket.AgentData.AgentID != AgentId) + break; + } #endregion - case PacketType.UUIDNameRequest: - UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + handlerObjectBuy = OnObjectBuy; - foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + if (handlerObjectBuy != null) { - UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest; - if (handlerNameRequest != null) + foreach (ObjectBuyPacket.ObjectDataBlock d + in objectBuyPacket.ObjectData) { - handlerNameRequest(UUIDBlock.ID, this); + handlerObjectBuy(this, + objectBuyPacket.AgentData.AgentID, + objectBuyPacket.AgentData.SessionID, + objectBuyPacket.AgentData.GroupID, + objectBuyPacket.AgentData.CategoryID, + d.ObjectLocalID, + d.SaleType, + d.SalePrice); } } break; - #region Parcel related packets + #endregion - case PacketType.RegionHandleRequest: - RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; + #region Script Packets - RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; - if (handlerRegionHandleRequest != null) + case PacketType.GetScriptRunning: + GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; + + handlerGetScriptRunning = OnGetScriptRunning; + if (handlerGetScriptRunning != null) { - handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); + handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); } break; - case PacketType.ParcelInfoRequest: - ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; + case PacketType.SetScriptRunning: + SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pirPack.AgentData.SessionID != SessionId || - pirPack.AgentData.AgentID != AgentId) + if (setScriptRunning.AgentData.SessionID != SessionId || + setScriptRunning.AgentData.AgentID != AgentId) break; } #endregion - ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest; - if (handlerParcelInfoRequest != null) + handlerSetScriptRunning = OnSetScriptRunning; + if (handlerSetScriptRunning != null) { - handlerParcelInfoRequest(this, pirPack.Data.ParcelID); + handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); } break; - case PacketType.ParcelAccessListRequest: - ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; + case PacketType.ScriptReset: + ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (requestPacket.AgentData.SessionID != SessionId || - requestPacket.AgentData.AgentID != AgentId) + if (scriptResetPacket.AgentData.SessionID != SessionId || + scriptResetPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest; - - if (handlerParcelAccessListRequest != null) + handlerScriptReset = OnScriptReset; + if (handlerScriptReset != null) { - handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, - requestPacket.Data.Flags, requestPacket.Data.SequenceID, - requestPacket.Data.LocalID, this); + handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); } break; - case PacketType.ParcelAccessListUpdate: - ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; + #endregion + + #region Gesture Managment + + case PacketType.ActivateGestures: + ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (updatePacket.AgentData.SessionID != SessionId || - updatePacket.AgentData.AgentID != AgentId) + if (activateGesturePacket.AgentData.SessionID != SessionId || + activateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - List entries = new List(); - foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) + handlerActivateGesture = OnActivateGesture; + if (handlerActivateGesture != null) { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = block.ID; - entry.Flags = (AccessList)block.Flags; - entry.Time = new DateTime(); - entries.Add(entry); + handlerActivateGesture(this, + activateGesturePacket.Data[0].AssetID, + activateGesturePacket.Data[0].ItemID); } + else m_log.Error("Null pointer for activateGesture"); - ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; - if (handlerParcelAccessListUpdateRequest != null) - { - handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, - updatePacket.AgentData.SessionID, updatePacket.Data.Flags, - updatePacket.Data.LocalID, entries, this); - } break; - case PacketType.ParcelPropertiesRequest: - ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; + case PacketType.DeactivateGestures: + DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (propertiesRequest.AgentData.SessionID != SessionId || - propertiesRequest.AgentData.AgentID != AgentId) + if (deactivateGesturePacket.AgentData.SessionID != SessionId || + deactivateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest; - if (handlerParcelPropertiesRequest != null) + handlerDeactivateGesture = OnDeactivateGesture; + if (handlerDeactivateGesture != null) { - handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), - (int)Math.Round(propertiesRequest.ParcelData.South), - (int)Math.Round(propertiesRequest.ParcelData.East), - (int)Math.Round(propertiesRequest.ParcelData.North), - propertiesRequest.ParcelData.SequenceID, - propertiesRequest.ParcelData.SnapSelection, this); + handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); } break; - case PacketType.ParcelDivide: - ParcelDividePacket landDivide = (ParcelDividePacket)Pack; + case PacketType.ObjectOwner: + ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (landDivide.AgentData.SessionID != SessionId || - landDivide.AgentData.AgentID != AgentId) + if (objectOwnerPacket.AgentData.SessionID != SessionId || + objectOwnerPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest; - if (handlerParcelDivideRequest != null) + List localIDs = new List(); + + foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) + localIDs.Add(d.ObjectLocalID); + + handlerObjectOwner = OnObjectOwner; + if (handlerObjectOwner != null) { - handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), - (int)Math.Round(landDivide.ParcelData.South), - (int)Math.Round(landDivide.ParcelData.East), - (int)Math.Round(landDivide.ParcelData.North), this); + handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); } break; - case PacketType.ParcelJoin: - ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (landJoin.AgentData.SessionID != SessionId || - landJoin.AgentData.AgentID != AgentId) - break; - } #endregion - ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest; - if (handlerParcelJoinRequest != null) - { - handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), - (int)Math.Round(landJoin.ParcelData.South), - (int)Math.Round(landJoin.ParcelData.East), - (int)Math.Round(landJoin.ParcelData.North), this); - } + #region unimplemented handlers + + case PacketType.StartPingCheck: + // Send the client the ping response back + // Pass the same PingID in the matching packet + // Handled In the packet processing + //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); + break; + case PacketType.CompletePingCheck: + // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client + //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); + break; + + case PacketType.ViewerStats: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); break; - case PacketType.ParcelPropertiesUpdate: - ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; + + case PacketType.MapItemRequest: + MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (parcelPropertiesPacket.AgentData.SessionID != SessionId || - parcelPropertiesPacket.AgentData.AgentID != AgentId) + if (mirpk.AgentData.SessionID != SessionId || + mirpk.AgentData.AgentID != AgentId) break; } #endregion - ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; - - if (handlerParcelPropertiesUpdateRequest != null) + //m_log.Debug(mirpk.ToString()); + handlerMapItemRequest = OnMapItemRequest; + if (handlerMapItemRequest != null) { - LandUpdateArgs args = new LandUpdateArgs(); + handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, + mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, + mirpk.RequestData.RegionHandle); - args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; - args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; - args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); - args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; - args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; - args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; - args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; - args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); - args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); - args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); - args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; - args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; - args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; - args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; - args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; - args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; - args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; - handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); } break; - case PacketType.ParcelSelectObjects: - ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; + + case PacketType.TransferAbort: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); + break; + case PacketType.MuteListRequest: + MuteListRequestPacket muteListRequest = + (MuteListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (selectPacket.AgentData.SessionID != SessionId || - selectPacket.AgentData.AgentID != AgentId) + if (muteListRequest.AgentData.SessionID != SessionId || + muteListRequest.AgentData.AgentID != AgentId) break; } #endregion - List returnIDs = new List(); - - foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in - selectPacket.ReturnIDs) + handlerMuteListRequest = OnMuteListRequest; + if (handlerMuteListRequest != null) { - returnIDs.Add(rb.ReturnID); + handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); } - - ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects; - - if (handlerParcelSelectObjects != null) + else { - handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, - Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); + SendUseCachedMuteList(); } break; - case PacketType.ParcelObjectOwnersRequest: - //m_log.Debug(Pack.ToString()); - ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + case PacketType.UseCircuitCode: + // Don't display this one, we handle it at a lower level + break; + + case PacketType.AgentHeightWidth: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); + break; + + case PacketType.InventoryDescendents: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); + + break; + case PacketType.DirPlacesQuery: + DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; + //m_log.Debug(dirPlacesQueryPacket.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (reqPacket.AgentData.SessionID != SessionId || - reqPacket.AgentData.AgentID != AgentId) + if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || + dirPlacesQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; - - if (handlerParcelObjectOwnerRequest != null) + handlerDirPlacesQuery = OnDirPlacesQuery; + if (handlerDirPlacesQuery != null) { - handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); + handlerDirPlacesQuery(this, + dirPlacesQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.QueryText), + (int)dirPlacesQueryPacket.QueryData.QueryFlags, + (int)dirPlacesQueryPacket.QueryData.Category, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.SimName), + dirPlacesQueryPacket.QueryData.QueryStart); } break; - case PacketType.ParcelGodForceOwner: - ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; + case PacketType.DirFindQuery: + DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (godForceOwnerPacket.AgentData.SessionID != SessionId || - godForceOwnerPacket.AgentData.AgentID != AgentId) + if (dirFindQueryPacket.AgentData.SessionID != SessionId || + dirFindQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner; - if (handlerParcelGodForceOwner != null) + handlerDirFindQuery = OnDirFindQuery; + if (handlerDirFindQuery != null) { - handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); + handlerDirFindQuery(this, + dirFindQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirFindQueryPacket.QueryData.QueryText), + dirFindQueryPacket.QueryData.QueryFlags, + dirFindQueryPacket.QueryData.QueryStart); } break; - case PacketType.ParcelRelease: - ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; + case PacketType.DirLandQuery: + DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (releasePacket.AgentData.SessionID != SessionId || - releasePacket.AgentData.AgentID != AgentId) + if (dirLandQueryPacket.AgentData.SessionID != SessionId || + dirLandQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest; - if (handlerParcelAbandonRequest != null) + handlerDirLandQuery = OnDirLandQuery; + if (handlerDirLandQuery != null) { - handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); + handlerDirLandQuery(this, + dirLandQueryPacket.QueryData.QueryID, + dirLandQueryPacket.QueryData.QueryFlags, + dirLandQueryPacket.QueryData.SearchType, + dirLandQueryPacket.QueryData.Price, + dirLandQueryPacket.QueryData.Area, + dirLandQueryPacket.QueryData.QueryStart); } break; - case PacketType.ParcelReclaim: - ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; + case PacketType.DirPopularQuery: + DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (reclaimPacket.AgentData.SessionID != SessionId || - reclaimPacket.AgentData.AgentID != AgentId) + if (dirPopularQueryPacket.AgentData.SessionID != SessionId || + dirPopularQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelReclaim handlerParcelReclaim = OnParcelReclaim; - if (handlerParcelReclaim != null) + handlerDirPopularQuery = OnDirPopularQuery; + if (handlerDirPopularQuery != null) { - handlerParcelReclaim(reclaimPacket.Data.LocalID, this); + handlerDirPopularQuery(this, + dirPopularQueryPacket.QueryData.QueryID, + dirPopularQueryPacket.QueryData.QueryFlags); } break; - case PacketType.ParcelReturnObjects: - - - ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; + case PacketType.DirClassifiedQuery: + DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (parcelReturnObjects.AgentData.SessionID != SessionId || - parcelReturnObjects.AgentData.AgentID != AgentId) + if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || + dirClassifiedQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; - for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) - puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; - - UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; - - for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) - puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; - - ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; - if (handlerParcelReturnObjectsRequest != null) + handlerDirClassifiedQuery = OnDirClassifiedQuery; + if (handlerDirClassifiedQuery != null) { - handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); - + handlerDirClassifiedQuery(this, + dirClassifiedQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirClassifiedQueryPacket.QueryData.QueryText), + dirClassifiedQueryPacket.QueryData.QueryFlags, + dirClassifiedQueryPacket.QueryData.Category, + dirClassifiedQueryPacket.QueryData.QueryStart); } break; - - case PacketType.ParcelSetOtherCleanTime: - ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; + case PacketType.EventInfoRequest: + EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || - parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) + if (eventInfoRequestPacket.AgentData.SessionID != SessionId || + eventInfoRequestPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; - if (handlerParcelSetOtherCleanTime != null) + if (OnEventInfoRequest != null) { - handlerParcelSetOtherCleanTime(this, - parcelSetOtherCleanTimePacket.ParcelData.LocalID, - parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); + OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); } break; - case PacketType.LandStatRequest: - LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; + #region Calling Card + + case PacketType.OfferCallingCard: + OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (lsrp.AgentData.SessionID != SessionId || - lsrp.AgentData.AgentID != AgentId) + if (offerCallingCardPacket.AgentData.SessionID != SessionId || + offerCallingCardPacket.AgentData.AgentID != AgentId) break; } #endregion - GodLandStatRequest handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + if (OnOfferCallingCard != null) { - handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); + OnOfferCallingCard(this, + offerCallingCardPacket.AgentBlock.DestID, + offerCallingCardPacket.AgentBlock.TransactionID); } break; - case PacketType.ParcelDwellRequest: - ParcelDwellRequestPacket dwellrq = - (ParcelDwellRequestPacket)Pack; + case PacketType.AcceptCallingCard: + AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dwellrq.AgentData.SessionID != SessionId || - dwellrq.AgentData.AgentID != AgentId) + if (acceptCallingCardPacket.AgentData.SessionID != SessionId || + acceptCallingCardPacket.AgentData.AgentID != AgentId) break; } #endregion - ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest; - if (handlerParcelDwellRequest != null) + // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should + // contain exactly one entry + if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) { - handlerParcelDwellRequest(dwellrq.Data.LocalID, this); + OnAcceptCallingCard(this, + acceptCallingCardPacket.TransactionBlock.TransactionID, + acceptCallingCardPacket.FolderData[0].FolderID); } break; - #endregion + case PacketType.DeclineCallingCard: + DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; - #region Estate Packets + #region Packet Session and User Check + if (m_checkPackets) + { + if (declineCallingCardPacket.AgentData.SessionID != SessionId || + declineCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - case PacketType.EstateOwnerMessage: - EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; - //m_log.Debug(messagePacket.ToString()); + if (OnDeclineCallingCard != null) + { + OnDeclineCallingCard(this, + declineCallingCardPacket.TransactionBlock.TransactionID); + } + break; + #endregion + + #region Groups + case PacketType.ActivateGroup: + ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (messagePacket.AgentData.SessionID != SessionId || - messagePacket.AgentData.AgentID != AgentId) + if (activateGroupPacket.AgentData.SessionID != SessionId || + activateGroupPacket.AgentData.AgentID != AgentId) break; } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + if (m_GroupsModule != null) { - case "getinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); - } - break; - case "setregioninfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), - convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), - Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), - (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), - Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), - convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); - } - break; -// case "texturebase": -// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) -// { -// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) -// { -// string s = Utils.BytesToString(block.Parameter); -// string[] splitField = s.Split(' '); -// if (splitField.Length == 2) -// { -// UUID tempUUID = new UUID(splitField[1]); -// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); -// } -// } -// } -// break; - case "texturedetail": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 2) - { - Int16 corner = Convert.ToInt16(splitField[0]); - UUID textureUUID = new UUID(splitField[1]); + m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); + m_GroupsModule.SendAgentGroupDataUpdate(this); + } + break; - OnSetEstateTerrainDetailTexture(this, corner, textureUUID); - } - } - } + case PacketType.GroupTitlesRequest: + GroupTitlesRequestPacket groupTitlesRequest = + (GroupTitlesRequestPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitlesRequest.AgentData.SessionID != SessionId || + groupTitlesRequest.AgentData.AgentID != AgentId) break; - case "textureheights": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 3) - { - Int16 corner = Convert.ToInt16(splitField[0]); - float lowValue = (float)Convert.ToDecimal(splitField[1]); - float highValue = (float)Convert.ToDecimal(splitField[2]); + } + #endregion - OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); - } - } - } - break; - case "texturecommit": - OnCommitEstateTerrainTextureRequest(this); - break; - case "setregionterrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length != 9) - { - m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); - } - else - { - try - { - string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float WaterHeight = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); - bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); - bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); - float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); - bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); - bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); - float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); + if (m_GroupsModule != null) + { + GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); + groupTitlesReply.AgentData = + new GroupTitlesReplyPacket.AgentDataBlock(); - } - catch (Exception ex) - { - m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); - } - } - } + groupTitlesReply.AgentData.AgentID = AgentId; + groupTitlesReply.AgentData.GroupID = + groupTitlesRequest.AgentData.GroupID; - break; - case "restart": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - float timeSeconds; - Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); - timeSeconds = (int)timeSeconds; - OnEstateRestartSimRequest(this, (int)timeSeconds); + groupTitlesReply.AgentData.RequestID = + groupTitlesRequest.AgentData.RequestID; - } - } - break; - case "estatechangecovenantid": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); - OnEstateChangeCovenantRequest(this, newCovenantID); - } - } - break; - case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); + List titles = + m_GroupsModule.GroupTitlesRequest(this, + groupTitlesRequest.AgentData.GroupID); - } - break; - case "simulatormessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "instantmessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length < 5) - break; - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "setregiondebug": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); - bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); - bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); + groupTitlesReply.GroupData = + new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); - } - break; - case "teleporthomeuser": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UUID Prey; + int i = 0; + foreach (GroupTitlesData d in titles) + { + groupTitlesReply.GroupData[i] = + new GroupTitlesReplyPacket.GroupDataBlock(); - UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); + groupTitlesReply.GroupData[i].Title = + Utils.StringToBytes(d.Name); + groupTitlesReply.GroupData[i].RoleID = + d.UUID; + groupTitlesReply.GroupData[i].Selected = + d.Selected; + i++; + } - OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); - } + OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + } + break; + + case PacketType.GroupProfileRequest: + GroupProfileRequestPacket groupProfileRequest = + (GroupProfileRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupProfileRequest.AgentData.SessionID != SessionId || + groupProfileRequest.AgentData.AgentID != AgentId) break; - case "teleporthomeallusers": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); - } + } + #endregion + + if (m_GroupsModule != null) + { + GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + + groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); + groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); + groupProfileReply.AgentData.AgentID = AgentId; + + GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, + groupProfileRequest.GroupData.GroupID); + + groupProfileReply.GroupData.GroupID = d.GroupID; + groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); + groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); + groupProfileReply.GroupData.ShowInList = d.ShowInList; + groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); + groupProfileReply.GroupData.PowersMask = d.PowersMask; + groupProfileReply.GroupData.InsigniaID = d.InsigniaID; + groupProfileReply.GroupData.FounderID = d.FounderID; + groupProfileReply.GroupData.MembershipFee = d.MembershipFee; + groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; + groupProfileReply.GroupData.Money = d.Money; + groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; + groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; + groupProfileReply.GroupData.AllowPublish = d.AllowPublish; + groupProfileReply.GroupData.MaturePublish = d.MaturePublish; + groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + + OutPacket(groupProfileReply, ThrottleOutPacketType.Task); + } + break; + + case PacketType.GroupMembersRequest: + GroupMembersRequestPacket groupMembersRequestPacket = + (GroupMembersRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupMembersRequestPacket.AgentData.SessionID != SessionId || + groupMembersRequestPacket.AgentData.AgentID != AgentId) break; - case "colliders": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + } + #endregion + + if (m_GroupsModule != null) + { + List members = + m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); + + int memberCount = members.Count; + + while (true) + { + int blockCount = members.Count; + if (blockCount > 40) + blockCount = 40; + + GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); + + groupMembersReply.AgentData = + new GroupMembersReplyPacket.AgentDataBlock(); + groupMembersReply.GroupData = + new GroupMembersReplyPacket.GroupDataBlock(); + groupMembersReply.MemberData = + new GroupMembersReplyPacket.MemberDataBlock[ + blockCount]; + + groupMembersReply.AgentData.AgentID = AgentId; + groupMembersReply.GroupData.GroupID = + groupMembersRequestPacket.GroupData.GroupID; + groupMembersReply.GroupData.RequestID = + groupMembersRequestPacket.GroupData.RequestID; + groupMembersReply.GroupData.MemberCount = memberCount; + + for (int i = 0 ; i < blockCount ; i++) { - handlerLandStatRequest(0, 1, 0, "", this); + GroupMembersData m = members[0]; + members.RemoveAt(0); + + groupMembersReply.MemberData[i] = + new GroupMembersReplyPacket.MemberDataBlock(); + groupMembersReply.MemberData[i].AgentID = + m.AgentID; + groupMembersReply.MemberData[i].Contribution = + m.Contribution; + groupMembersReply.MemberData[i].OnlineStatus = + Utils.StringToBytes(m.OnlineStatus); + groupMembersReply.MemberData[i].AgentPowers = + m.AgentPowers; + groupMembersReply.MemberData[i].Title = + Utils.StringToBytes(m.Title); + groupMembersReply.MemberData[i].IsOwner = + m.IsOwner; } + OutPacket(groupMembersReply, ThrottleOutPacketType.Task); + if (members.Count == 0) + break; + } + } + break; + + case PacketType.GroupRoleDataRequest: + GroupRoleDataRequestPacket groupRolesRequest = + (GroupRoleDataRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRolesRequest.AgentData.SessionID != SessionId || + groupRolesRequest.AgentData.AgentID != AgentId) break; - case "scripts": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) - { - handlerLandStatRequest(0, 0, 0, "", this); - } + } + #endregion + + if (m_GroupsModule != null) + { + GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); + + groupRolesReply.AgentData = + new GroupRoleDataReplyPacket.AgentDataBlock(); + + groupRolesReply.AgentData.AgentID = AgentId; + + groupRolesReply.GroupData = + new GroupRoleDataReplyPacket.GroupDataBlock(); + + groupRolesReply.GroupData.GroupID = + groupRolesRequest.GroupData.GroupID; + + groupRolesReply.GroupData.RequestID = + groupRolesRequest.GroupData.RequestID; + + List titles = + m_GroupsModule.GroupRoleDataRequest(this, + groupRolesRequest.GroupData.GroupID); + + groupRolesReply.GroupData.RoleCount = + titles.Count; + + groupRolesReply.RoleData = + new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; + + int i = 0; + foreach (GroupRolesData d in titles) + { + groupRolesReply.RoleData[i] = + new GroupRoleDataReplyPacket.RoleDataBlock(); + + groupRolesReply.RoleData[i].RoleID = + d.RoleID; + groupRolesReply.RoleData[i].Name = + Utils.StringToBytes(d.Name); + groupRolesReply.RoleData[i].Title = + Utils.StringToBytes(d.Title); + groupRolesReply.RoleData[i].Description = + Utils.StringToBytes(d.Description); + groupRolesReply.RoleData[i].Powers = + d.Powers; + groupRolesReply.RoleData[i].Members = + (uint)d.Members; + + i++; + } + + OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + } + break; + + case PacketType.GroupRoleMembersRequest: + GroupRoleMembersRequestPacket groupRoleMembersRequest = + (GroupRoleMembersRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleMembersRequest.AgentData.SessionID != SessionId || + groupRoleMembersRequest.AgentData.AgentID != AgentId) break; - case "terrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length > 0) - { - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") - { - BakeTerrain handlerBakeTerrain = OnBakeTerrain; - if (handlerBakeTerrain != null) - { - handlerBakeTerrain(this); - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") - { - if (messagePacket.ParamList.Length > 1) - { - RequestTerrain handlerRequestTerrain = OnRequestTerrain; - if (handlerRequestTerrain != null) - { - handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") - { - if (messagePacket.ParamList.Length > 1) - { - RequestTerrain handlerUploadTerrain = OnUploadTerrain; - if (handlerUploadTerrain != null) - { - handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } + } + #endregion + + if (m_GroupsModule != null) + { + List mappings = + m_GroupsModule.GroupRoleMembersRequest(this, + groupRoleMembersRequest.GroupData.GroupID); + + int mappingsCount = mappings.Count; + + while (mappings.Count > 0) + { + int pairs = mappings.Count; + if (pairs > 32) + pairs = 32; - } + GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); + groupRoleMembersReply.AgentData = + new GroupRoleMembersReplyPacket.AgentDataBlock(); + groupRoleMembersReply.AgentData.AgentID = + AgentId; + groupRoleMembersReply.AgentData.GroupID = + groupRoleMembersRequest.GroupData.GroupID; + groupRoleMembersReply.AgentData.RequestID = + groupRoleMembersRequest.GroupData.RequestID; + groupRoleMembersReply.AgentData.TotalPairs = + (uint)mappingsCount; - } - break; + groupRoleMembersReply.MemberData = + new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; - case "estatechangeinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + for (int i = 0 ; i < pairs ; i++) { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + GroupRoleMembersData d = mappings[0]; + mappings.RemoveAt(0); - EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo; - if (handlerEstateChangeInfo != null) - { - handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); - } + groupRoleMembersReply.MemberData[i] = + new GroupRoleMembersReplyPacket.MemberDataBlock(); + + groupRoleMembersReply.MemberData[i].RoleID = + d.RoleID; + groupRoleMembersReply.MemberData[i].MemberID = + d.MemberID; } - break; - default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); - break; + OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); + } } - - //int parcelID, uint reportType, uint requestflags, string filter - - //lsrp.RequestData.ParcelLocalID; - //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts - //lsrp.RequestData.RequestFlags; - //lsrp.RequestData.Filter; - break; - case PacketType.RequestRegionInfo: - RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; + case PacketType.CreateGroupRequest: + CreateGroupRequestPacket createGroupRequest = + (CreateGroupRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (mPacket.SessionID != SessionId || - mPacket.AgentID != AgentId) + if (createGroupRequest.AgentData.SessionID != SessionId || + createGroupRequest.AgentData.AgentID != AgentId) break; } #endregion - RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest; - if (handlerRegionInfoRequest != null) + if (m_GroupsModule != null) { - handlerRegionInfoRequest(this); + m_GroupsModule.CreateGroup(this, + Utils.BytesToString(createGroupRequest.GroupData.Name), + Utils.BytesToString(createGroupRequest.GroupData.Charter), + createGroupRequest.GroupData.ShowInList, + createGroupRequest.GroupData.InsigniaID, + createGroupRequest.GroupData.MembershipFee, + createGroupRequest.GroupData.OpenEnrollment, + createGroupRequest.GroupData.AllowPublish, + createGroupRequest.GroupData.MaturePublish); } break; - case PacketType.EstateCovenantRequest: - //EstateCovenantRequestPacket.AgentDataBlock epack = - // ((EstateCovenantRequestPacket)Pack).AgentData; + case PacketType.UpdateGroupInfo: + UpdateGroupInfoPacket updateGroupInfo = + (UpdateGroupInfoPacket)Pack; - EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest; - if (handlerEstateCovenantRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerEstateCovenantRequest(this); + if (updateGroupInfo.AgentData.SessionID != SessionId || + updateGroupInfo.AgentData.AgentID != AgentId) + break; } - break; - #endregion - #region GodPackets + if (m_GroupsModule != null) + { + m_GroupsModule.UpdateGroupInfo(this, + updateGroupInfo.GroupData.GroupID, + Utils.BytesToString(updateGroupInfo.GroupData.Charter), + updateGroupInfo.GroupData.ShowInList, + updateGroupInfo.GroupData.InsigniaID, + updateGroupInfo.GroupData.MembershipFee, + updateGroupInfo.GroupData.OpenEnrollment, + updateGroupInfo.GroupData.AllowPublish, + updateGroupInfo.GroupData.MaturePublish); + } - case PacketType.RequestGodlikePowers: - RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; - RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; - UUID token = rblock.Token; + break; - RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + case PacketType.SetGroupAcceptNotices: + SetGroupAcceptNoticesPacket setGroupAcceptNotices = + (SetGroupAcceptNoticesPacket)Pack; - RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers; + #region Packet Session and User Check + if (m_checkPackets) + { + if (setGroupAcceptNotices.AgentData.SessionID != SessionId || + setGroupAcceptNotices.AgentData.AgentID != AgentId) + break; + } + #endregion - if (handlerReqGodlikePowers != null) + if (m_GroupsModule != null) { - handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); + m_GroupsModule.SetGroupAcceptNotices(this, + setGroupAcceptNotices.Data.GroupID, + setGroupAcceptNotices.Data.AcceptNotices, + setGroupAcceptNotices.NewData.ListInProfile); } break; - case PacketType.GodKickUser: - GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) + case PacketType.GroupTitleUpdate: + GroupTitleUpdatePacket groupTitleUpdate = + (GroupTitleUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - GodKickUser handlerGodKickUser = OnGodKickUser; - if (handlerGodKickUser != null) - { - handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, - gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); - } + if (groupTitleUpdate.AgentData.SessionID != SessionId || + groupTitleUpdate.AgentData.AgentID != AgentId) + break; } - else + #endregion + + if (m_GroupsModule != null) { - SendAgentAlertMessage("Kick request denied", false); + m_GroupsModule.GroupTitleUpdate(this, + groupTitleUpdate.AgentData.GroupID, + groupTitleUpdate.AgentData.TitleRoleID); } - //KickUserPacket kupack = new KickUserPacket(); - //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; - //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; - //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; + break; - //kupack.TargetBlock.TargetIP = (uint)0; - //kupack.TargetBlock.TargetPort = (ushort)0; - //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; - //OutPacket(kupack, ThrottleOutPacketType.Task); - break; + case PacketType.ParcelDeedToGroup: + ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; + if (m_GroupsModule != null) + { + handlerParcelDeedToGroup = OnParcelDeedToGroup; + if (handlerParcelDeedToGroup != null) + { + handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); - #endregion + } + } - #region Economy/Transaction Packets + break; - case PacketType.MoneyBalanceRequest: - MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + + case PacketType.GroupNoticesListRequest: + GroupNoticesListRequestPacket groupNoticesListRequest = + (GroupNoticesListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moneybalancerequestpacket.AgentData.SessionID != SessionId || - moneybalancerequestpacket.AgentData.AgentID != AgentId) + if (groupNoticesListRequest.AgentData.SessionID != SessionId || + groupNoticesListRequest.AgentData.AgentID != AgentId) break; } #endregion - MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest; - - if (handlerMoneyBalanceRequest != null) + if (m_GroupsModule != null) { - handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); - } + GroupNoticeData[] gn = + m_GroupsModule.GroupNoticesListRequest(this, + groupNoticesListRequest.Data.GroupID); - break; - case PacketType.EconomyDataRequest: + GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); + groupNoticesListReply.AgentData = + new GroupNoticesListReplyPacket.AgentDataBlock(); + groupNoticesListReply.AgentData.AgentID = AgentId; + groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; - - EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; - if (handlerEconomoyDataRequest != null) - { - handlerEconomoyDataRequest(AgentId); - } - break; - case PacketType.RequestPayPrice: - RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; - RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice; - if (handlerRequestPayPrice != null) - { - handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); + int i = 0; + foreach (GroupNoticeData g in gn) + { + groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); + groupNoticesListReply.Data[i].NoticeID = + g.NoticeID; + groupNoticesListReply.Data[i].Timestamp = + g.Timestamp; + groupNoticesListReply.Data[i].FromName = + Utils.StringToBytes(g.FromName); + groupNoticesListReply.Data[i].Subject = + Utils.StringToBytes(g.Subject); + groupNoticesListReply.Data[i].HasAttachment = + g.HasAttachment; + groupNoticesListReply.Data[i].AssetType = + g.AssetType; + i++; + } + + OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); } - break; - case PacketType.ObjectSaleInfo: - ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; + break; + case PacketType.GroupNoticeRequest: + GroupNoticeRequestPacket groupNoticeRequest = + (GroupNoticeRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectSaleInfoPacket.AgentData.SessionID != SessionId || - objectSaleInfoPacket.AgentData.AgentID != AgentId) + if (groupNoticeRequest.AgentData.SessionID != SessionId || + groupNoticeRequest.AgentData.AgentID != AgentId) break; } #endregion - ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo; - if (handlerObjectSaleInfo != null) + if (m_GroupsModule != null) { - foreach (ObjectSaleInfoPacket.ObjectDataBlock d - in objectSaleInfoPacket.ObjectData) - { - handlerObjectSaleInfo(this, - objectSaleInfoPacket.AgentData.AgentID, - objectSaleInfoPacket.AgentData.SessionID, - d.LocalID, - d.SaleType, - d.SalePrice); - } + m_GroupsModule.GroupNoticeRequest(this, + groupNoticeRequest.Data.GroupNoticeID); } break; - case PacketType.ObjectBuy: - ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; + case PacketType.GroupRoleUpdate: + GroupRoleUpdatePacket groupRoleUpdate = + (GroupRoleUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectBuyPacket.AgentData.SessionID != SessionId || - objectBuyPacket.AgentData.AgentID != AgentId) + if (groupRoleUpdate.AgentData.SessionID != SessionId || + groupRoleUpdate.AgentData.AgentID != AgentId) break; } #endregion - ObjectBuy handlerObjectBuy = OnObjectBuy; - - if (handlerObjectBuy != null) + if (m_GroupsModule != null) { - foreach (ObjectBuyPacket.ObjectDataBlock d - in objectBuyPacket.ObjectData) + foreach (GroupRoleUpdatePacket.RoleDataBlock d in + groupRoleUpdate.RoleData) { - handlerObjectBuy(this, - objectBuyPacket.AgentData.AgentID, - objectBuyPacket.AgentData.SessionID, - objectBuyPacket.AgentData.GroupID, - objectBuyPacket.AgentData.CategoryID, - d.ObjectLocalID, - d.SaleType, - d.SalePrice); + m_GroupsModule.GroupRoleUpdate(this, + groupRoleUpdate.AgentData.GroupID, + d.RoleID, + Utils.BytesToString(d.Name), + Utils.BytesToString(d.Description), + Utils.BytesToString(d.Title), + d.Powers, + d.UpdateType); } + m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); } break; - #endregion - - #region Script Packets - - case PacketType.GetScriptRunning: - GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; - - GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning; - if (handlerGetScriptRunning != null) - { - handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); - } - break; - - case PacketType.SetScriptRunning: - SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; + case PacketType.GroupRoleChanges: + GroupRoleChangesPacket groupRoleChanges = + (GroupRoleChangesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (setScriptRunning.AgentData.SessionID != SessionId || - setScriptRunning.AgentData.AgentID != AgentId) + if (groupRoleChanges.AgentData.SessionID != SessionId || + groupRoleChanges.AgentData.AgentID != AgentId) break; } #endregion - SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning; - if (handlerSetScriptRunning != null) + if (m_GroupsModule != null) { - handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); + foreach (GroupRoleChangesPacket.RoleChangeBlock d in + groupRoleChanges.RoleChange) + { + m_GroupsModule.GroupRoleChanges(this, + groupRoleChanges.AgentData.GroupID, + d.RoleID, + d.MemberID, + d.Change); + } + m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); } break; - case PacketType.ScriptReset: - ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; + case PacketType.JoinGroupRequest: + JoinGroupRequestPacket joinGroupRequest = + (JoinGroupRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scriptResetPacket.AgentData.SessionID != SessionId || - scriptResetPacket.AgentData.AgentID != AgentId) + if (joinGroupRequest.AgentData.SessionID != SessionId || + joinGroupRequest.AgentData.AgentID != AgentId) break; } #endregion - ScriptReset handlerScriptReset = OnScriptReset; - if (handlerScriptReset != null) + if (m_GroupsModule != null) { - handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); + m_GroupsModule.JoinGroupRequest(this, + joinGroupRequest.GroupData.GroupID); } break; - #endregion - - #region Gesture Managment - - case PacketType.ActivateGestures: - ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; + case PacketType.LeaveGroupRequest: + LeaveGroupRequestPacket leaveGroupRequest = + (LeaveGroupRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGesturePacket.AgentData.SessionID != SessionId || - activateGesturePacket.AgentData.AgentID != AgentId) + if (leaveGroupRequest.AgentData.SessionID != SessionId || + leaveGroupRequest.AgentData.AgentID != AgentId) break; } #endregion - ActivateGesture handlerActivateGesture = OnActivateGesture; - if (handlerActivateGesture != null) + if (m_GroupsModule != null) { - handlerActivateGesture(this, - activateGesturePacket.Data[0].AssetID, - activateGesturePacket.Data[0].ItemID); + m_GroupsModule.LeaveGroupRequest(this, + leaveGroupRequest.GroupData.GroupID); } - else m_log.Error("Null pointer for activateGesture"); - break; - case PacketType.DeactivateGestures: - DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; + case PacketType.EjectGroupMemberRequest: + EjectGroupMemberRequestPacket ejectGroupMemberRequest = + (EjectGroupMemberRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deactivateGesturePacket.AgentData.SessionID != SessionId || - deactivateGesturePacket.AgentData.AgentID != AgentId) + if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || + ejectGroupMemberRequest.AgentData.AgentID != AgentId) break; } #endregion - DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture; - if (handlerDeactivateGesture != null) + if (m_GroupsModule != null) { - handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); + foreach (EjectGroupMemberRequestPacket.EjectDataBlock e + in ejectGroupMemberRequest.EjectData) + { + m_GroupsModule.EjectGroupMemberRequest(this, + ejectGroupMemberRequest.GroupData.GroupID, + e.EjecteeID); + } } break; - case PacketType.ObjectOwner: - ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; + + case PacketType.InviteGroupRequest: + InviteGroupRequestPacket inviteGroupRequest = + (InviteGroupRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectOwnerPacket.AgentData.SessionID != SessionId || - objectOwnerPacket.AgentData.AgentID != AgentId) + if (inviteGroupRequest.AgentData.SessionID != SessionId || + inviteGroupRequest.AgentData.AgentID != AgentId) break; } #endregion - List localIDs = new List(); - - foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) - localIDs.Add(d.ObjectLocalID); - - ObjectOwner handlerObjectOwner = OnObjectOwner; - if (handlerObjectOwner != null) + if (m_GroupsModule != null) { - handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); + foreach (InviteGroupRequestPacket.InviteDataBlock b in + inviteGroupRequest.InviteData) + { + m_GroupsModule.InviteGroupRequest(this, + inviteGroupRequest.GroupData.GroupID, + b.InviteeID, + b.RoleID); + } } break; - #endregion - - - #region unimplemented handlers - - case PacketType.StartPingCheck: - StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; - CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); - pingComplete.PingID.PingID = pingStart.PingID.PingID; - m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); - break; - - case PacketType.CompletePingCheck: - // TODO: Do stats tracking or something with these? - break; - - case PacketType.ViewerStats: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); - break; - - case PacketType.MapItemRequest: - MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; + #endregion + case PacketType.StartLure: + StartLurePacket startLureRequest = (StartLurePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (mirpk.AgentData.SessionID != SessionId || - mirpk.AgentData.AgentID != AgentId) + if (startLureRequest.AgentData.SessionID != SessionId || + startLureRequest.AgentData.AgentID != AgentId) break; } #endregion - //m_log.Debug(mirpk.ToString()); - MapItemRequest handlerMapItemRequest = OnMapItemRequest; - if (handlerMapItemRequest != null) - { - handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, - mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, - mirpk.RequestData.RegionHandle); - - } + handlerStartLure = OnStartLure; + if (handlerStartLure != null) + handlerStartLure(startLureRequest.Info.LureType, + Utils.BytesToString( + startLureRequest.Info.Message), + startLureRequest.TargetData[0].TargetID, + this); break; - case PacketType.TransferAbort: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); - break; - case PacketType.MuteListRequest: - MuteListRequestPacket muteListRequest = - (MuteListRequestPacket)Pack; + case PacketType.TeleportLureRequest: + TeleportLureRequestPacket teleportLureRequest = + (TeleportLureRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (muteListRequest.AgentData.SessionID != SessionId || - muteListRequest.AgentData.AgentID != AgentId) + if (teleportLureRequest.Info.SessionID != SessionId || + teleportLureRequest.Info.AgentID != AgentId) break; } #endregion - MuteListRequest handlerMuteListRequest = OnMuteListRequest; - if (handlerMuteListRequest != null) - { - handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); - } - else - { - SendUseCachedMuteList(); - } - break; - case PacketType.UseCircuitCode: - // Don't display this one, we handle it at a lower level - break; - - case PacketType.AgentHeightWidth: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); + handlerTeleportLureRequest = OnTeleportLureRequest; + if (handlerTeleportLureRequest != null) + handlerTeleportLureRequest( + teleportLureRequest.Info.LureID, + teleportLureRequest.Info.TeleportFlags, + this); break; - case PacketType.InventoryDescendents: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); - - break; - case PacketType.DirPlacesQuery: - DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; - //m_log.Debug(dirPlacesQueryPacket.ToString()); + case PacketType.ClassifiedInfoRequest: + ClassifiedInfoRequestPacket classifiedInfoRequest = + (ClassifiedInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || - dirPlacesQueryPacket.AgentData.AgentID != AgentId) + if (classifiedInfoRequest.AgentData.SessionID != SessionId || + classifiedInfoRequest.AgentData.AgentID != AgentId) break; } #endregion - DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery; - if (handlerDirPlacesQuery != null) - { - handlerDirPlacesQuery(this, - dirPlacesQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.QueryText), - (int)dirPlacesQueryPacket.QueryData.QueryFlags, - (int)dirPlacesQueryPacket.QueryData.Category, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.SimName), - dirPlacesQueryPacket.QueryData.QueryStart); - } + handlerClassifiedInfoRequest = OnClassifiedInfoRequest; + if (handlerClassifiedInfoRequest != null) + handlerClassifiedInfoRequest( + classifiedInfoRequest.Data.ClassifiedID, + this); break; - case PacketType.DirFindQuery: - DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; + + case PacketType.ClassifiedInfoUpdate: + ClassifiedInfoUpdatePacket classifiedInfoUpdate = + (ClassifiedInfoUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirFindQueryPacket.AgentData.SessionID != SessionId || - dirFindQueryPacket.AgentData.AgentID != AgentId) + if (classifiedInfoUpdate.AgentData.SessionID != SessionId || + classifiedInfoUpdate.AgentData.AgentID != AgentId) break; } #endregion - DirFindQuery handlerDirFindQuery = OnDirFindQuery; - if (handlerDirFindQuery != null) - { - handlerDirFindQuery(this, - dirFindQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirFindQueryPacket.QueryData.QueryText), - dirFindQueryPacket.QueryData.QueryFlags, - dirFindQueryPacket.QueryData.QueryStart); - } + handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; + if (handlerClassifiedInfoUpdate != null) + handlerClassifiedInfoUpdate( + classifiedInfoUpdate.Data.ClassifiedID, + classifiedInfoUpdate.Data.Category, + Utils.BytesToString( + classifiedInfoUpdate.Data.Name), + Utils.BytesToString( + classifiedInfoUpdate.Data.Desc), + classifiedInfoUpdate.Data.ParcelID, + classifiedInfoUpdate.Data.ParentEstate, + classifiedInfoUpdate.Data.SnapshotID, + new Vector3( + classifiedInfoUpdate.Data.PosGlobal), + classifiedInfoUpdate.Data.ClassifiedFlags, + classifiedInfoUpdate.Data.PriceForListing, + this); break; - case PacketType.DirLandQuery: - DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; + + case PacketType.ClassifiedDelete: + ClassifiedDeletePacket classifiedDelete = + (ClassifiedDeletePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirLandQueryPacket.AgentData.SessionID != SessionId || - dirLandQueryPacket.AgentData.AgentID != AgentId) + if (classifiedDelete.AgentData.SessionID != SessionId || + classifiedDelete.AgentData.AgentID != AgentId) break; } #endregion - DirLandQuery handlerDirLandQuery = OnDirLandQuery; - if (handlerDirLandQuery != null) - { - handlerDirLandQuery(this, - dirLandQueryPacket.QueryData.QueryID, - dirLandQueryPacket.QueryData.QueryFlags, - dirLandQueryPacket.QueryData.SearchType, - dirLandQueryPacket.QueryData.Price, - dirLandQueryPacket.QueryData.Area, - dirLandQueryPacket.QueryData.QueryStart); - } + handlerClassifiedDelete = OnClassifiedDelete; + if (handlerClassifiedDelete != null) + handlerClassifiedDelete( + classifiedDelete.Data.ClassifiedID, + this); break; - case PacketType.DirPopularQuery: - DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; + + case PacketType.ClassifiedGodDelete: + ClassifiedGodDeletePacket classifiedGodDelete = + (ClassifiedGodDeletePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPopularQueryPacket.AgentData.SessionID != SessionId || - dirPopularQueryPacket.AgentData.AgentID != AgentId) + if (classifiedGodDelete.AgentData.SessionID != SessionId || + classifiedGodDelete.AgentData.AgentID != AgentId) break; } #endregion - DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery; - if (handlerDirPopularQuery != null) - { - handlerDirPopularQuery(this, - dirPopularQueryPacket.QueryData.QueryID, - dirPopularQueryPacket.QueryData.QueryFlags); - } + handlerClassifiedGodDelete = OnClassifiedGodDelete; + if (handlerClassifiedGodDelete != null) + handlerClassifiedGodDelete( + classifiedGodDelete.Data.ClassifiedID, + this); break; - case PacketType.DirClassifiedQuery: - DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; + + case PacketType.EventGodDelete: + EventGodDeletePacket eventGodDelete = + (EventGodDeletePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || - dirClassifiedQueryPacket.AgentData.AgentID != AgentId) + if (eventGodDelete.AgentData.SessionID != SessionId || + eventGodDelete.AgentData.AgentID != AgentId) break; } #endregion - DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery; - if (handlerDirClassifiedQuery != null) - { - handlerDirClassifiedQuery(this, - dirClassifiedQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirClassifiedQueryPacket.QueryData.QueryText), - dirClassifiedQueryPacket.QueryData.QueryFlags, - dirClassifiedQueryPacket.QueryData.Category, - dirClassifiedQueryPacket.QueryData.QueryStart); - } + handlerEventGodDelete = OnEventGodDelete; + if (handlerEventGodDelete != null) + handlerEventGodDelete( + eventGodDelete.EventData.EventID, + eventGodDelete.QueryData.QueryID, + Utils.BytesToString( + eventGodDelete.QueryData.QueryText), + eventGodDelete.QueryData.QueryFlags, + eventGodDelete.QueryData.QueryStart, + this); break; - case PacketType.EventInfoRequest: - EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; + + case PacketType.EventNotificationAddRequest: + EventNotificationAddRequestPacket eventNotificationAdd = + (EventNotificationAddRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventInfoRequestPacket.AgentData.SessionID != SessionId || - eventInfoRequestPacket.AgentData.AgentID != AgentId) + if (eventNotificationAdd.AgentData.SessionID != SessionId || + eventNotificationAdd.AgentData.AgentID != AgentId) break; } #endregion - if (OnEventInfoRequest != null) - { - OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); - } + handlerEventNotificationAddRequest = OnEventNotificationAddRequest; + if (handlerEventNotificationAddRequest != null) + handlerEventNotificationAddRequest( + eventNotificationAdd.EventData.EventID, this); break; - #region Calling Card - - case PacketType.OfferCallingCard: - OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; + case PacketType.EventNotificationRemoveRequest: + EventNotificationRemoveRequestPacket eventNotificationRemove = + (EventNotificationRemoveRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (offerCallingCardPacket.AgentData.SessionID != SessionId || - offerCallingCardPacket.AgentData.AgentID != AgentId) + if (eventNotificationRemove.AgentData.SessionID != SessionId || + eventNotificationRemove.AgentData.AgentID != AgentId) break; } #endregion - if (OnOfferCallingCard != null) - { - OnOfferCallingCard(this, - offerCallingCardPacket.AgentBlock.DestID, - offerCallingCardPacket.AgentBlock.TransactionID); - } + handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; + if (handlerEventNotificationRemoveRequest != null) + handlerEventNotificationRemoveRequest( + eventNotificationRemove.EventData.EventID, this); break; - case PacketType.AcceptCallingCard: - AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; + case PacketType.RetrieveInstantMessages: + RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (acceptCallingCardPacket.AgentData.SessionID != SessionId || - acceptCallingCardPacket.AgentData.AgentID != AgentId) + if (rimpInstantMessagePack.AgentData.SessionID != SessionId || + rimpInstantMessagePack.AgentData.AgentID != AgentId) break; } #endregion - // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should - // contain exactly one entry - if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) - { - OnAcceptCallingCard(this, - acceptCallingCardPacket.TransactionBlock.TransactionID, - acceptCallingCardPacket.FolderData[0].FolderID); - } + handlerRetrieveInstantMessages = OnRetrieveInstantMessages; + if (handlerRetrieveInstantMessages != null) + handlerRetrieveInstantMessages(this); break; - case PacketType.DeclineCallingCard: - DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; + case PacketType.PickDelete: + PickDeletePacket pickDelete = + (PickDeletePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (declineCallingCardPacket.AgentData.SessionID != SessionId || - declineCallingCardPacket.AgentData.AgentID != AgentId) + if (pickDelete.AgentData.SessionID != SessionId || + pickDelete.AgentData.AgentID != AgentId) break; } #endregion - if (OnDeclineCallingCard != null) - { - OnDeclineCallingCard(this, - declineCallingCardPacket.TransactionBlock.TransactionID); - } + handlerPickDelete = OnPickDelete; + if (handlerPickDelete != null) + handlerPickDelete(this, pickDelete.Data.PickID); break; - #endregion - - #region Groups - case PacketType.ActivateGroup: - ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; + case PacketType.PickGodDelete: + PickGodDeletePacket pickGodDelete = + (PickGodDeletePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGroupPacket.AgentData.SessionID != SessionId || - activateGroupPacket.AgentData.AgentID != AgentId) + if (pickGodDelete.AgentData.SessionID != SessionId || + pickGodDelete.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); - m_GroupsModule.SendAgentGroupDataUpdate(this); - } + handlerPickGodDelete = OnPickGodDelete; + if (handlerPickGodDelete != null) + handlerPickGodDelete(this, + pickGodDelete.AgentData.AgentID, + pickGodDelete.Data.PickID, + pickGodDelete.Data.QueryID); break; - - case PacketType.GroupTitlesRequest: - GroupTitlesRequestPacket groupTitlesRequest = - (GroupTitlesRequestPacket)Pack; + case PacketType.PickInfoUpdate: + PickInfoUpdatePacket pickInfoUpdate = + (PickInfoUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupTitlesRequest.AgentData.SessionID != SessionId || - groupTitlesRequest.AgentData.AgentID != AgentId) + if (pickInfoUpdate.AgentData.SessionID != SessionId || + pickInfoUpdate.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - - groupTitlesReply.AgentData = - new GroupTitlesReplyPacket.AgentDataBlock(); - - groupTitlesReply.AgentData.AgentID = AgentId; - groupTitlesReply.AgentData.GroupID = - groupTitlesRequest.AgentData.GroupID; - - groupTitlesReply.AgentData.RequestID = - groupTitlesRequest.AgentData.RequestID; - - List titles = - m_GroupsModule.GroupTitlesRequest(this, - groupTitlesRequest.AgentData.GroupID); - - groupTitlesReply.GroupData = - new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - - int i = 0; - foreach (GroupTitlesData d in titles) - { - groupTitlesReply.GroupData[i] = - new GroupTitlesReplyPacket.GroupDataBlock(); - - groupTitlesReply.GroupData[i].Title = - Utils.StringToBytes(d.Name); - groupTitlesReply.GroupData[i].RoleID = - d.UUID; - groupTitlesReply.GroupData[i].Selected = - d.Selected; - i++; - } - - OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); - } + handlerPickInfoUpdate = OnPickInfoUpdate; + if (handlerPickInfoUpdate != null) + handlerPickInfoUpdate(this, + pickInfoUpdate.Data.PickID, + pickInfoUpdate.Data.CreatorID, + pickInfoUpdate.Data.TopPick, + Utils.BytesToString(pickInfoUpdate.Data.Name), + Utils.BytesToString(pickInfoUpdate.Data.Desc), + pickInfoUpdate.Data.SnapshotID, + pickInfoUpdate.Data.SortOrder, + pickInfoUpdate.Data.Enabled); break; - - case PacketType.GroupProfileRequest: - GroupProfileRequestPacket groupProfileRequest = - (GroupProfileRequestPacket)Pack; + case PacketType.AvatarNotesUpdate: + AvatarNotesUpdatePacket avatarNotesUpdate = + (AvatarNotesUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupProfileRequest.AgentData.SessionID != SessionId || - groupProfileRequest.AgentData.AgentID != AgentId) + if (avatarNotesUpdate.AgentData.SessionID != SessionId || + avatarNotesUpdate.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + handlerAvatarNotesUpdate = OnAvatarNotesUpdate; + if (handlerAvatarNotesUpdate != null) + handlerAvatarNotesUpdate(this, + avatarNotesUpdate.Data.TargetID, + Utils.BytesToString(avatarNotesUpdate.Data.Notes)); + break; - groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); - groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); - groupProfileReply.AgentData.AgentID = AgentId; +// case PacketType.AvatarInterestsUpdate: +// AvatarInterestsUpdatePacket avatarInterestUpdate = +// (AvatarInterestsUpdatePacket)Pack; +// +// break; - GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, - groupProfileRequest.GroupData.GroupID); + case PacketType.PlacesQuery: + PlacesQueryPacket placesQueryPacket = + (PlacesQueryPacket)Pack; - groupProfileReply.GroupData.GroupID = d.GroupID; - groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); - groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); - groupProfileReply.GroupData.ShowInList = d.ShowInList; - groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); - groupProfileReply.GroupData.PowersMask = d.PowersMask; - groupProfileReply.GroupData.InsigniaID = d.InsigniaID; - groupProfileReply.GroupData.FounderID = d.FounderID; - groupProfileReply.GroupData.MembershipFee = d.MembershipFee; - groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; - groupProfileReply.GroupData.Money = d.Money; - groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; - groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; - groupProfileReply.GroupData.AllowPublish = d.AllowPublish; - groupProfileReply.GroupData.MaturePublish = d.MaturePublish; - groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + handlerPlacesQuery = OnPlacesQuery; - OutPacket(groupProfileReply, ThrottleOutPacketType.Task); - } + if (handlerPlacesQuery != null) + handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, + placesQueryPacket.TransactionData.TransactionID, + Utils.BytesToString( + placesQueryPacket.QueryData.QueryText), + placesQueryPacket.QueryData.QueryFlags, + (byte)placesQueryPacket.QueryData.Category, + Utils.BytesToString( + placesQueryPacket.QueryData.SimName), + this); + break; + default: + m_log.Warn("[CLIENT]: unhandled packet " + Pack); break; - case PacketType.GroupMembersRequest: - GroupMembersRequestPacket groupMembersRequestPacket = - (GroupMembersRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupMembersRequestPacket.AgentData.SessionID != SessionId || - groupMembersRequestPacket.AgentData.AgentID != AgentId) - break; - } #endregion + } - if (m_GroupsModule != null) - { - List members = - m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); + PacketPool.Instance.ReturnPacket(Pack); - int memberCount = members.Count; + } - while (true) - { - int blockCount = members.Count; - if (blockCount > 40) - blockCount = 40; + private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); - GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); + shape.PCode = addPacket.ObjectData.PCode; + shape.State = addPacket.ObjectData.State; + shape.PathBegin = addPacket.ObjectData.PathBegin; + shape.PathEnd = addPacket.ObjectData.PathEnd; + shape.PathScaleX = addPacket.ObjectData.PathScaleX; + shape.PathScaleY = addPacket.ObjectData.PathScaleY; + shape.PathShearX = addPacket.ObjectData.PathShearX; + shape.PathShearY = addPacket.ObjectData.PathShearY; + shape.PathSkew = addPacket.ObjectData.PathSkew; + shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; + shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; + shape.Scale = addPacket.ObjectData.Scale; + shape.PathCurve = addPacket.ObjectData.PathCurve; + shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; + shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; + shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; + shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; + shape.PathTaperX = addPacket.ObjectData.PathTaperX; + shape.PathTaperY = addPacket.ObjectData.PathTaperY; + shape.PathTwist = addPacket.ObjectData.PathTwist; + shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); + shape.TextureEntry = ntex.GetBytes(); + //shape.Textures = ntex; + return shape; + } - groupMembersReply.AgentData = - new GroupMembersReplyPacket.AgentDataBlock(); - groupMembersReply.GroupData = - new GroupMembersReplyPacket.GroupDataBlock(); - groupMembersReply.MemberData = - new GroupMembersReplyPacket.MemberDataBlock[ - blockCount]; + /// + /// Send the client an Estate message blue box pop-down with a single OK button + /// + /// + /// + /// + /// + public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) + { + if (!ChildAgentStatus()) + SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); - groupMembersReply.AgentData.AgentID = AgentId; - groupMembersReply.GroupData.GroupID = - groupMembersRequestPacket.GroupData.GroupID; - groupMembersReply.GroupData.RequestID = - groupMembersRequestPacket.GroupData.RequestID; - groupMembersReply.GroupData.MemberCount = memberCount; + //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); + } - for (int i = 0 ; i < blockCount ; i++) - { - GroupMembersData m = members[0]; - members.RemoveAt(0); + public void SendLogoutPacket() + { + // I know this is a bit of a hack, however there are times when you don't + // want to send this, but still need to do the rest of the shutdown process + // this method gets called from the packet server.. which makes it practically + // impossible to do any other way. - groupMembersReply.MemberData[i] = - new GroupMembersReplyPacket.MemberDataBlock(); - groupMembersReply.MemberData[i].AgentID = - m.AgentID; - groupMembersReply.MemberData[i].Contribution = - m.Contribution; - groupMembersReply.MemberData[i].OnlineStatus = - Utils.StringToBytes(m.OnlineStatus); - groupMembersReply.MemberData[i].AgentPowers = - m.AgentPowers; - groupMembersReply.MemberData[i].Title = - Utils.StringToBytes(m.Title); - groupMembersReply.MemberData[i].IsOwner = - m.IsOwner; - } - OutPacket(groupMembersReply, ThrottleOutPacketType.Task); - if (members.Count == 0) - break; - } - } - break; + if (m_SendLogoutPacketWhenClosing) + { + LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); + // TODO: don't create new blocks if recycling an old packet + logReply.AgentData.AgentID = AgentId; + logReply.AgentData.SessionID = SessionId; + logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; + logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); + logReply.InventoryData[0].ItemID = UUID.Zero; - case PacketType.GroupRoleDataRequest: - GroupRoleDataRequestPacket groupRolesRequest = - (GroupRoleDataRequestPacket)Pack; + OutPacket(logReply, ThrottleOutPacketType.Task); + } + } + + public void SendHealth(float health) + { + HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); + healthpacket.HealthData.Health = health; + OutPacket(healthpacket, ThrottleOutPacketType.Task); + } + + public void SendAgentOnline(UUID[] agentIDs) + { + OnlineNotificationPacket onp = new OnlineNotificationPacket(); + OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) + { + OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + onpb[i] = onpbl; + } + onp.AgentBlock = onpb; + onp.Header.Reliable = true; + OutPacket(onp, ThrottleOutPacketType.Task); + } + + public void SendAgentOffline(UUID[] agentIDs) + { + OfflineNotificationPacket offp = new OfflineNotificationPacket(); + OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) + { + OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + offpb[i] = onpbl; + } + offp.AgentBlock = offpb; + offp.Header.Reliable = true; + OutPacket(offp, ThrottleOutPacketType.Task); + } + + public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, + Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) + { + AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); + avatarSitResponse.SitObject.ID = TargetID; + if (CameraAtOffset != Vector3.Zero) + { + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; + } + avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; + avatarSitResponse.SitTransform.AutoPilot = autopilot; + avatarSitResponse.SitTransform.SitPosition = OffsetPos; + avatarSitResponse.SitTransform.SitRotation = SitOrientation; + + OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); + } + + public void SendAdminResponse(UUID Token, uint AdminLevel) + { + GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); + GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); + GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); + + adb.AgentID = AgentId; + adb.SessionID = SessionId; // More security + gdb.GodLevel = (byte)AdminLevel; + gdb.Token = Token; + //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; + respondPacket.GrantData = gdb; + respondPacket.AgentData = adb; + OutPacket(respondPacket, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupRolesRequest.AgentData.SessionID != SessionId || - groupRolesRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendGroupMembership(GroupMembershipData[] GroupMembership) + { + m_groupPowers.Clear(); - if (m_GroupsModule != null) - { - GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); + AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); + AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; - groupRolesReply.AgentData = - new GroupRoleDataReplyPacket.AgentDataBlock(); + AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); + Group.AcceptNotices = GroupMembership[i].AcceptNotices; + Group.Contribution = GroupMembership[i].Contribution; + Group.GroupID = GroupMembership[i].GroupID; + Group.GroupInsigniaID = GroupMembership[i].GroupPicture; + Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); + Group.GroupPowers = GroupMembership[i].GroupPowers; + Groups[i] = Group; + - groupRolesReply.AgentData.AgentID = AgentId; + } + Groupupdate.GroupData = Groups; + Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); + Groupupdate.AgentData.AgentID = AgentId; + OutPacket(Groupupdate, ThrottleOutPacketType.Task); - groupRolesReply.GroupData = - new GroupRoleDataReplyPacket.GroupDataBlock(); + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + eq.GroupMembership(Groupupdate, this.AgentId); + } + } + catch (Exception ex) + { + m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending group membership data via UDP"); + OutPacket(Groupupdate, ThrottleOutPacketType.Task); + } + } - groupRolesReply.GroupData.GroupID = - groupRolesRequest.GroupData.GroupID; - groupRolesReply.GroupData.RequestID = - groupRolesRequest.GroupData.RequestID; + public void SendGroupNameReply(UUID groupLLUID, string GroupName) + { + UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); + UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; + UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); + uidnamebloc.ID = groupLLUID; + uidnamebloc.GroupName = Utils.StringToBytes(GroupName); + uidnameblock[0] = uidnamebloc; + pack.UUIDNameBlock = uidnameblock; + OutPacket(pack, ThrottleOutPacketType.Task); + } - List titles = - m_GroupsModule.GroupRoleDataRequest(this, - groupRolesRequest.GroupData.GroupID); + public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) + { + LandStatReplyPacket lsrp = new LandStatReplyPacket(); + // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); + LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; + //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + // lsrepdb. + lsrp.RequestData.ReportType = reportType; + lsrp.RequestData.RequestFlags = requestFlags; + lsrp.RequestData.TotalObjectCount = resultCount; + for (int i = 0; i < lsrpia.Length; i++) + { + LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + lsrepdb.LocationX = lsrpia[i].LocationX; + lsrepdb.LocationY = lsrpia[i].LocationY; + lsrepdb.LocationZ = lsrpia[i].LocationZ; + lsrepdb.Score = lsrpia[i].Score; + lsrepdb.TaskID = lsrpia[i].TaskID; + lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; + lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); + lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); + lsrepdba[i] = lsrepdb; + } + lsrp.ReportData = lsrepdba; + OutPacket(lsrp, ThrottleOutPacketType.Task); + } - groupRolesReply.GroupData.RoleCount = - titles.Count; + public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) + { + ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); + scriptRunningReply.Script.ObjectID = objectID; + scriptRunningReply.Script.ItemID = itemID; + scriptRunningReply.Script.Running = running; - groupRolesReply.RoleData = - new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; + OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); + } - int i = 0; - foreach (GroupRolesData d in titles) - { - groupRolesReply.RoleData[i] = - new GroupRoleDataReplyPacket.RoleDataBlock(); + public void SendAsset(AssetRequestToClient req) + { + //m_log.Debug("sending asset " + req.RequestAssetID); + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + if (req.AssetRequestSource == 2) + { + Transfer.TransferInfo.Params = new byte[20]; + Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + int assType = req.AssetInf.Type; + Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); + } + else if (req.AssetRequestSource == 3) + { + Transfer.TransferInfo.Params = req.Params; + // Transfer.TransferInfo.Params = new byte[100]; + //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); + } + Transfer.TransferInfo.Size = req.AssetInf.Data.Length; + Transfer.TransferInfo.TransferID = req.TransferRequestID; + Transfer.Header.Zerocoded = true; + OutPacket(Transfer, ThrottleOutPacketType.Asset); - groupRolesReply.RoleData[i].RoleID = - d.RoleID; - groupRolesReply.RoleData[i].Name = - Utils.StringToBytes(d.Name); - groupRolesReply.RoleData[i].Title = - Utils.StringToBytes(d.Title); - groupRolesReply.RoleData[i].Description = - Utils.StringToBytes(d.Description); - groupRolesReply.RoleData[i].Powers = - d.Powers; - groupRolesReply.RoleData[i].Members = - (uint)d.Members; + if (req.NumPackets == 1) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + TransferPacket.TransferData.Data = req.AssetInf.Data; + TransferPacket.TransferData.Status = 1; + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + } + else + { + int processedLength = 0; + int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; + int packetNumber = 0; - i++; - } + while (processedLength < req.AssetInf.Data.Length) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = packetNumber; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; - OutPacket(groupRolesReply, ThrottleOutPacketType.Task); - } - break; + int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); + byte[] chunk = new byte[chunkSize]; + Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); - case PacketType.GroupRoleMembersRequest: - GroupRoleMembersRequestPacket groupRoleMembersRequest = - (GroupRoleMembersRequestPacket)Pack; + TransferPacket.TransferData.Data = chunk; - #region Packet Session and User Check - if (m_checkPackets) + // 0 indicates more packets to come, 1 indicates last packet + if (req.AssetInf.Data.Length - processedLength > maxChunkSize) { - if (groupRoleMembersRequest.AgentData.SessionID != SessionId || - groupRoleMembersRequest.AgentData.AgentID != AgentId) - break; + TransferPacket.TransferData.Status = 0; } - #endregion - - if (m_GroupsModule != null) + else { - List mappings = - m_GroupsModule.GroupRoleMembersRequest(this, - groupRoleMembersRequest.GroupData.GroupID); - - int mappingsCount = mappings.Count; + TransferPacket.TransferData.Status = 1; + } + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - while (mappings.Count > 0) - { - int pairs = mappings.Count; - if (pairs > 32) - pairs = 32; + processedLength += chunkSize; + packetNumber++; + } + } + } - GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); - groupRoleMembersReply.AgentData = - new GroupRoleMembersReplyPacket.AgentDataBlock(); - groupRoleMembersReply.AgentData.AgentID = - AgentId; - groupRoleMembersReply.AgentData.GroupID = - groupRoleMembersRequest.GroupData.GroupID; - groupRoleMembersReply.AgentData.RequestID = - groupRoleMembersRequest.GroupData.RequestID; + public void SendTexture(AssetBase TextureAsset) + { - groupRoleMembersReply.AgentData.TotalPairs = - (uint)mappingsCount; + } - groupRoleMembersReply.MemberData = - new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; + public ClientInfo GetClientInfo() + { + ClientInfo info = m_PacketHandler.GetClientInfo(); - for (int i = 0 ; i < pairs ; i++) - { - GroupRoleMembersData d = mappings[0]; - mappings.RemoveAt(0); + info.userEP = m_userEndPoint; + info.proxyEP = m_proxyEndPoint; + info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); - groupRoleMembersReply.MemberData[i] = - new GroupRoleMembersReplyPacket.MemberDataBlock(); + return info; + } - groupRoleMembersReply.MemberData[i].RoleID = - d.RoleID; - groupRoleMembersReply.MemberData[i].MemberID = - d.MemberID; - } + public EndPoint GetClientEP() + { + return m_userEndPoint; + } - OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); - } - } - break; + public void SetClientInfo(ClientInfo info) + { + m_PacketHandler.SetClientInfo(info); + } - case PacketType.CreateGroupRequest: - CreateGroupRequestPacket createGroupRequest = - (CreateGroupRequestPacket)Pack; + #region Media Parcel Members - #region Packet Session and User Check - if (m_checkPackets) - { - if (createGroupRequest.AgentData.SessionID != SessionId || - createGroupRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) + { + ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); + commandMessagePacket.CommandBlock.Flags = flags; + commandMessagePacket.CommandBlock.Command =(uint) command; + commandMessagePacket.CommandBlock.Time = time; - if (m_GroupsModule != null) - { - m_GroupsModule.CreateGroup(this, - Utils.BytesToString(createGroupRequest.GroupData.Name), - Utils.BytesToString(createGroupRequest.GroupData.Charter), - createGroupRequest.GroupData.ShowInList, - createGroupRequest.GroupData.InsigniaID, - createGroupRequest.GroupData.MembershipFee, - createGroupRequest.GroupData.OpenEnrollment, - createGroupRequest.GroupData.AllowPublish, - createGroupRequest.GroupData.MaturePublish); - } - break; + OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); + } - case PacketType.UpdateGroupInfo: - UpdateGroupInfoPacket updateGroupInfo = - (UpdateGroupInfoPacket)Pack; + public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, + byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, + byte mediaLoop) + { + ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); + updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); + updatePacket.DataBlock.MediaID = mediaTextureID; + updatePacket.DataBlock.MediaAutoScale = autoScale; - #region Packet Session and User Check - if (m_checkPackets) - { - if (updateGroupInfo.AgentData.SessionID != SessionId || - updateGroupInfo.AgentData.AgentID != AgentId) - break; - } - #endregion + updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); + updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); + updatePacket.DataBlockExtended.MediaWidth = mediaWidth; + updatePacket.DataBlockExtended.MediaHeight = mediaHeight; + updatePacket.DataBlockExtended.MediaLoop = mediaLoop; - if (m_GroupsModule != null) - { - m_GroupsModule.UpdateGroupInfo(this, - updateGroupInfo.GroupData.GroupID, - Utils.BytesToString(updateGroupInfo.GroupData.Charter), - updateGroupInfo.GroupData.ShowInList, - updateGroupInfo.GroupData.InsigniaID, - updateGroupInfo.GroupData.MembershipFee, - updateGroupInfo.GroupData.OpenEnrollment, - updateGroupInfo.GroupData.AllowPublish, - updateGroupInfo.GroupData.MaturePublish); - } + OutPacket(updatePacket, ThrottleOutPacketType.Unknown); + } - break; + #endregion - case PacketType.SetGroupAcceptNotices: - SetGroupAcceptNoticesPacket setGroupAcceptNotices = - (SetGroupAcceptNoticesPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (setGroupAcceptNotices.AgentData.SessionID != SessionId || - setGroupAcceptNotices.AgentData.AgentID != AgentId) - break; - } - #endregion + #region Camera - if (m_GroupsModule != null) - { - m_GroupsModule.SetGroupAcceptNotices(this, - setGroupAcceptNotices.Data.GroupID, - setGroupAcceptNotices.Data.AcceptNotices, - setGroupAcceptNotices.NewData.ListInProfile); - } + public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) + { + SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; + uint idx = 0; + foreach (KeyValuePair pair in parameters) + { + SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); + block.Type = pair.Key; + block.Value = pair.Value; - break; + camPropBlock[idx++] = block; + } + packet.CameraProperty = camPropBlock; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.GroupTitleUpdate: - GroupTitleUpdatePacket groupTitleUpdate = - (GroupTitleUpdatePacket)Pack; + public void SendClearFollowCamProperties (UUID objectID) + { + ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + OutPacket(packet, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupTitleUpdate.AgentData.SessionID != SessionId || - groupTitleUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + #endregion - if (m_GroupsModule != null) - { - m_GroupsModule.GroupTitleUpdate(this, - groupTitleUpdate.AgentData.GroupID, - groupTitleUpdate.AgentData.TitleRoleID); - } + public void SendRegionHandle(UUID regionID, ulong handle) { + RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); + reply.ReplyBlock.RegionID = regionID; + reply.ReplyBlock.RegionHandle = handle; + OutPacket(reply, ThrottleOutPacketType.Land); + } - break; + public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) + { + ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); + reply.AgentData.AgentID = m_agentId; + reply.Data.ParcelID = parcelID; + reply.Data.OwnerID = land.OwnerID; + reply.Data.Name = Utils.StringToBytes(land.Name); + reply.Data.Desc = Utils.StringToBytes(land.Description); + reply.Data.ActualArea = land.Area; + reply.Data.BillableArea = land.Area; // TODO: what is this? + + // Bit 0: Mature, bit 7: on sale, other bits: no idea + reply.Data.Flags = (byte)( + ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + + ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + Vector3 pos = land.UserLocation; + if (pos.Equals(Vector3.Zero)) + { + pos = (land.AABBMax + land.AABBMin) * 0.5f; + } + reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; + reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; + reply.Data.GlobalZ = pos.Z; + reply.Data.SimName = Utils.StringToBytes(info.RegionName); + reply.Data.SnapshotID = land.SnapshotID; + reply.Data.Dwell = land.Dwell; + reply.Data.SalePrice = land.SalePrice; + reply.Data.AuctionID = (int)land.AuctionID; - case PacketType.ParcelDeedToGroup: - ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; - if (m_GroupsModule != null) - { - ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; - if (handlerParcelDeedToGroup != null) - { - handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); + OutPacket(reply, ThrottleOutPacketType.Land); + } - } - } + public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) + { + ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); - break; + packet.Data.ObjectName = Utils.StringToBytes(objName); + packet.Data.SimName = Utils.StringToBytes(simName); + packet.Data.SimPosition = pos; + packet.Data.LookAt = lookAt; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.GroupNoticesListRequest: - GroupNoticesListRequestPacket groupNoticesListRequest = - (GroupNoticesListRequestPacket)Pack; + public void SetClientOption(string option, string value) + { + switch (option) + { + case "ReliableIsImportant": + bool val; - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupNoticesListRequest.AgentData.SessionID != SessionId || - groupNoticesListRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + if (bool.TryParse(value, out val)) + m_PacketHandler.ReliableIsImportant = val; + break; + default: + break; + } + } - if (m_GroupsModule != null) - { - GroupNoticeData[] gn = - m_GroupsModule.GroupNoticesListRequest(this, - groupNoticesListRequest.Data.GroupID); + public string GetClientOption(string option) + { + switch (option) + { + case "ReliableIsImportant": + return m_PacketHandler.ReliableIsImportant.ToString(); - GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); - groupNoticesListReply.AgentData = - new GroupNoticesListReplyPacket.AgentDataBlock(); - groupNoticesListReply.AgentData.AgentID = AgentId; - groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; + default: + break; + } + return string.Empty; + } - groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; + public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) + { + DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); - int i = 0; - foreach (GroupNoticeData g in gn) - { - groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); - groupNoticesListReply.Data[i].NoticeID = - g.NoticeID; - groupNoticesListReply.Data[i].Timestamp = - g.Timestamp; - groupNoticesListReply.Data[i].FromName = - Utils.StringToBytes(g.FromName); - groupNoticesListReply.Data[i].Subject = - Utils.StringToBytes(g.Subject); - groupNoticesListReply.Data[i].HasAttachment = - g.HasAttachment; - groupNoticesListReply.Data[i].AssetType = - g.AssetType; - i++; - } + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); - OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); - } + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); - break; - case PacketType.GroupNoticeRequest: - GroupNoticeRequestPacket groupNoticeRequest = - (GroupNoticeRequestPacket)Pack; + packet.QueryReplies = + new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupNoticeRequest.AgentData.SessionID != SessionId || - groupNoticeRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ + data.Length]; - if (m_GroupsModule != null) - { - m_GroupsModule.GroupNoticeRequest(this, - groupNoticeRequest.Data.GroupNoticeID); - } - break; + packet.AgentData.AgentID = AgentId; - case PacketType.GroupRoleUpdate: - GroupRoleUpdatePacket groupRoleUpdate = - (GroupRoleUpdatePacket)Pack; + packet.QueryData[0].QueryID = queryID; - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupRoleUpdate.AgentData.SessionID != SessionId || - groupRoleUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + int i = 0; + foreach (DirPlacesReplyData d in data) + { + packet.QueryReplies[i] = + new DirPlacesReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].Dwell = d.dwell; + packet.StatusData[i].Status = d.Status; + i++; + } - if (m_GroupsModule != null) - { - foreach (GroupRoleUpdatePacket.RoleDataBlock d in - groupRoleUpdate.RoleData) - { - m_GroupsModule.GroupRoleUpdate(this, - groupRoleUpdate.AgentData.GroupID, - d.RoleID, - Utils.BytesToString(d.Name), - Utils.BytesToString(d.Description), - Utils.BytesToString(d.Title), - d.Powers, - d.UpdateType); - } - m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); - } - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.GroupRoleChanges: - GroupRoleChangesPacket groupRoleChanges = - (GroupRoleChangesPacket)Pack; + public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) + { + DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupRoleChanges.AgentData.SessionID != SessionId || - groupRoleChanges.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - if (m_GroupsModule != null) - { - foreach (GroupRoleChangesPacket.RoleChangeBlock d in - groupRoleChanges.RoleChange) - { - m_GroupsModule.GroupRoleChanges(this, - groupRoleChanges.AgentData.GroupID, - d.RoleID, - d.MemberID, - d.Change); - } - m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); - } - break; + packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - case PacketType.JoinGroupRequest: - JoinGroupRequestPacket joinGroupRequest = - (JoinGroupRequestPacket)Pack; + packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ + data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (joinGroupRequest.AgentData.SessionID != SessionId || - joinGroupRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + int i = 0; + foreach (DirPeopleReplyData d in data) + { + packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].AgentID = d.agentID; + packet.QueryReplies[i].FirstName = + Utils.StringToBytes(d.firstName); + packet.QueryReplies[i].LastName = + Utils.StringToBytes(d.lastName); + packet.QueryReplies[i].Group = + Utils.StringToBytes(d.group); + packet.QueryReplies[i].Online = d.online; + packet.QueryReplies[i].Reputation = d.reputation; + i++; + } - if (m_GroupsModule != null) - { - m_GroupsModule.JoinGroupRequest(this, - joinGroupRequest.GroupData.GroupID); - } - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.LeaveGroupRequest: - LeaveGroupRequestPacket leaveGroupRequest = - (LeaveGroupRequestPacket)Pack; + public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) + { + DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (leaveGroupRequest.AgentData.SessionID != SessionId || - leaveGroupRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - if (m_GroupsModule != null) - { - m_GroupsModule.LeaveGroupRequest(this, - leaveGroupRequest.GroupData.GroupID); - } - break; + packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - case PacketType.EjectGroupMemberRequest: - EjectGroupMemberRequestPacket ejectGroupMemberRequest = - (EjectGroupMemberRequestPacket)Pack; + packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ + data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || - ejectGroupMemberRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ + data.Length]; - if (m_GroupsModule != null) - { - foreach (EjectGroupMemberRequestPacket.EjectDataBlock e - in ejectGroupMemberRequest.EjectData) - { - m_GroupsModule.EjectGroupMemberRequest(this, - ejectGroupMemberRequest.GroupData.GroupID, - e.EjecteeID); - } - } - break; + int i = 0; + foreach (DirEventsReplyData d in data) + { + packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].OwnerID = d.ownerID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].EventID = d.eventID; + packet.QueryReplies[i].Date = + Utils.StringToBytes(d.date); + packet.QueryReplies[i].UnixTime = d.unixTime; + packet.QueryReplies[i].EventFlags = d.eventFlags; + packet.StatusData[i].Status = d.Status; + i++; + } - case PacketType.InviteGroupRequest: - InviteGroupRequestPacket inviteGroupRequest = - (InviteGroupRequestPacket)Pack; + OutPacket(packet, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (inviteGroupRequest.AgentData.SessionID != SessionId || - inviteGroupRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) + { + DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); - if (m_GroupsModule != null) - { - foreach (InviteGroupRequestPacket.InviteDataBlock b in - inviteGroupRequest.InviteData) - { - m_GroupsModule.InviteGroupRequest(this, - inviteGroupRequest.GroupData.GroupID, - b.InviteeID, - b.RoleID); - } - } - break; + packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ + data.Length]; + + int i = 0; + foreach (DirGroupsReplyData d in data) + { + packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].GroupID = d.groupID; + packet.QueryReplies[i].GroupName = + Utils.StringToBytes(d.groupName); + packet.QueryReplies[i].Members = d.members; + packet.QueryReplies[i].SearchOrder = d.searchOrder; + i++; + } + + OutPacket(packet, ThrottleOutPacketType.Task); + } - #endregion - case PacketType.StartLure: - StartLurePacket startLureRequest = (StartLurePacket)Pack; + public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) + { + DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (startLureRequest.AgentData.SessionID != SessionId || - startLureRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - StartLure handlerStartLure = OnStartLure; - if (handlerStartLure != null) - handlerStartLure(startLureRequest.Info.LureType, - Utils.BytesToString( - startLureRequest.Info.Message), - startLureRequest.TargetData[0].TargetID, - this); - break; + packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - case PacketType.TeleportLureRequest: - TeleportLureRequestPacket teleportLureRequest = - (TeleportLureRequestPacket)Pack; + packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ + data.Length]; + packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ + data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (teleportLureRequest.Info.SessionID != SessionId || - teleportLureRequest.Info.AgentID != AgentId) - break; - } - #endregion + int i = 0; + foreach (DirClassifiedReplyData d in data) + { + packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ClassifiedID = d.classifiedID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; + packet.QueryReplies[i].CreationDate = d.creationDate; + packet.QueryReplies[i].ExpirationDate = d.expirationDate; + packet.QueryReplies[i].PriceForListing = d.price; + packet.StatusData[i].Status = d.Status; + i++; + } - TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest; - if (handlerTeleportLureRequest != null) - handlerTeleportLureRequest( - teleportLureRequest.Info.LureID, - teleportLureRequest.Info.TeleportFlags, - this); - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.ClassifiedInfoRequest: - ClassifiedInfoRequestPacket classifiedInfoRequest = - (ClassifiedInfoRequestPacket)Pack; + public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) + { + DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (classifiedInfoRequest.AgentData.SessionID != SessionId || - classifiedInfoRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest; - if (handlerClassifiedInfoRequest != null) - handlerClassifiedInfoRequest( - classifiedInfoRequest.Data.ClassifiedID, - this); - break; + packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - case PacketType.ClassifiedInfoUpdate: - ClassifiedInfoUpdatePacket classifiedInfoUpdate = - (ClassifiedInfoUpdatePacket)Pack; + packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ + data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (classifiedInfoUpdate.AgentData.SessionID != SessionId || - classifiedInfoUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + int i = 0; + foreach (DirLandReplyData d in data) + { + packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].SalePrice = d.salePrice; + packet.QueryReplies[i].ActualArea = d.actualArea; + i++; + } - ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; - if (handlerClassifiedInfoUpdate != null) - handlerClassifiedInfoUpdate( - classifiedInfoUpdate.Data.ClassifiedID, - classifiedInfoUpdate.Data.Category, - Utils.BytesToString( - classifiedInfoUpdate.Data.Name), - Utils.BytesToString( - classifiedInfoUpdate.Data.Desc), - classifiedInfoUpdate.Data.ParcelID, - classifiedInfoUpdate.Data.ParentEstate, - classifiedInfoUpdate.Data.SnapshotID, - new Vector3( - classifiedInfoUpdate.Data.PosGlobal), - classifiedInfoUpdate.Data.ClassifiedFlags, - classifiedInfoUpdate.Data.PriceForListing, - this); - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.ClassifiedDelete: - ClassifiedDeletePacket classifiedDelete = - (ClassifiedDeletePacket)Pack; + public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) + { + DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (classifiedDelete.AgentData.SessionID != SessionId || - classifiedDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete; - if (handlerClassifiedDelete != null) - handlerClassifiedDelete( - classifiedDelete.Data.ClassifiedID, - this); - break; + packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - case PacketType.ClassifiedGodDelete: - ClassifiedGodDeletePacket classifiedGodDelete = - (ClassifiedGodDeletePacket)Pack; + packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ + data.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (classifiedGodDelete.AgentData.SessionID != SessionId || - classifiedGodDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + int i = 0; + foreach (DirPopularReplyData d in data) + { + packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Dwell = d.dwell; + i++; + } - ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; - if (handlerClassifiedGodDelete != null) - handlerClassifiedGodDelete( - classifiedGodDelete.Data.ClassifiedID, - this); - break; + OutPacket(packet, ThrottleOutPacketType.Task); + } - case PacketType.EventGodDelete: - EventGodDeletePacket eventGodDelete = - (EventGodDeletePacket)Pack; + public void SendEventInfoReply(EventData data) + { + EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); - #region Packet Session and User Check - if (m_checkPackets) - { - if (eventGodDelete.AgentData.SessionID != SessionId || - eventGodDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - EventGodDelete handlerEventGodDelete = OnEventGodDelete; - if (handlerEventGodDelete != null) - handlerEventGodDelete( - eventGodDelete.EventData.EventID, - eventGodDelete.QueryData.QueryID, - Utils.BytesToString( - eventGodDelete.QueryData.QueryText), - eventGodDelete.QueryData.QueryFlags, - eventGodDelete.QueryData.QueryStart, - this); - break; + packet.EventData = new EventInfoReplyPacket.EventDataBlock(); + packet.EventData.EventID = data.eventID; + packet.EventData.Creator = Utils.StringToBytes(data.creator); + packet.EventData.Name = Utils.StringToBytes(data.name); + packet.EventData.Category = Utils.StringToBytes(data.category); + packet.EventData.Desc = Utils.StringToBytes(data.description); + packet.EventData.Date = Utils.StringToBytes(data.date); + packet.EventData.DateUTC = data.dateUTC; + packet.EventData.Duration = data.duration; + packet.EventData.Cover = data.cover; + packet.EventData.Amount = data.amount; + packet.EventData.SimName = Utils.StringToBytes(data.simName); + packet.EventData.GlobalPos = new Vector3d(data.globalPos); + packet.EventData.EventFlags = data.eventFlags; - case PacketType.EventNotificationAddRequest: - EventNotificationAddRequestPacket eventNotificationAdd = - (EventNotificationAddRequestPacket)Pack; + OutPacket(packet, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (eventNotificationAdd.AgentData.SessionID != SessionId || - eventNotificationAdd.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) + { + MapItemReplyPacket mirplk = new MapItemReplyPacket(); + mirplk.AgentData.AgentID = AgentId; + mirplk.RequestData.ItemType = mapitemtype; + mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; + for (int i = 0; i < replies.Length; i++) + { + MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); + mrdata.X = replies[i].x; + mrdata.Y = replies[i].y; + mrdata.ID = replies[i].id; + mrdata.Extra = replies[i].Extra; + mrdata.Extra2 = replies[i].Extra2; + mrdata.Name = Utils.StringToBytes(replies[i].name); + mirplk.Data[i] = mrdata; + } + //m_log.Debug(mirplk.ToString()); + OutPacket(mirplk, ThrottleOutPacketType.Task); - EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest; - if (handlerEventNotificationAddRequest != null) - handlerEventNotificationAddRequest( - eventNotificationAdd.EventData.EventID, this); - break; + } - case PacketType.EventNotificationRemoveRequest: - EventNotificationRemoveRequestPacket eventNotificationRemove = - (EventNotificationRemoveRequestPacket)Pack; + public void SendOfferCallingCard(UUID srcID, UUID transactionID) + { + // a bit special, as this uses AgentID to store the source instead + // of the destination. The destination (the receiver) goes into destID + OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); + p.AgentData.AgentID = srcID; + p.AgentData.SessionID = UUID.Zero; + p.AgentBlock.DestID = AgentId; + p.AgentBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (eventNotificationRemove.AgentData.SessionID != SessionId || - eventNotificationRemove.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendAcceptCallingCard(UUID transactionID) + { + AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; + p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); + p.FolderData[0].FolderID = UUID.Zero; + OutPacket(p, ThrottleOutPacketType.Task); + } - EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; - if (handlerEventNotificationRemoveRequest != null) - handlerEventNotificationRemoveRequest( - eventNotificationRemove.EventData.EventID, this); - break; + public void SendDeclineCallingCard(UUID transactionID) + { + DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.TransactionBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); + } - case PacketType.RetrieveInstantMessages: - RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; + public void SendTerminateFriend(UUID exFriendID) + { + TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = SessionId; + p.ExBlock.OtherID = exFriendID; + OutPacket(p, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (rimpInstantMessagePack.AgentData.SessionID != SessionId || - rimpInstantMessagePack.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) + { + AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); - RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages; - if (handlerRetrieveInstantMessages != null) - handlerRetrieveInstantMessages(this); - break; + p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; + p.AgentData.AvatarID = avatarID; - case PacketType.PickDelete: - PickDeletePacket pickDelete = - (PickDeletePacket)Pack; + p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; + int i = 0; + foreach (GroupMembershipData m in data) + { + p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); + p.GroupData[i].GroupPowers = m.GroupPowers; + p.GroupData[i].AcceptNotices = m.AcceptNotices; + p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); + p.GroupData[i].GroupID = m.GroupID; + p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); + p.GroupData[i].GroupInsigniaID = m.GroupPicture; + i++; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (pickDelete.AgentData.SessionID != SessionId || - pickDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); + p.NewGroupData.ListInProfile = true; - PickDelete handlerPickDelete = OnPickDelete; - if (handlerPickDelete != null) - handlerPickDelete(this, pickDelete.Data.PickID); - break; - case PacketType.PickGodDelete: - PickGodDeletePacket pickGodDelete = - (PickGodDeletePacket)Pack; + OutPacket(p, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (pickGodDelete.AgentData.SessionID != SessionId || - pickGodDelete.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendJoinGroupReply(UUID groupID, bool success) + { + JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); - PickGodDelete handlerPickGodDelete = OnPickGodDelete; - if (handlerPickGodDelete != null) - handlerPickGodDelete(this, - pickGodDelete.AgentData.AgentID, - pickGodDelete.Data.PickID, - pickGodDelete.Data.QueryID); - break; - case PacketType.PickInfoUpdate: - PickInfoUpdatePacket pickInfoUpdate = - (PickInfoUpdatePacket)Pack; + p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - #region Packet Session and User Check - if (m_checkPackets) - { - if (pickInfoUpdate.AgentData.SessionID != SessionId || - pickInfoUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; - PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate; - if (handlerPickInfoUpdate != null) - handlerPickInfoUpdate(this, - pickInfoUpdate.Data.PickID, - pickInfoUpdate.Data.CreatorID, - pickInfoUpdate.Data.TopPick, - Utils.BytesToString(pickInfoUpdate.Data.Name), - Utils.BytesToString(pickInfoUpdate.Data.Desc), - pickInfoUpdate.Data.SnapshotID, - pickInfoUpdate.Data.SortOrder, - pickInfoUpdate.Data.Enabled); - break; - case PacketType.AvatarNotesUpdate: - AvatarNotesUpdatePacket avatarNotesUpdate = - (AvatarNotesUpdatePacket)Pack; + OutPacket(p, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avatarNotesUpdate.AgentData.SessionID != SessionId || - avatarNotesUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) + { + EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); - AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate; - if (handlerAvatarNotesUpdate != null) - handlerAvatarNotesUpdate(this, - avatarNotesUpdate.Data.TargetID, - Utils.BytesToString(avatarNotesUpdate.Data.Notes)); - break; + p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = agentID; -// case PacketType.AvatarInterestsUpdate: -// AvatarInterestsUpdatePacket avatarInterestUpdate = -// (AvatarInterestsUpdatePacket)Pack; -// -// break; + p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; - case PacketType.PlacesQuery: - PlacesQueryPacket placesQueryPacket = - (PlacesQueryPacket)Pack; + p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); + p.EjectData.Success = success; - PlacesQuery handlerPlacesQuery = OnPlacesQuery; + OutPacket(p, ThrottleOutPacketType.Task); + } - if (handlerPlacesQuery != null) - handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, - placesQueryPacket.TransactionData.TransactionID, - Utils.BytesToString( - placesQueryPacket.QueryData.QueryText), - placesQueryPacket.QueryData.QueryFlags, - (byte)placesQueryPacket.QueryData.Category, - Utils.BytesToString( - placesQueryPacket.QueryData.SimName), - this); - break; - default: - m_log.Warn("[CLIENT]: unhandled packet " + Pack); - break; + public void SendLeaveGroupReply(UUID groupID, bool success) + { + LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); - #endregion - } + p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - PacketPool.Instance.ReturnPacket(Pack); + p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; + OutPacket(p, ThrottleOutPacketType.Task); } - private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) + public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) { - PrimitiveBaseShape shape = new PrimitiveBaseShape(); + if (classifiedID.Length != name.Length) + return; - shape.PCode = addPacket.ObjectData.PCode; - shape.State = addPacket.ObjectData.State; - shape.PathBegin = addPacket.ObjectData.PathBegin; - shape.PathEnd = addPacket.ObjectData.PathEnd; - shape.PathScaleX = addPacket.ObjectData.PathScaleX; - shape.PathScaleY = addPacket.ObjectData.PathScaleY; - shape.PathShearX = addPacket.ObjectData.PathShearX; - shape.PathShearY = addPacket.ObjectData.PathShearY; - shape.PathSkew = addPacket.ObjectData.PathSkew; - shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; - shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; - shape.Scale = addPacket.ObjectData.Scale; - shape.PathCurve = addPacket.ObjectData.PathCurve; - shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; - shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; - shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; - shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; - shape.PathTaperX = addPacket.ObjectData.PathTaperX; - shape.PathTaperY = addPacket.ObjectData.PathTaperY; - shape.PathTwist = addPacket.ObjectData.PathTwist; - shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); - shape.TextureEntry = ntex.GetBytes(); - //shape.Textures = ntex; - return shape; + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); + + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; + + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; + int i; + for (i = 0 ; i < classifiedID.Length ; i++) + { + ac.Data[i].ClassifiedID = classifiedID[i]; + ac.Data[i].Name = Utils.StringToBytes(name[i]); + } + + OutPacket(ac, ThrottleOutPacketType.Task); } - - public ClientInfo GetClientInfo() + + public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) { - ClientInfo info = m_udpClient.GetClientInfo(); + ClassifiedInfoReplyPacket cr = + (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ClassifiedInfoReply); - info.userEP = m_userEndPoint; - info.proxyEP = null; - info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); + cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); + cr.AgentData.AgentID = AgentId; - return info; + cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); + cr.Data.ClassifiedID = classifiedID; + cr.Data.CreatorID = creatorID; + cr.Data.CreationDate = creationDate; + cr.Data.ExpirationDate = expirationDate; + cr.Data.Category = category; + cr.Data.Name = Utils.StringToBytes(name); + cr.Data.Desc = Utils.StringToBytes(description); + cr.Data.ParcelID = parcelID; + cr.Data.ParentEstate = parentEstate; + cr.Data.SnapshotID = snapshotID; + cr.Data.SimName = Utils.StringToBytes(simName); + cr.Data.PosGlobal = new Vector3d(globalPos); + cr.Data.ParcelName = Utils.StringToBytes(parcelName); + cr.Data.ClassifiedFlags = classifiedFlags; + cr.Data.PriceForListing = price; + + OutPacket(cr, ThrottleOutPacketType.Task); } - public void SetClientInfo(ClientInfo info) + public void SendAgentDropGroup(UUID groupID) { - m_udpClient.SetClientInfo(info); + AgentDropGroupPacket dg = + (AgentDropGroupPacket)PacketPool.Instance.GetPacket( + PacketType.AgentDropGroup); + + dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); + dg.AgentData.AgentID = AgentId; + dg.AgentData.GroupID = groupID; + + OutPacket(dg, ThrottleOutPacketType.Task); } - public EndPoint GetClientEP() + public void SendAvatarNotesReply(UUID targetID, string text) { - return m_userEndPoint; - } + AvatarNotesReplyPacket an = + (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarNotesReply); - #region Media Parcel Members + an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); + an.AgentData.AgentID = AgentId; - public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) - { - ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); - commandMessagePacket.CommandBlock.Flags = flags; - commandMessagePacket.CommandBlock.Command =(uint) command; - commandMessagePacket.CommandBlock.Time = time; + an.Data = new AvatarNotesReplyPacket.DataBlock(); + an.Data.TargetID = targetID; + an.Data.Notes = Utils.StringToBytes(text); - OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); + OutPacket(an, ThrottleOutPacketType.Task); } - public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, - byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, - byte mediaLoop) + public void SendAvatarPicksReply(UUID targetID, Dictionary picks) { - ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); - updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); - updatePacket.DataBlock.MediaID = mediaTextureID; - updatePacket.DataBlock.MediaAutoScale = autoScale; + AvatarPicksReplyPacket ap = + (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarPicksReply); - updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); - updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); - updatePacket.DataBlockExtended.MediaWidth = mediaWidth; - updatePacket.DataBlockExtended.MediaHeight = mediaHeight; - updatePacket.DataBlockExtended.MediaLoop = mediaLoop; + ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); + ap.AgentData.AgentID = AgentId; + ap.AgentData.TargetID = targetID; - OutPacket(updatePacket, ThrottleOutPacketType.Unknown); - } + ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; - #endregion + int i = 0; + foreach (KeyValuePair pick in picks) + { + ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); + ap.Data[i].PickID = pick.Key; + ap.Data[i].PickName = Utils.StringToBytes(pick.Value); + i++; + } - #region Camera + OutPacket(ap, ThrottleOutPacketType.Task); + } - public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) + public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) { - SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; - uint idx = 0; - foreach (KeyValuePair pair in parameters) - { - SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); - block.Type = pair.Key; - block.Value = pair.Value; + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); - camPropBlock[idx++] = block; + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; + + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; + + int i = 0; + foreach (KeyValuePair classified in classifieds) + { + ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); + ac.Data[i].ClassifiedID = classified.Key; + ac.Data[i].Name = Utils.StringToBytes(classified.Value); + i++; } - packet.CameraProperty = camPropBlock; - OutPacket(packet, ThrottleOutPacketType.Task); + + OutPacket(ac, ThrottleOutPacketType.Task); } - public void SendClearFollowCamProperties (UUID objectID) + public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) { - ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - OutPacket(packet, ThrottleOutPacketType.Task); - } + ParcelDwellReplyPacket pd = + (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ParcelDwellReply); - #endregion + pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); + pd.AgentData.AgentID = AgentId; - public void SetClientOption(string option, string value) - { - switch (option) - { - default: - break; - } + pd.Data = new ParcelDwellReplyPacket.DataBlock(); + pd.Data.LocalID = localID; + pd.Data.ParcelID = parcelID; + pd.Data.Dwell = dwell; + + OutPacket(pd, ThrottleOutPacketType.Land); } - public string GetClientOption(string option) + public void SendUserInfoReply(bool imViaEmail, bool visible, string email) { - switch (option) - { - default: - break; - } - return string.Empty; + UserInfoReplyPacket ur = + (UserInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.UserInfoReply); + + string Visible = "hidden"; + if (visible) + Visible = "default"; + + ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); + ur.AgentData.AgentID = AgentId; + + ur.UserData = new UserInfoReplyPacket.UserDataBlock(); + ur.UserData.IMViaEMail = imViaEmail; + ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); + ur.UserData.EMail = Utils.StringToBytes(email); + + OutPacket(ur, ThrottleOutPacketType.Task); } public void KillEndDone() { - m_udpClient.Shutdown(); + KillPacket kp = new KillPacket(); + OutPacket(kp, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); } #region IClientCore @@ -10273,6 +10767,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + protected virtual void RegisterInterfaces() + { + RegisterInterface(this); + RegisterInterface(this); + RegisterInterface(this); + } + public bool TryGet(out T iface) { if (m_clientInterfaces.ContainsKey(typeof(T))) @@ -10320,14 +10821,78 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void SendCreateGroupReply(UUID groupID, bool success, string message) + { + CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); + + createGroupReply.AgentData = + new CreateGroupReplyPacket.AgentDataBlock(); + createGroupReply.ReplyData = + new CreateGroupReplyPacket.ReplyDataBlock(); + + createGroupReply.AgentData.AgentID = AgentId; + createGroupReply.ReplyData.GroupID = groupID; + + createGroupReply.ReplyData.Success = success; + createGroupReply.ReplyData.Message = Utils.StringToBytes(message); + OutPacket(createGroupReply, ThrottleOutPacketType.Task); + } + + public void SendUseCachedMuteList() + { + UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); + + useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); + useCachedMuteList.AgentData.AgentID = AgentId; + + OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); + } + + public void SendMuteListUpdate(string filename) + { + MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); + + muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); + muteListUpdate.MuteData.AgentID = AgentId; + muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); + + OutPacket(muteListUpdate, ThrottleOutPacketType.Task); + } + + public void SendPickInfoReply(UUID pickID,UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) + { + PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); + + pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); + pickInfoReply.AgentData.AgentID = AgentId; + + pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); + pickInfoReply.Data.PickID = pickID; + pickInfoReply.Data.CreatorID = creatorID; + pickInfoReply.Data.TopPick = topPick; + pickInfoReply.Data.ParcelID = parcelID; + pickInfoReply.Data.Name = Utils.StringToBytes(name); + pickInfoReply.Data.Desc = Utils.StringToBytes(desc); + pickInfoReply.Data.SnapshotID = snapshotID; + pickInfoReply.Data.User = Utils.StringToBytes(user); + pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); + pickInfoReply.Data.SimName = Utils.StringToBytes(simName); + pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); + pickInfoReply.Data.SortOrder = sortOrder; + pickInfoReply.Data.Enabled = enabled; + + OutPacket(pickInfoReply, ThrottleOutPacketType.Task); + } + public string Report() { - return m_udpClient.GetStats(); + LLPacketHandler handler = (LLPacketHandler) m_PacketHandler; + return handler.PacketQueue.GetStats(); } public string XReport(string uptime, string version) { - return String.Empty; + return ""; } public void MakeAssetRequest(TransferRequestPacket transferRequest) @@ -10416,6 +10981,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return numPackets; } + #region IClientIPEndpoint Members public IPAddress EndPoint -- cgit v1.1 From d33b6fef2b8d3898ab6411df3267d42d18e56d9b Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 7 Oct 2009 04:37:12 +0100 Subject: replace LLClientView with proper version --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 12814 +++++++++---------- 1 file changed, 6124 insertions(+), 6690 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 0052729..84e705a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -58,526 +58,180 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector { + // LLClientView Only + public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); + + /// Used to adjust Sun Orbit values so Linden based viewers properly position sun + private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients - /* static variables */ - public static SynchronizeClientHandler SynchronizeClient; - /* private variables */ + private readonly LLUDPServer m_udpServer; + private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; - private readonly UUID m_secureSessionId = UUID.Zero; - - private int m_debugPacketLevel; + private readonly UUID m_secureSessionId; + private readonly UUID m_agentId; + private readonly uint m_circuitCode; + private readonly byte[] m_channelVersion = Utils.EmptyBytes; + private readonly Dictionary m_defaultAnimations = new Dictionary(); + private readonly IGroupsModule m_GroupsModule; - //private readonly IAssetCache m_assetCache; private int m_cachedTextureSerial; - private Timer m_clientPingTimer; - private Timer m_avatarTerseUpdateTimer; private List m_avatarTerseUpdates = new List(); - private Timer m_primTerseUpdateTimer; private List m_primTerseUpdates = new List(); private Timer m_primFullUpdateTimer; - private List m_primFullUpdates = - new List(); - - private bool m_clientBlocked; - - private int m_probesWithNoIngressPackets; - - private readonly UUID m_agentId; - private readonly uint m_circuitCode; + private List m_primFullUpdates = new List(); private int m_moneyBalance; - private readonly ILLPacketHandler m_PacketHandler; - private int m_animationSequenceNumber = 1; - - private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL - - private readonly Dictionary m_defaultAnimations = new Dictionary(); - private bool m_SendLogoutPacketWhenClosing = true; - - private int m_inPacketsChecked; - - // Used to adjust Sun Orbit values so Linden based viewers properly position sun - private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; - - - /* protected variables */ - - protected static Dictionary PacketHandlers = - new Dictionary(); //Global/static handlers for all clients + private AgentUpdateArgs lastarg; + private bool m_IsActive = true; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers - protected IScene m_scene; - - protected LLPacketServer m_networkServer; - protected LLImageManager m_imageManager; - - /* public variables */ protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; protected Vector3 m_startpos; protected EndPoint m_userEndPoint; - protected EndPoint m_proxyEndPoint; protected UUID m_activeGroupID = UUID.Zero; protected string m_activeGroupName = String.Empty; protected ulong m_activeGroupPowers; protected Dictionary m_groupPowers = new Dictionary(); - protected int m_avatarTerseUpdateRate = 50; - protected int m_avatarTerseUpdatesPerPacket = 5; + protected int m_terrainCheckerCount; - // LL uses these limits, apparently. Compressed terse would be - // 23, but we don't have that yet - // + // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet protected int m_primTerseUpdatesPerPacket = 10; protected int m_primFullUpdatesPerPacket = 14; - protected int m_primTerseUpdateRate = 10; protected int m_primFullUpdateRate = 14; - protected int m_textureSendLimit = 20; protected int m_textureDataLimit = 10; - + protected int m_avatarTerseUpdateRate = 50; + protected int m_avatarTerseUpdatesPerPacket = 5; protected int m_packetMTU = 1400; - protected IAssetService m_assetService; - // LLClientView Only - public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); - - /* Instantiated Designated Event Delegates */ - //- used so we don't create new objects for each incoming packet and then toss it out later */ - - private GenericMessage handlerGenericMessage; - private RequestAvatarProperties handlerRequestAvatarProperties; //OnRequestAvatarProperties; - private UpdateAvatarProperties handlerUpdateAvatarProperties; // OnUpdateAvatarProperties; - private ChatMessage handlerChatFromClient; //OnChatFromClient; - private ChatMessage handlerChatFromClient2; //OnChatFromClient; - private ImprovedInstantMessage handlerInstantMessage; //OnInstantMessage; - private FriendActionDelegate handlerApproveFriendRequest; //OnApproveFriendRequest; - private FriendshipTermination handlerTerminateFriendship; //OnTerminateFriendship; - private RezObject handlerRezObject; //OnRezObject; - private DeRezObject handlerDeRezObject; //OnDeRezObject; - private ModifyTerrain handlerModifyTerrain; - private BakeTerrain handlerBakeTerrain; - private EstateChangeInfo handlerEstateChangeInfo; - private Action handlerRegionHandShakeReply; //OnRegionHandShakeReply; - private GenericCall2 handlerRequestWearables; //OnRequestWearables; - private Action handlerRequestAvatarsData; //OnRequestAvatarsData; - private SetAppearance handlerSetAppearance; //OnSetAppearance; - private AvatarNowWearing handlerAvatarNowWearing; //OnAvatarNowWearing; - private RezSingleAttachmentFromInv handlerRezSingleAttachment; //OnRezSingleAttachmentFromInv; - private RezMultipleAttachmentsFromInv handlerRezMultipleAttachments; //OnRezMultipleAttachmentsFromInv; - private UUIDNameRequest handlerDetachAttachmentIntoInv; // Detach attachment! - private ObjectAttach handlerObjectAttach; //OnObjectAttach; - private SetAlwaysRun handlerSetAlwaysRun; //OnSetAlwaysRun; - private GenericCall2 handlerCompleteMovementToRegion; //OnCompleteMovementToRegion; - private UpdateAgent handlerAgentUpdate; //OnAgentUpdate; - private StartAnim handlerStartAnim; - private StopAnim handlerStopAnim; - private AgentRequestSit handlerAgentRequestSit; //OnAgentRequestSit; - private AgentSit handlerAgentSit; //OnAgentSit; - private AvatarPickerRequest handlerAvatarPickerRequest; //OnAvatarPickerRequest; - private FetchInventory handlerAgentDataUpdateRequest; //OnAgentDataUpdateRequest; - private TeleportLocationRequest handlerSetStartLocationRequest; //OnSetStartLocationRequest; - private TeleportLandmarkRequest handlerTeleportLandmarkRequest; //OnTeleportLandmarkRequest; - private LinkObjects handlerLinkObjects; //OnLinkObjects; - private DelinkObjects handlerDelinkObjects; //OnDelinkObjects; - private AddNewPrim handlerAddPrim; //OnAddPrim; - private UpdateShape handlerUpdatePrimShape; //null; - private ObjectExtraParams handlerUpdateExtraParams; //OnUpdateExtraParams; - private ObjectDuplicate handlerObjectDuplicate; - private ObjectDuplicateOnRay handlerObjectDuplicateOnRay; - private ObjectRequest handlerObjectRequest; - private ObjectSelect handlerObjectSelect; - private ObjectDeselect handlerObjectDeselect; - private ObjectIncludeInSearch handlerObjectIncludeInSearch; - private UpdatePrimFlags handlerUpdatePrimFlags; //OnUpdatePrimFlags; - private UpdatePrimTexture handlerUpdatePrimTexture; - private GrabObject handlerGrabObject; //OnGrabObject; - private MoveObject handlerGrabUpdate; //OnGrabUpdate; - private DeGrabObject handlerDeGrabObject; //OnDeGrabObject; - private SpinStart handlerSpinStart; //OnSpinStart; - private SpinObject handlerSpinUpdate; //OnSpinUpdate; - private SpinStop handlerSpinStop; //OnSpinStop; - private GenericCall7 handlerObjectDescription; - private GenericCall7 handlerObjectName; - private GenericCall7 handlerObjectClickAction; - private GenericCall7 handlerObjectMaterial; - private ObjectPermissions handlerObjectPermissions; - private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily; //OnRequestObjectPropertiesFamily; - //private TextureRequest handlerTextureRequest; - private UDPAssetUploadRequest handlerAssetUploadRequest; //OnAssetUploadRequest; - private RequestXfer handlerRequestXfer; //OnRequestXfer; - private XferReceive handlerXferReceive; //OnXferReceive; - private ConfirmXfer handlerConfirmXfer; //OnConfirmXfer; - private AbortXfer handlerAbortXfer; - private CreateInventoryFolder handlerCreateInventoryFolder; //OnCreateNewInventoryFolder; - private UpdateInventoryFolder handlerUpdateInventoryFolder; - private MoveInventoryFolder handlerMoveInventoryFolder; - private CreateNewInventoryItem handlerCreateNewInventoryItem; //OnCreateNewInventoryItem; - private FetchInventory handlerFetchInventory; - private FetchInventoryDescendents handlerFetchInventoryDescendents; //OnFetchInventoryDescendents; - private PurgeInventoryDescendents handlerPurgeInventoryDescendents; //OnPurgeInventoryDescendents; - private UpdateInventoryItem handlerUpdateInventoryItem; - private CopyInventoryItem handlerCopyInventoryItem; - private MoveInventoryItem handlerMoveInventoryItem; - private RemoveInventoryItem handlerRemoveInventoryItem; - private RemoveInventoryFolder handlerRemoveInventoryFolder; - private RequestTaskInventory handlerRequestTaskInventory; //OnRequestTaskInventory; - private UpdateTaskInventory handlerUpdateTaskInventory; //OnUpdateTaskInventory; - private MoveTaskInventory handlerMoveTaskItem; - private RemoveTaskInventory handlerRemoveTaskItem; //OnRemoveTaskItem; - private RezScript handlerRezScript; //OnRezScript; - private RequestMapBlocks handlerRequestMapBlocks; //OnRequestMapBlocks; - private RequestMapName handlerMapNameRequest; //OnMapNameRequest; - private TeleportLocationRequest handlerTeleportLocationRequest; //OnTeleportLocationRequest; - private MoneyBalanceRequest handlerMoneyBalanceRequest; //OnMoneyBalanceRequest; - private UUIDNameRequest handlerNameRequest; - private ParcelAccessListRequest handlerParcelAccessListRequest; //OnParcelAccessListRequest; - private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest; //OnParcelAccessListUpdateRequest; - private ParcelPropertiesRequest handlerParcelPropertiesRequest; //OnParcelPropertiesRequest; - private ParcelDivideRequest handlerParcelDivideRequest; //OnParcelDivideRequest; - private ParcelJoinRequest handlerParcelJoinRequest; //OnParcelJoinRequest; - private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest; //OnParcelPropertiesUpdateRequest; - private ParcelSelectObjects handlerParcelSelectObjects; //OnParcelSelectObjects; - private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest; //OnParcelObjectOwnerRequest; - private ParcelAbandonRequest handlerParcelAbandonRequest; - private ParcelGodForceOwner handlerParcelGodForceOwner; - private ParcelReclaim handlerParcelReclaim; - private RequestTerrain handlerRequestTerrain; - private RequestTerrain handlerUploadTerrain; - private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest; - private RegionInfoRequest handlerRegionInfoRequest; //OnRegionInfoRequest; - private EstateCovenantRequest handlerEstateCovenantRequest; //OnEstateCovenantRequest; - private RequestGodlikePowers handlerReqGodlikePowers; //OnRequestGodlikePowers; - private GodKickUser handlerGodKickUser; //OnGodKickUser; - private ViewerEffectEventHandler handlerViewerEffect; //OnViewerEffect; - private Action handlerLogout; //OnLogout; - private MoneyTransferRequest handlerMoneyTransferRequest; //OnMoneyTransferRequest; - private ParcelBuy handlerParcelBuy; - private EconomyDataRequest handlerEconomoyDataRequest; - - private UpdateVector handlerUpdatePrimSinglePosition; //OnUpdatePrimSinglePosition; - private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation; //OnUpdatePrimSingleRotation; - private UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition; //OnUpdatePrimSingleRotation; - private UpdateVector handlerUpdatePrimScale; //OnUpdatePrimScale; - private UpdateVector handlerUpdatePrimGroupScale; //OnUpdateGroupScale; - private UpdateVector handlerUpdateVector; //OnUpdatePrimGroupPosition; - private UpdatePrimRotation handlerUpdatePrimRotation; //OnUpdatePrimGroupRotation; - // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; //OnUpdatePrimGroupMouseRotation; - // private RequestAsset handlerRequestAsset; // OnRequestAsset; - private UUIDNameRequest handlerTeleportHomeRequest; - - private RegionHandleRequest handlerRegionHandleRequest; // OnRegionHandleRequest - private ParcelInfoRequest handlerParcelInfoRequest; // OnParcelInfoRequest - - private ScriptAnswer handlerScriptAnswer; - private RequestPayPrice handlerRequestPayPrice; - private ObjectSaleInfo handlerObjectSaleInfo; - private ObjectBuy handlerObjectBuy; - //private BuyObjectInventory handlerBuyObjectInventory; - private ObjectDeselect handlerObjectDetach; - private ObjectDrop handlerObjectDrop; - private AgentSit handlerOnUndo; - - private ForceReleaseControls handlerForceReleaseControls; - - private GodLandStatRequest handlerLandStatRequest; - - private UUIDNameRequest handlerUUIDGroupNameRequest; - - private ParcelDeedToGroup handlerParcelDeedToGroup; - - private RequestObjectPropertiesFamily handlerObjectGroupRequest; - private ScriptReset handlerScriptReset; - private GetScriptRunning handlerGetScriptRunning; - private SetScriptRunning handlerSetScriptRunning; - private UpdateVector handlerAutoPilotGo; - //Gesture - private ActivateGesture handlerActivateGesture; - private DeactivateGesture handlerDeactivateGesture; - //Sound - private SoundTrigger handlerSoundTrigger; - private ObjectOwner handlerObjectOwner; - - private DirPlacesQuery handlerDirPlacesQuery; - private DirFindQuery handlerDirFindQuery; - private DirLandQuery handlerDirLandQuery; - private DirPopularQuery handlerDirPopularQuery; - private DirClassifiedQuery handlerDirClassifiedQuery; - private ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime; - - private MapItemRequest handlerMapItemRequest; - - private StartLure handlerStartLure; - private TeleportLureRequest handlerTeleportLureRequest; - - private NetworkStats handlerNetworkStatsUpdate; - - private ClassifiedInfoRequest handlerClassifiedInfoRequest; - private ClassifiedInfoUpdate handlerClassifiedInfoUpdate; - private ClassifiedDelete handlerClassifiedDelete; - private ClassifiedDelete handlerClassifiedGodDelete; - - private EventNotificationAddRequest handlerEventNotificationAddRequest; - private EventNotificationRemoveRequest handlerEventNotificationRemoveRequest; - private EventGodDelete handlerEventGodDelete; - - private ParcelDwellRequest handlerParcelDwellRequest; - - private UserInfoRequest handlerUserInfoRequest; - private UpdateUserInfo handlerUpdateUserInfo; - - private RetrieveInstantMessages handlerRetrieveInstantMessages; - - private PickDelete handlerPickDelete; - private PickGodDelete handlerPickGodDelete; - private PickInfoUpdate handlerPickInfoUpdate; - private AvatarNotesUpdate handlerAvatarNotesUpdate; - - private MuteListRequest handlerMuteListRequest; - - //private AvatarInterestUpdate handlerAvatarInterestUpdate; - - private PlacesQuery handlerPlacesQuery; - - private readonly IGroupsModule m_GroupsModule; - - private AgentUpdateArgs lastarg = null; - - //private TerrainUnacked handlerUnackedTerrain = null; - - //** - - /* Properties */ - - public UUID SecureSessionId - { - get { return m_secureSessionId; } - } - - public IScene Scene - { - get { return m_scene; } - } - - public UUID SessionId - { - get { return m_sessionId; } - } + #region Properties + public UUID SecureSessionId { get { return m_secureSessionId; } } + public IScene Scene { get { return m_scene; } } + public UUID SessionId { get { return m_sessionId; } } public Vector3 StartPos { get { return m_startpos; } set { m_startpos = value; } } - - public UUID AgentId - { - get { return m_agentId; } - } - - public UUID ActiveGroupId - { - get { return m_activeGroupID; } - } - - public string ActiveGroupName - { - get { return m_activeGroupName; } - } - - public ulong ActiveGroupPowers - { - get { return m_activeGroupPowers; } - } - - public bool IsGroupMember(UUID groupID) - { - return m_groupPowers.ContainsKey(groupID); - } - - public ulong GetGroupPowers(UUID groupID) - { - if (groupID == m_activeGroupID) - return m_activeGroupPowers; - - if (m_groupPowers.ContainsKey(groupID)) - return m_groupPowers[groupID]; - - return 0; - } - - /// - /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. - /// - public bool ChildAgentStatus() - { - return m_scene.PresenceChildStatus(AgentId); - } - + public UUID AgentId { get { return m_agentId; } } + public UUID ActiveGroupId { get { return m_activeGroupID; } } + public string ActiveGroupName { get { return m_activeGroupName; } } + public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } + public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } /// /// First name of the agent/avatar represented by the client /// - public string FirstName - { - get { return m_firstName; } - } - + public string FirstName { get { return m_firstName; } } /// /// Last name of the agent/avatar represented by the client /// - public string LastName - { - get { return m_lastName; } - } - + public string LastName { get { return m_lastName; } } /// /// Full name of the client (first name and last name) /// - public string Name - { - get { return FirstName + " " + LastName; } - } - - public uint CircuitCode - { - get { return m_circuitCode; } - } - - public int MoneyBalance - { - get { return m_moneyBalance; } - } - - public int NextAnimationSequenceNumber - { - get { return m_animationSequenceNumber++; } - } - - public ILLPacketHandler PacketHandler - { - get { return m_PacketHandler; } - } - - bool m_IsActive = true; - + public string Name { get { return FirstName + " " + LastName; } } + public uint CircuitCode { get { return m_circuitCode; } } + public int MoneyBalance { get { return m_moneyBalance; } } + public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } public bool IsActive { get { return m_IsActive; } set { m_IsActive = value; } } + public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } - public bool SendLogoutPacketWhenClosing - { - set { m_SendLogoutPacketWhenClosing = value; } - } - - /* METHODS */ + #endregion Properties /// /// Constructor /// - public LLClientView( - EndPoint remoteEP, IScene scene, LLPacketServer packServer, - AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP, - ClientStackUserSettings userSettings) + public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, + UUID agentId, UUID sessionId, uint circuitCode) { - // Should be called first? - RegisterInterfaces(); - - m_GroupsModule = scene.RequestModuleInterface(); - m_moneyBalance = 1000; - - m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); - + RegisterInterface(this); + RegisterInterface(this); + RegisterInterface(this); + InitDefaultAnimations(); m_scene = scene; - //m_assetCache = assetCache; - m_assetService = m_scene.RequestModuleInterface(); - - m_networkServer = packServer; - + m_GroupsModule = scene.RequestModuleInterface(); + m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); + m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); m_agentId = agentId; m_sessionId = sessionId; + m_secureSessionId = sessionInfo.LoginInfo.SecureSession; m_circuitCode = circuitCode; - m_userEndPoint = remoteEP; - m_proxyEndPoint = proxyEP; - m_firstName = sessionInfo.LoginInfo.First; m_lastName = sessionInfo.LoginInfo.Last; m_startpos = sessionInfo.LoginInfo.StartPos; + m_moneyBalance = 1000; - if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) - { - m_secureSessionId = sessionInfo.LoginInfo.SecureSession; - } - - // While working on this, the BlockingQueue had me fooled for a bit. - // The Blocking queue causes the thread to stop until there's something - // in it to process. It's an on-purpose threadlock though because - // without it, the clientloop will suck up all sim resources. - - m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings); - m_PacketHandler.SynchronizeClient = SynchronizeClient; - m_PacketHandler.OnPacketStats += PopulateStats; - m_PacketHandler.OnQueueEmpty += HandleQueueEmpty; - - if (scene.Config != null) - { - IConfig clientConfig = scene.Config.Configs["LLClient"]; - if (clientConfig != null) - { - m_PacketHandler.ReliableIsImportant = - clientConfig.GetBoolean("ReliableIsImportant", - false); - m_PacketHandler.MaxReliableResends = clientConfig.GetInt("MaxReliableResends", - m_PacketHandler.MaxReliableResends); - m_primTerseUpdatesPerPacket = clientConfig.GetInt("TerseUpdatesPerPacket", - m_primTerseUpdatesPerPacket); - m_primFullUpdatesPerPacket = clientConfig.GetInt("FullUpdatesPerPacket", - m_primFullUpdatesPerPacket); - - m_primTerseUpdateRate = clientConfig.GetInt("TerseUpdateRate", - m_primTerseUpdateRate); - m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate", - m_primFullUpdateRate); - - m_textureSendLimit = clientConfig.GetInt("TextureSendLimit", - m_textureSendLimit); - - m_textureDataLimit = clientConfig.GetInt("TextureDataLimit", - m_textureDataLimit); - - m_packetMTU = clientConfig.GetInt("PacketMTU", 1400); - } - } + m_udpServer = udpServer; + m_udpClient = udpClient; + m_udpClient.OnQueueEmpty += HandleQueueEmpty; + m_udpClient.OnPacketStats += PopulateStats; RegisterLocalPacketHandlers(); - m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); } - public void SetDebugPacketLevel(int newDebugPacketLevel) + public void SetDebugPacketLevel(int newDebug) { - m_debugPacketLevel = newDebugPacketLevel; } - # region Client Methods + #region Client Methods - private void CloseCleanup(bool shutdownCircuit) + /// + /// Close down the client view. This *must* be the last method called, since the last # + /// statement of CloseCleanup() aborts the thread. + /// + /// + public void Close(bool shutdownCircuit) { + m_log.DebugFormat( + "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", + shutdownCircuit, Name, m_scene.RegionInfo.RegionName); - + if (m_imageManager != null) + m_imageManager.Close(); + + if (m_udpServer != null) + m_udpServer.Flush(); + + // raise an event on the packet server to Shutdown the circuit + // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup + // here otherwise we'll end up calling it twice. + // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks + // horribly tangly. Hopefully it should be possible to greatly simplify it. + if (shutdownCircuit) + { + if (OnConnectionClosed != null) + OnConnectionClosed(this); + } + else + { + CloseCleanup(shutdownCircuit); + } + } + + private void CloseCleanup(bool shutdownCircuit) + { m_scene.RemoveClient(AgentId); //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); @@ -590,9 +244,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP Thread.Sleep(2000); // Shut down timers. Thread Context of this method is murky. Lock all timers - if (m_clientPingTimer.Enabled) - lock (m_clientPingTimer) - m_clientPingTimer.Stop(); if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -625,43 +276,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP // of the client thread regardless of where Close() is called. KillEndDone(); } - - Terminate(); - } - /// - /// Close down the client view. This *must* be the last method called, since the last # - /// statement of CloseCleanup() aborts the thread. - /// - /// - public void Close(bool shutdownCircuit) - { - m_clientPingTimer.Enabled = false; + IsActive = false; - m_log.DebugFormat( - "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", - shutdownCircuit, Name, m_scene.RegionInfo.RegionName); + m_avatarTerseUpdateTimer.Close(); + m_primTerseUpdateTimer.Close(); + m_primFullUpdateTimer.Close(); - if (m_imageManager != null) - m_imageManager.Close(); + //m_udpServer.OnPacketStats -= PopulateStats; + m_udpClient.Shutdown(); - if (m_PacketHandler != null) - m_PacketHandler.Flush(); + // wait for thread stoped + // m_clientThread.Join(); - // raise an event on the packet server to Shutdown the circuit - // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup - // here otherwise we'll end up calling it twice. - // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks - // horribly tangly. Hopefully it should be possible to greatly simplify it. - if (shutdownCircuit) - { - if (OnConnectionClosed != null) - OnConnectionClosed(this); - } - else - { - CloseCleanup(shutdownCircuit); - } + // delete circuit code + //m_networkServer.CloseClient(this); } public void Kick(string message) @@ -683,10 +312,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Stop() { // Shut down timers. Thread Context is Murky, lock all timers! - if (m_clientPingTimer.Enabled) - lock (m_clientPingTimer) - m_clientPingTimer.Stop(); - if (m_avatarTerseUpdateTimer.Enabled) lock (m_avatarTerseUpdateTimer) m_avatarTerseUpdateTimer.Stop(); @@ -700,54 +325,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdateTimer.Stop(); } - public void Restart() - { - // re-construct - m_PacketHandler.Clear(); - - m_clientPingTimer = new Timer(5000); - m_clientPingTimer.Elapsed += CheckClientConnectivity; - m_clientPingTimer.Enabled = true; - - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); - m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); - m_avatarTerseUpdateTimer.AutoReset = false; - - m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); - m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); - m_primTerseUpdateTimer.AutoReset = false; - - m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); - m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); - m_primFullUpdateTimer.AutoReset = false; - } - - private void Terminate() - { - IsActive = false; - - m_clientPingTimer.Close(); - m_avatarTerseUpdateTimer.Close(); - m_primTerseUpdateTimer.Close(); - m_primFullUpdateTimer.Close(); - - m_PacketHandler.OnPacketStats -= PopulateStats; - m_PacketHandler.Dispose(); - - // wait for thread stoped - // m_clientThread.Join(); - - // delete circuit code - //m_networkServer.CloseClient(this); - } - - #endregion + #endregion Client Methods - # region Packet Handling + #region Packet Handling public void PopulateStats(int inPackets, int outPackets, int unAckedBytes) { - handlerNetworkStatsUpdate = OnNetworkStatsUpdate; + NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate; if (handlerNetworkStatsUpdate != null) { handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes); @@ -828,7 +412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return result; } - protected void DebugPacket(string direction, Packet packet) + /*protected void DebugPacket(string direction, Packet packet) { string info; @@ -854,111 +438,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); - } + }*/ + + #endregion Packet Handling + + # region Setup /// - /// Main packet processing loop for the UDP component of the client session. Both incoming and outgoing - /// packets are processed here. + /// Starts up the timers to check the client and resend unacked packets + /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene /// - protected virtual void ClientLoop() + protected virtual void InitNewClient() { - m_log.DebugFormat( - "[CLIENT]: Entered main packet processing loop for {0} in {1}", Name, Scene.RegionInfo.RegionName); + m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); + m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); + m_avatarTerseUpdateTimer.AutoReset = false; - while (IsActive) - { - LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue(); - - if (nextPacket == null) { - m_log.DebugFormat("[CLIENT]: PacketQueue return null LLQueItem"); - continue; - } - - if (nextPacket.Incoming) - { - if (m_debugPacketLevel > 0) - DebugPacket("IN", nextPacket.Packet); - m_PacketHandler.ProcessInPacket(nextPacket); - } - else - { - if (m_debugPacketLevel > 0) - DebugPacket("OUT", nextPacket.Packet); - m_PacketHandler.ProcessOutPacket(nextPacket); - } - } - } - - # endregion - - protected int m_terrainCheckerCount; - - /// - /// Event handler for check client timer - /// Checks to ensure that the client is still connected. If the client has failed to respond to many pings - /// in succession then close down the connection. - /// - /// - /// - protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) - { - if (m_PacketHandler.PacketsReceived == m_inPacketsChecked) - { - // no packet came in since the last time we checked... - - m_probesWithNoIngressPackets++; - if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) // agent active - || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) // agent paused - { - m_clientPingTimer.Enabled = false; - - m_log.WarnFormat( - "[CLIENT]: Client for agent {0} {1} has stopped responding to pings. Closing connection", - Name, AgentId); - - if (OnConnectionClosed != null) - { - OnConnectionClosed(this); - } - } - else - { - // this will normally trigger at least one packet (ping response) - SendStartPingCheck(0); - } - } - else - { - // Something received in the meantime - we can reset the counters - m_probesWithNoIngressPackets = 0; - // ... and store the current number of packets received to find out if another one got in on the next cycle - m_inPacketsChecked = m_PacketHandler.PacketsReceived; - } - - } - - # region Setup - - /// - /// Starts up the timers to check the client and resend unacked packets - /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene - /// - protected virtual void InitNewClient() - { - //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); - - // Ping the client regularly to check that it's still there - m_clientPingTimer = new Timer(5000); - m_clientPingTimer.Elapsed += CheckClientConnectivity; - m_clientPingTimer.Enabled = true; - - m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); - m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); - m_avatarTerseUpdateTimer.AutoReset = false; - - m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); - m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); - m_primTerseUpdateTimer.AutoReset = false; + m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate); + m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates); + m_primTerseUpdateTimer.AutoReset = false; m_primFullUpdateTimer = new Timer(m_primFullUpdateRate); m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates); @@ -971,27 +469,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_clientThread = new Thread(RunUserSession); - m_clientThread.Name = "ClientThread"; - m_clientThread.IsBackground = true; - m_clientThread.Start(); - ThreadTracker.Add(m_clientThread); + // This sets up all the timers + InitNewClient(); } /// /// Run a user session. This method lies at the base of the entire client thread. /// - protected virtual void RunUserSession() + protected void RunUserSession() { - //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US) - //otherwise it will override this and use the system default - Culture.SetCurrentCulture(); - try { - // This sets up all the timers - InitNewClient(); - ClientLoop(); + } catch (Exception e) { @@ -1015,11 +504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP + "Any further actions taken will not be processed.\n" + "Please relog", true); - LLQueItem item = new LLQueItem(); - item.Packet = packet; - item.Sequence = packet.Header.Sequence; - - m_PacketHandler.ProcessOutPacket(item); + m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false); // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to // listeners yet, though. @@ -1037,7 +522,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP # endregion - // Previously ClientView.API partial class + #region Events + public event GenericMessage OnGenericMessage; public event BinaryGenericMessage OnBinaryGenericMessage; public event Action OnLogout; @@ -1197,13 +683,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; - public event TerrainUnacked OnUnackedTerrain; - public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; public event ObjectOwner OnObjectOwner; - public event DirPlacesQuery OnDirPlacesQuery; public event DirFindQuery OnDirFindQuery; public event DirLandQuery OnDirLandQuery; @@ -1211,45 +694,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event DirClassifiedQuery OnDirClassifiedQuery; public event EventInfoRequest OnEventInfoRequest; public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; - public event MapItemRequest OnMapItemRequest; - public event OfferCallingCard OnOfferCallingCard; public event AcceptCallingCard OnAcceptCallingCard; public event DeclineCallingCard OnDeclineCallingCard; public event SoundTrigger OnSoundTrigger; - public event StartLure OnStartLure; public event TeleportLureRequest OnTeleportLureRequest; public event NetworkStats OnNetworkStatsUpdate; - public event ClassifiedInfoRequest OnClassifiedInfoRequest; public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; public event ClassifiedDelete OnClassifiedDelete; public event ClassifiedDelete OnClassifiedGodDelete; - public event EventNotificationAddRequest OnEventNotificationAddRequest; public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; public event EventGodDelete OnEventGodDelete; - public event ParcelDwellRequest OnParcelDwellRequest; - public event UserInfoRequest OnUserInfoRequest; public event UpdateUserInfo OnUpdateUserInfo; - public event RetrieveInstantMessages OnRetrieveInstantMessages; - public event PickDelete OnPickDelete; public event PickGodDelete OnPickGodDelete; public event PickInfoUpdate OnPickInfoUpdate; public event AvatarNotesUpdate OnAvatarNotesUpdate; - public event MuteListRequest OnMuteListRequest; - - //public event AvatarInterestUpdate OnAvatarInterestUpdate; - + public event AvatarInterestUpdate OnAvatarInterestUpdate; public event PlacesQuery OnPlacesQuery; + #endregion Events + public void ActivateGesture(UUID assetId, UUID gestureId) { } @@ -1850,8 +1323,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendStartPingCheck(byte seq) { StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); - pc.PingID.PingID = seq; pc.Header.Reliable = false; + + OutgoingPacket oldestPacket = m_udpClient.NeedAcks.GetOldest(); + + pc.PingID.PingID = seq; + pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; + OutPacket(pc, ThrottleOutPacketType.Unknown); } @@ -1927,12 +1405,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP descend.ItemData[i].AssetID = item.AssetID; descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; descend.ItemData[i].BaseMask = item.BasePermissions; - descend.ItemData[i].Description = LLUtil.StringToPacketBytes(item.Description); + descend.ItemData[i].Description = Util.StringToBytes256(item.Description); descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; descend.ItemData[i].OwnerMask = item.CurrentPermissions; descend.ItemData[i].FolderID = item.Folder; descend.ItemData[i].InvType = (sbyte)item.InvType; - descend.ItemData[i].Name = LLUtil.StringToPacketBytes(item.Name); + descend.ItemData[i].Name = Util.StringToBytes256(item.Name); descend.ItemData[i].NextOwnerMask = item.NextPermissions; descend.ItemData[i].OwnerID = item.Owner; descend.ItemData[i].Type = (sbyte)item.AssetType; @@ -2013,7 +1491,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); descend.FolderData[i].FolderID = folder.ID; - descend.FolderData[i].Name = LLUtil.StringToPacketBytes(folder.Name); + descend.FolderData[i].Name = Util.StringToBytes256(folder.Name); descend.FolderData[i].ParentID = folder.ParentID; descend.FolderData[i].Type = (sbyte)folder.Type; @@ -2128,11 +1606,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; inventoryReply.InventoryData[0].CreationDate = item.CreationDate; - inventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(item.Description); + inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description); inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; inventoryReply.InventoryData[0].FolderID = item.Folder; inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; - inventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(item.Name); + inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name); inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; inventoryReply.InventoryData[0].OwnerID = item.Owner; inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; @@ -2257,7 +1735,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; folderBlock.Type = -1; - folderBlock.Name = LLUtil.StringToPacketBytes(folder.Name); + folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; } @@ -2275,11 +1753,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP itemBlock.AssetID = item.AssetID; itemBlock.CreatorID = item.CreatorIdAsUuid; itemBlock.BaseMask = item.BasePermissions; - itemBlock.Description = LLUtil.StringToPacketBytes(item.Description); + itemBlock.Description = Util.StringToBytes256(item.Description); itemBlock.EveryoneMask = item.EveryOnePermissions; itemBlock.FolderID = item.Folder; itemBlock.InvType = (sbyte)item.InvType; - itemBlock.Name = LLUtil.StringToPacketBytes(item.Name); + itemBlock.Name = Util.StringToBytes256(item.Name); itemBlock.NextOwnerMask = item.NextPermissions; itemBlock.OwnerID = item.Owner; itemBlock.OwnerMask = item.CurrentPermissions; @@ -2339,11 +1817,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid; bulkUpdate.ItemData[0].BaseMask = item.BasePermissions; bulkUpdate.ItemData[0].CreationDate = item.CreationDate; - bulkUpdate.ItemData[0].Description = LLUtil.StringToPacketBytes(item.Description); + bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description); bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions; bulkUpdate.ItemData[0].FolderID = item.Folder; bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType; - bulkUpdate.ItemData[0].Name = LLUtil.StringToPacketBytes(item.Name); + bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name); bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions; bulkUpdate.ItemData[0].OwnerID = item.Owner; bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; @@ -2386,11 +1864,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP InventoryReply.InventoryData[0].AssetID = Item.AssetID; InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid; InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions; - InventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(Item.Description); + InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description); InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions; InventoryReply.InventoryData[0].FolderID = Item.Folder; InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType; - InventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(Item.Name); + InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name); InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions; InventoryReply.InventoryData[0].OwnerID = Item.Owner; InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; @@ -2557,7 +2035,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// /// - protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) + public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) { AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); alertPack.AgentData.AgentID = AgentId; @@ -2768,7983 +2246,8011 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(avatarReply, ThrottleOutPacketType.Task); } - #endregion - - // Gesture + /// + /// Send the client an Estate message blue box pop-down with a single OK button + /// + /// + /// + /// + /// + public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) + { + if (!ChildAgentStatus()) + SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); - #region Appearance/ Wearables Methods + //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); + } - public void SendWearables(AvatarWearable[] wearables, int serial) + public void SendLogoutPacket() { - AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); - aw.AgentData.AgentID = AgentId; - aw.AgentData.SerialNum = (uint)serial; - aw.AgentData.SessionID = m_sessionId; + // I know this is a bit of a hack, however there are times when you don't + // want to send this, but still need to do the rest of the shutdown process + // this method gets called from the packet server.. which makes it practically + // impossible to do any other way. - // TODO: don't create new blocks if recycling an old packet - aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; - AgentWearablesUpdatePacket.WearableDataBlock awb; - for (int i = 0; i < wearables.Length; i++) + if (m_SendLogoutPacketWhenClosing) { - awb = new AgentWearablesUpdatePacket.WearableDataBlock(); - awb.WearableType = (byte)i; - awb.AssetID = wearables[i].AssetID; - awb.ItemID = wearables[i].ItemID; - aw.WearableData[i] = awb; + LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); + // TODO: don't create new blocks if recycling an old packet + logReply.AgentData.AgentID = AgentId; + logReply.AgentData.SessionID = SessionId; + logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; + logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); + logReply.InventoryData[0].ItemID = UUID.Zero; -// m_log.DebugFormat( -// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", -// awb.ItemID, awb.AssetID, i, Name); + OutPacket(logReply, ThrottleOutPacketType.Task); } - - OutPacket(aw, ThrottleOutPacketType.Task); } - public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) + public void SendHealth(float health) { - AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); - // TODO: don't create new blocks if recycling an old packet - avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; - avp.ObjectData.TextureEntry = textureEntry; + HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); + healthpacket.HealthData.Health = health; + OutPacket(healthpacket, ThrottleOutPacketType.Task); + } - AvatarAppearancePacket.VisualParamBlock avblock = null; - for (int i = 0; i < visualParams.Length; i++) + public void SendAgentOnline(UUID[] agentIDs) + { + OnlineNotificationPacket onp = new OnlineNotificationPacket(); + OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) { - avblock = new AvatarAppearancePacket.VisualParamBlock(); - avblock.ParamValue = visualParams[i]; - avp.VisualParam[i] = avblock; + OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + onpb[i] = onpbl; } - - avp.Sender.IsTrial = false; - avp.Sender.ID = agentID; - OutPacket(avp, ThrottleOutPacketType.Task); + onp.AgentBlock = onpb; + onp.Header.Reliable = true; + OutPacket(onp, ThrottleOutPacketType.Task); } - public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + public void SendAgentOffline(UUID[] agentIDs) { - //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); - - AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); - // TODO: don't create new blocks if recycling an old packet - ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; - ani.Sender = new AvatarAnimationPacket.SenderBlock(); - ani.Sender.ID = sourceAgentId; - ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; - ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; - - for (int i = 0; i < animations.Length; ++i) + OfflineNotificationPacket offp = new OfflineNotificationPacket(); + OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; + for (int i = 0; i < agentIDs.Length; i++) { - ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); - ani.AnimationList[i].AnimID = animations[i]; - ani.AnimationList[i].AnimSequenceID = seqs[i]; + OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = agentIDs[i]; + offpb[i] = onpbl; + } + offp.AgentBlock = offpb; + offp.Header.Reliable = true; + OutPacket(offp, ThrottleOutPacketType.Task); + } - ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); - ani.AnimationSourceList[i].ObjectID = objectIDs[i]; - if (objectIDs[i] == UUID.Zero) - ani.AnimationSourceList[i].ObjectID = sourceAgentId; + public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, + Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) + { + AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); + avatarSitResponse.SitObject.ID = TargetID; + if (CameraAtOffset != Vector3.Zero) + { + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; } - ani.Header.Reliable = false; - OutPacket(ani, ThrottleOutPacketType.Task); + avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; + avatarSitResponse.SitTransform.AutoPilot = autopilot; + avatarSitResponse.SitTransform.SitPosition = OffsetPos; + avatarSitResponse.SitTransform.SitRotation = SitOrientation; + + OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); } - #endregion + public void SendAdminResponse(UUID Token, uint AdminLevel) + { + GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); + GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); + GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); - #region Avatar Packet/data sending Methods + adb.AgentID = AgentId; + adb.SessionID = SessionId; // More security + gdb.GodLevel = (byte)AdminLevel; + gdb.Token = Token; + //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; + respondPacket.GrantData = gdb; + respondPacket.AgentData = adb; + OutPacket(respondPacket, ThrottleOutPacketType.Task); + } - /// - /// send a objectupdate packet with information about the clients avatar - /// - public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, - uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) + public void SendGroupMembership(GroupMembershipData[] GroupMembership) { - ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - // TODO: don't create new blocks if recycling an old packet - objupdate.RegionData.RegionHandle = regionHandle; - objupdate.RegionData.TimeDilation = ushort.MaxValue; - objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); + m_groupPowers.Clear(); - //give this avatar object a local id and assign the user a name - objupdate.ObjectData[0].ID = avatarLocalID; - objupdate.ObjectData[0].FullID = avatarID; - objupdate.ObjectData[0].ParentID = parentID; - objupdate.ObjectData[0].NameValue = - Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); + AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); + AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; - Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); - byte[] pb = pos2.GetBytes(); - Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); + Group.AcceptNotices = GroupMembership[i].AcceptNotices; + Group.Contribution = GroupMembership[i].Contribution; + Group.GroupID = GroupMembership[i].GroupID; + Group.GroupInsigniaID = GroupMembership[i].GroupPicture; + Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); + Group.GroupPowers = GroupMembership[i].GroupPowers; + Groups[i] = Group; - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); - objupdate.Header.Zerocoded = true; - OutPacket(objupdate, ThrottleOutPacketType.Task); - } - - /// - /// Send a terse positional/rotation/velocity update about an avatar - /// to the client. This avatar can be that of the client itself. - /// - public virtual void SendAvatarTerseUpdate(ulong regionHandle, - ushort timeDilation, uint localID, Vector3 position, - Vector3 velocity, Quaternion rotation, UUID agentid) - { - if (rotation.X == rotation.Y && - rotation.Y == rotation.Z && - rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + } + Groupupdate.GroupData = Groups; + Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); + Groupupdate.AgentData.AgentID = AgentId; + OutPacket(Groupupdate, ThrottleOutPacketType.Task); - ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = - CreateAvatarImprovedBlock(localID, position, velocity,rotation); - - lock (m_avatarTerseUpdates) + try { - m_avatarTerseUpdates.Add(terseBlock); - - // If packet is full or own movement packet, send it. - if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) - { - ProcessAvatarTerseUpdates(this, null); - } - else if (m_avatarTerseUpdates.Count == 1) + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Start(); + eq.GroupMembership(Groupupdate, this.AgentId); } } + catch (Exception ex) + { + m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending group membership data via UDP"); + OutPacket(Groupupdate, ThrottleOutPacketType.Task); + } } - private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) + + public void SendGroupNameReply(UUID groupLLUID, string GroupName) { - lock (m_avatarTerseUpdates) - { - ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); + UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; + UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); + uidnamebloc.ID = groupLLUID; + uidnamebloc.GroupName = Utils.StringToBytes(GroupName); + uidnameblock[0] = uidnamebloc; + pack.UUIDNameBlock = uidnameblock; + OutPacket(pack, ThrottleOutPacketType.Task); + } - terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); + public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) + { + LandStatReplyPacket lsrp = new LandStatReplyPacket(); + // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); + LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; + //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + // lsrepdb. + lsrp.RequestData.ReportType = reportType; + lsrp.RequestData.RequestFlags = requestFlags; + lsrp.RequestData.TotalObjectCount = resultCount; + for (int i = 0; i < lsrpia.Length; i++) + { + LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + lsrepdb.LocationX = lsrpia[i].LocationX; + lsrepdb.LocationY = lsrpia[i].LocationY; + lsrepdb.LocationZ = lsrpia[i].LocationZ; + lsrepdb.Score = lsrpia[i].Score; + lsrepdb.TaskID = lsrpia[i].TaskID; + lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; + lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); + lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); + lsrepdba[i] = lsrepdb; + } + lsrp.ReportData = lsrepdba; + OutPacket(lsrp, ThrottleOutPacketType.Task); + } - terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; - terse.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) + { + ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); + scriptRunningReply.Script.ObjectID = objectID; + scriptRunningReply.Script.ItemID = itemID; + scriptRunningReply.Script.Running = running; - int max = m_avatarTerseUpdatesPerPacket; - if (max > m_avatarTerseUpdates.Count) - max = m_avatarTerseUpdates.Count; + OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); + } - int count = 0; - int size = 0; + public void SendAsset(AssetRequestToClient req) + { + //m_log.Debug("sending asset " + req.RequestAssetID); + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + if (req.AssetRequestSource == 2) + { + Transfer.TransferInfo.Params = new byte[20]; + Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + int assType = req.AssetInf.Type; + Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); + } + else if (req.AssetRequestSource == 3) + { + Transfer.TransferInfo.Params = req.Params; + // Transfer.TransferInfo.Params = new byte[100]; + //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); + } + Transfer.TransferInfo.Size = req.AssetInf.Data.Length; + Transfer.TransferInfo.TransferID = req.TransferRequestID; + Transfer.Header.Zerocoded = true; + OutPacket(Transfer, ThrottleOutPacketType.Asset); - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + if (req.NumPackets == 1) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + TransferPacket.TransferData.Data = req.AssetInf.Data; + TransferPacket.TransferData.Status = 1; + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + } + else + { + int processedLength = 0; + int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; + int packetNumber = 0; - for (count = 0 ; count < max ; count++) + while (processedLength < req.AssetInf.Data.Length) { - int length = 0; - m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = packetNumber; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; - terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; + int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); + byte[] chunk = new byte[chunkSize]; + Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); - for (int i = 0 ; i < count ; i++) - { - terse.ObjectData[i] = m_avatarTerseUpdates[0]; - m_avatarTerseUpdates.RemoveAt(0); - } + TransferPacket.TransferData.Data = chunk; - terse.Header.Reliable = false; - terse.Header.Zerocoded = true; - OutPacket(terse, ThrottleOutPacketType.Task); + // 0 indicates more packets to come, 1 indicates last packet + if (req.AssetInf.Data.Length - processedLength > maxChunkSize) + { + TransferPacket.TransferData.Status = 0; + } + else + { + TransferPacket.TransferData.Status = 1; + } + TransferPacket.Header.Zerocoded = true; + OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - if (m_avatarTerseUpdates.Count == 0) - { - lock (m_avatarTerseUpdateTimer) - m_avatarTerseUpdateTimer.Stop(); + processedLength += chunkSize; + packetNumber++; } } } - public void SendCoarseLocationUpdate(List users, List CoarseLocations) + public void SendTexture(AssetBase TextureAsset) { - if (!IsActive) return; // We don't need to update inactive clients. - CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); - // TODO: don't create new blocks if recycling an old packet - int total = CoarseLocations.Count; - CoarseLocationUpdatePacket.IndexBlock ib = - new CoarseLocationUpdatePacket.IndexBlock(); - loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; - loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; + } - for (int i = 0; i < total; i++) - { - CoarseLocationUpdatePacket.LocationBlock lb = - new CoarseLocationUpdatePacket.LocationBlock(); - lb.X = (byte)CoarseLocations[i].X; - lb.Y = (byte)CoarseLocations[i].Y; + public void SendRegionHandle(UUID regionID, ulong handle) + { + RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); + reply.ReplyBlock.RegionID = regionID; + reply.ReplyBlock.RegionHandle = handle; + OutPacket(reply, ThrottleOutPacketType.Land); + } - lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); - loc.Location[i] = lb; - loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); - loc.AgentData[i].AgentID = users[i]; + public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) + { + ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); + reply.AgentData.AgentID = m_agentId; + reply.Data.ParcelID = parcelID; + reply.Data.OwnerID = land.OwnerID; + reply.Data.Name = Utils.StringToBytes(land.Name); + reply.Data.Desc = Utils.StringToBytes(land.Description); + reply.Data.ActualArea = land.Area; + reply.Data.BillableArea = land.Area; // TODO: what is this? + + // Bit 0: Mature, bit 7: on sale, other bits: no idea + reply.Data.Flags = (byte)( + ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + + ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + + Vector3 pos = land.UserLocation; + if (pos.Equals(Vector3.Zero)) + { + pos = (land.AABBMax + land.AABBMin) * 0.5f; } - ib.You = -1; - ib.Prey = -1; - loc.Index = ib; - loc.Header.Reliable = false; - loc.Header.Zerocoded = true; + reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; + reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; + reply.Data.GlobalZ = pos.Z; + reply.Data.SimName = Utils.StringToBytes(info.RegionName); + reply.Data.SnapshotID = land.SnapshotID; + reply.Data.Dwell = land.Dwell; + reply.Data.SalePrice = land.SalePrice; + reply.Data.AuctionID = (int)land.AuctionID; - OutPacket(loc, ThrottleOutPacketType.Task); + OutPacket(reply, ThrottleOutPacketType.Land); } - #endregion + public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) + { + ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); - #region Primitive Packet/data Sending Methods - - /// - /// - /// - /// - /// - /// - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; + packet.Data.ObjectName = Utils.StringToBytes(objName); + packet.Data.SimName = Utils.StringToBytes(simName); + packet.Data.SimPosition = pos; + packet.Data.LookAt = lookAt; - ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); - // TODO: don't create new blocks if recycling an old packet - attach.AgentData.AgentID = AgentId; - attach.AgentData.SessionID = m_sessionId; - attach.AgentData.AttachmentPoint = attachPoint; - attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; - attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); - attach.ObjectData[0].ObjectLocalID = localID; - attach.ObjectData[0].Rotation = rotation; - attach.Header.Zerocoded = true; - OutPacket(attach, ThrottleOutPacketType.Task); + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, - uint flags, UUID objectID, UUID ownerID, string text, byte[] color, - uint parentID, byte[] particleSystem, byte clickAction, byte material) + public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) { - byte[] textureanim = new byte[0]; - - SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, - acc, rotation, rvel, flags, - objectID, ownerID, text, color, parentID, particleSystem, - clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); - } + DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); - public void SendPrimitiveToClient( - ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, - Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, - uint flags, - UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, - byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) - { + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); - if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) - return; + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + packet.QueryReplies = + new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; - ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); + packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ + data.Length]; - objectData.ID = localID; - objectData.FullID = objectID; - objectData.OwnerID = ownerID; + packet.AgentData.AgentID = AgentId; - objectData.Text = LLUtil.StringToPacketBytes(text); - objectData.TextColor[0] = color[0]; - objectData.TextColor[1] = color[1]; - objectData.TextColor[2] = color[2]; - objectData.TextColor[3] = color[3]; - objectData.ParentID = parentID; - objectData.PSBlock = particleSystem; - objectData.ClickAction = clickAction; - objectData.Material = material; - objectData.Flags = 0; + packet.QueryData[0].QueryID = queryID; - if (attachment) + int i = 0; + foreach (DirPlacesReplyData d in data) { - // Necessary??? - objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); - objectData.JointPivot = new Vector3(0, 0, 0); - - // Item from inventory??? - objectData.NameValue = - Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); - objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); + packet.QueryReplies[i] = + new DirPlacesReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].Dwell = d.dwell; + packet.StatusData[i].Status = d.Status; + i++; } - // Xantor 20080528: Send sound info as well - // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again - objectData.Sound = SoundId; - if (SoundId == UUID.Zero) - { - objectData.OwnerID = UUID.Zero; - objectData.Gain = 0.0f; - objectData.Radius = 0.0f; - objectData.Flags = 0; - } - else - { - objectData.OwnerID = ownerID; - objectData.Gain = (float)SoundGain; - objectData.Radius = (float)SoundRadius; - objectData.Flags = SoundFlags; - } + OutPacket(packet, ThrottleOutPacketType.Task); + } - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); + public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) + { + DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); - byte[] vel = velocity.GetBytes(); - Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); + packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - byte[] rot = rotation.GetBytes(); - Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); + packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - byte[] rvel = rotational_velocity.GetBytes(); - Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); + packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ + data.Length]; - if (textureanim.Length > 0) + int i = 0; + foreach (DirPeopleReplyData d in data) { - objectData.TextureAnim = textureanim; + packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].AgentID = d.agentID; + packet.QueryReplies[i].FirstName = + Utils.StringToBytes(d.firstName); + packet.QueryReplies[i].LastName = + Utils.StringToBytes(d.lastName); + packet.QueryReplies[i].Group = + Utils.StringToBytes(d.group); + packet.QueryReplies[i].Online = d.online; + packet.QueryReplies[i].Reputation = d.reputation; + i++; } - lock (m_primFullUpdates) - { - if (m_primFullUpdates.Count == 0) - m_primFullUpdateTimer.Start(); - - m_primFullUpdates.Add(objectData); - - if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) - ProcessPrimFullUpdates(this, null); - } + OutPacket(packet, ThrottleOutPacketType.Task); } - void HandleQueueEmpty(ThrottleOutPacketType queue) + public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) { - switch (queue) + DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); + + packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ + data.Length]; + + packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ + data.Length]; + + int i = 0; + foreach (DirEventsReplyData d in data) { - case ThrottleOutPacketType.Texture: - ProcessTextureRequests(); - break; + packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].OwnerID = d.ownerID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].EventID = d.eventID; + packet.QueryReplies[i].Date = + Utils.StringToBytes(d.date); + packet.QueryReplies[i].UnixTime = d.unixTime; + packet.QueryReplies[i].EventFlags = d.eventFlags; + packet.StatusData[i].Status = d.Status; + i++; } - } - void ProcessTextureRequests() - { - if (m_imageManager != null) - m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); + OutPacket(packet, ThrottleOutPacketType.Task); } - void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) + public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) { - lock (m_primFullUpdates) - { - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - { - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); - - return; - } + DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); - ObjectUpdatePacket outPacket = - (ObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ObjectUpdate); + packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - int max = m_primFullUpdates.Count; - if (max > m_primFullUpdatesPerPacket) - max = m_primFullUpdatesPerPacket; + packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ + data.Length]; - int count = 0; - int size = 0; + int i = 0; + foreach (DirGroupsReplyData d in data) + { + packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].GroupID = d.groupID; + packet.QueryReplies[i].GroupName = + Utils.StringToBytes(d.groupName); + packet.QueryReplies[i].Members = d.members; + packet.QueryReplies[i].SearchOrder = d.searchOrder; + i++; + } - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + OutPacket(packet, ThrottleOutPacketType.Task); + } - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primFullUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) + { + DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); - outPacket.ObjectData = - new ObjectUpdatePacket.ObjectDataBlock[count]; + packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - for (int index = 0 ; index < count ; index++) - { - outPacket.ObjectData[index] = m_primFullUpdates[0]; - m_primFullUpdates.RemoveAt(0); - } + packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ + data.Length]; + packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ + data.Length]; - if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) - lock (m_primFullUpdateTimer) - m_primFullUpdateTimer.Stop(); + int i = 0; + foreach (DirClassifiedReplyData d in data) + { + packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); + packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); + packet.QueryReplies[i].ClassifiedID = d.classifiedID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; + packet.QueryReplies[i].CreationDate = d.creationDate; + packet.QueryReplies[i].ExpirationDate = d.expirationDate; + packet.QueryReplies[i].PriceForListing = d.price; + packet.StatusData[i].Status = d.Status; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - /// - /// - /// - public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, - Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) + public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; + DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); - ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = - CreatePrimImprovedBlock(localID, position, rotation, - velocity, rotationalvelocity, state); + packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - lock (m_primTerseUpdates) - { - if (m_primTerseUpdates.Count == 0) - m_primTerseUpdateTimer.Start(); + packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - m_primTerseUpdates.Add(objectData); + packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ + data.Length]; - if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) - ProcessPrimTerseUpdates(this, null); + int i = 0; + foreach (DirLandReplyData d in data) + { + packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Auction = d.auction; + packet.QueryReplies[i].ForSale = d.forSale; + packet.QueryReplies[i].SalePrice = d.salePrice; + packet.QueryReplies[i].ActualArea = d.actualArea; + i++; } + + OutPacket(packet, ThrottleOutPacketType.Task); } - void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) + public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) { - lock (m_primTerseUpdates) - { - if (m_primTerseUpdates.Count == 0) - { - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); - - return; - } - - ImprovedTerseObjectUpdatePacket outPacket = - (ImprovedTerseObjectUpdatePacket) - PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); - outPacket.RegionData.RegionHandle = - Scene.RegionInfo.RegionHandle; - outPacket.RegionData.TimeDilation = - (ushort)(Scene.TimeDilation * ushort.MaxValue); + packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - int max = m_primTerseUpdates.Count; - if (max > m_primTerseUpdatesPerPacket) - max = m_primTerseUpdatesPerPacket; + packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; - int count = 0; - int size = 0; + packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ + data.Length]; - byte[] zerobuffer = new byte[1024]; - byte[] blockbuffer = new byte[1024]; + int i = 0; + foreach (DirPopularReplyData d in data) + { + packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); + packet.QueryReplies[i].ParcelID = d.parcelID; + packet.QueryReplies[i].Name = + Utils.StringToBytes(d.name); + packet.QueryReplies[i].Dwell = d.dwell; + i++; + } - for (count = 0 ; count < max ; count++) - { - int length = 0; - m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); - length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); - if (size + length > m_packetMTU) - break; - size += length; - } + OutPacket(packet, ThrottleOutPacketType.Task); + } - outPacket.ObjectData = - new ImprovedTerseObjectUpdatePacket. - ObjectDataBlock[count]; + public void SendEventInfoReply(EventData data) + { + EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); - for (int index = 0 ; index < count ; index++) - { - outPacket.ObjectData[index] = m_primTerseUpdates[0]; - m_primTerseUpdates.RemoveAt(0); - } + packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; - outPacket.Header.Reliable = false; - outPacket.Header.Zerocoded = true; - OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + packet.EventData = new EventInfoReplyPacket.EventDataBlock(); + packet.EventData.EventID = data.eventID; + packet.EventData.Creator = Utils.StringToBytes(data.creator); + packet.EventData.Name = Utils.StringToBytes(data.name); + packet.EventData.Category = Utils.StringToBytes(data.category); + packet.EventData.Desc = Utils.StringToBytes(data.description); + packet.EventData.Date = Utils.StringToBytes(data.date); + packet.EventData.DateUTC = data.dateUTC; + packet.EventData.Duration = data.duration; + packet.EventData.Cover = data.cover; + packet.EventData.Amount = data.amount; + packet.EventData.SimName = Utils.StringToBytes(data.simName); + packet.EventData.GlobalPos = new Vector3d(data.globalPos); + packet.EventData.EventFlags = data.eventFlags; - if (m_primTerseUpdates.Count == 0) - lock (m_primTerseUpdateTimer) - m_primTerseUpdateTimer.Stop(); - } + OutPacket(packet, ThrottleOutPacketType.Task); } - public void FlushPrimUpdates() + public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) { - while (m_primFullUpdates.Count > 0) - { - ProcessPrimFullUpdates(this, null); - } - while (m_primTerseUpdates.Count > 0) - { - ProcessPrimTerseUpdates(this, null); - } - while (m_avatarTerseUpdates.Count > 0) + MapItemReplyPacket mirplk = new MapItemReplyPacket(); + mirplk.AgentData.AgentID = AgentId; + mirplk.RequestData.ItemType = mapitemtype; + mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; + for (int i = 0; i < replies.Length; i++) { - ProcessAvatarTerseUpdates(this, null); + MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); + mrdata.X = replies[i].x; + mrdata.Y = replies[i].y; + mrdata.ID = replies[i].id; + mrdata.Extra = replies[i].Extra; + mrdata.Extra2 = replies[i].Extra2; + mrdata.Name = Utils.StringToBytes(replies[i].name); + mirplk.Data[i] = mrdata; } + //m_log.Debug(mirplk.ToString()); + OutPacket(mirplk, ThrottleOutPacketType.Task); + } - public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) + public void SendOfferCallingCard(UUID srcID, UUID transactionID) { - AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); - newPack.AssetBlock.Type = AssetType; - newPack.AssetBlock.Success = Success; - newPack.AssetBlock.UUID = AssetFullID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + // a bit special, as this uses AgentID to store the source instead + // of the destination. The destination (the receiver) goes into destID + OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); + p.AgentData.AgentID = srcID; + p.AgentData.SessionID = UUID.Zero; + p.AgentBlock.DestID = AgentId; + p.AgentBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) + public void SendAcceptCallingCard(UUID transactionID) { - RequestXferPacket newPack = new RequestXferPacket(); - newPack.XferID.ID = XferID; - newPack.XferID.VFileType = AssetType; - newPack.XferID.VFileID = vFileID; - newPack.XferID.FilePath = FilePath; - newPack.XferID.Filename = FileName; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; + p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); + p.FolderData[0].FolderID = UUID.Zero; + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendConfirmXfer(ulong xferID, uint PacketID) + public void SendDeclineCallingCard(UUID transactionID) { - ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); - newPack.XferID.ID = xferID; - newPack.XferID.Packet = PacketID; - newPack.Header.Zerocoded = true; - OutPacket(newPack, ThrottleOutPacketType.Asset); + DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = UUID.Zero; + p.TransactionBlock.TransactionID = transactionID; + OutPacket(p, ThrottleOutPacketType.Task); } - - public void SendInitiateDownload(string simFileName, string clientFileName) + + public void SendTerminateFriend(UUID exFriendID) { - InitiateDownloadPacket newPack = new InitiateDownloadPacket(); - newPack.AgentData.AgentID = AgentId; - newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); - newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); - OutPacket(newPack, ThrottleOutPacketType.Asset); + TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); + p.AgentData.AgentID = AgentId; + p.AgentData.SessionID = SessionId; + p.ExBlock.OtherID = exFriendID; + OutPacket(p, ThrottleOutPacketType.Task); } - - public void SendImageFirstPart( - ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) + + public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = numParts; - im.ImageID.ID = ImageUUID; + AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); - if (ImageSize > 0) - im.ImageID.Size = ImageSize; + p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; + p.AgentData.AvatarID = avatarID; - im.ImageData.Data = ImageData; - im.ImageID.Codec = imageCodec; - im.Header.Zerocoded = true; - OutPacket(im, ThrottleOutPacketType.Texture); - } + p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; + int i = 0; + foreach (GroupMembershipData m in data) + { + p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); + p.GroupData[i].GroupPowers = m.GroupPowers; + p.GroupData[i].AcceptNotices = m.AcceptNotices; + p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); + p.GroupData[i].GroupID = m.GroupID; + p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); + p.GroupData[i].GroupInsigniaID = m.GroupPicture; + i++; + } - public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) - { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = partNumber; - im.ImageID.ID = imageUuid; - im.ImageData.Data = imageData; + p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); + p.NewGroupData.ListInProfile = true; - OutPacket(im, ThrottleOutPacketType.Texture); + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendImageNotFound(UUID imageid) + public void SendJoinGroupReply(UUID groupID, bool success) { - ImageNotInDatabasePacket notFoundPacket - = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); + JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); - notFoundPacket.ImageID.ID = imageid; + p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); - } + p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; - public void SendShutdownConnectionNotice() - { - OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendSimStats(SimStats stats) + public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) { - SimStatsPacket pack = new SimStatsPacket(); - pack.Region = new SimStatsPacket.RegionBlock(); - pack.Region.RegionX = stats.RegionX; - pack.Region.RegionY = stats.RegionY; - pack.Region.RegionFlags = stats.RegionFlags; - pack.Region.ObjectCapacity = stats.ObjectCapacity; - //pack.Region = //stats.RegionBlock; - pack.Stat = stats.StatsBlock; - - pack.Header.Reliable = false; + EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); - OutPacket(pack, ThrottleOutPacketType.Task); - } + p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = agentID; - public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, - uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, - uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, - UUID LastOwnerID, string ObjectName, string Description) - { - ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); - // TODO: don't create new blocks if recycling an old packet + p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; - ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); - objPropDB.RequestFlags = RequestFlags; - objPropDB.ObjectID = ObjectUUID; - if (OwnerID == GroupID) - objPropDB.OwnerID = UUID.Zero; - else - objPropDB.OwnerID = OwnerID; - objPropDB.GroupID = GroupID; - objPropDB.BaseMask = BaseMask; - objPropDB.OwnerMask = OwnerMask; - objPropDB.GroupMask = GroupMask; - objPropDB.EveryoneMask = EveryoneMask; - objPropDB.NextOwnerMask = NextOwnerMask; + p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); + p.EjectData.Success = success; - // TODO: More properties are needed in SceneObjectPart! - objPropDB.OwnershipCost = OwnershipCost; - objPropDB.SaleType = SaleType; - objPropDB.SalePrice = SalePrice; - objPropDB.Category = Category; - objPropDB.LastOwnerID = LastOwnerID; - objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); - objPropDB.Description = LLUtil.StringToPacketBytes(Description); - objPropFamilyPack.ObjectData = objPropDB; - objPropFamilyPack.Header.Zerocoded = true; - OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); + OutPacket(p, ThrottleOutPacketType.Task); } - public void SendObjectPropertiesReply( - UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, - UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, - UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, - string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, - uint BaseMask, byte saleType, int salePrice) + public void SendLeaveGroupReply(UUID groupID, bool success) { - ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); - // TODO: don't create new blocks if recycling an old packet + LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); - proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; - proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); - proper.ObjectData[0].ItemID = ItemID; - proper.ObjectData[0].CreationDate = CreationDate; - proper.ObjectData[0].CreatorID = CreatorUUID; - proper.ObjectData[0].FolderID = FolderUUID; - proper.ObjectData[0].FromTaskID = FromTaskUUID; - proper.ObjectData[0].GroupID = GroupUUID; - proper.ObjectData[0].InventorySerial = InventorySerial; + p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; - proper.ObjectData[0].LastOwnerID = LastOwnerUUID; - // proper.ObjectData[0].LastOwnerID = UUID.Zero; + p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; - proper.ObjectData[0].ObjectID = ObjectUUID; - if (OwnerUUID == GroupUUID) - proper.ObjectData[0].OwnerID = UUID.Zero; - else - proper.ObjectData[0].OwnerID = OwnerUUID; - proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); - proper.ObjectData[0].TextureID = TextureID; - proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); - proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); - proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); - proper.ObjectData[0].OwnerMask = OwnerMask; - proper.ObjectData[0].NextOwnerMask = NextOwnerMask; - proper.ObjectData[0].GroupMask = GroupMask; - proper.ObjectData[0].EveryoneMask = EveryoneMask; - proper.ObjectData[0].BaseMask = BaseMask; - // proper.ObjectData[0].AggregatePerms = 53; - // proper.ObjectData[0].AggregatePermTextures = 0; - // proper.ObjectData[0].AggregatePermTexturesOwner = 0; - proper.ObjectData[0].SaleType = saleType; - proper.ObjectData[0].SalePrice = salePrice; - proper.Header.Zerocoded = true; - OutPacket(proper, ThrottleOutPacketType.Task); + OutPacket(p, ThrottleOutPacketType.Task); } - #endregion + public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) + { + if (classifiedID.Length != name.Length) + return; - #region Estate Data Sending Methods + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); - private static bool convertParamStringToBool(byte[] field) - { - string s = Utils.BytesToString(field); - if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; + + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; + int i; + for (i = 0; i < classifiedID.Length; i++) { - return true; + ac.Data[i].ClassifiedID = classifiedID[i]; + ac.Data[i].Name = Utils.StringToBytes(name[i]); } - return false; + + OutPacket(ac, ThrottleOutPacketType.Task); } - public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) + public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + ClassifiedInfoReplyPacket cr = + (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ClassifiedInfoReply); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; + cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); + cr.AgentData.AgentID = AgentId; - for (int i = 0; i < (6 + EstateManagers.Length); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); + cr.Data.ClassifiedID = classifiedID; + cr.Data.CreatorID = creatorID; + cr.Data.CreationDate = creationDate; + cr.Data.ExpirationDate = expirationDate; + cr.Data.Category = category; + cr.Data.Name = Utils.StringToBytes(name); + cr.Data.Desc = Utils.StringToBytes(description); + cr.Data.ParcelID = parcelID; + cr.Data.ParentEstate = parentEstate; + cr.Data.SnapshotID = snapshotID; + cr.Data.SimName = Utils.StringToBytes(simName); + cr.Data.PosGlobal = new Vector3d(globalPos); + cr.Data.ParcelName = Utils.StringToBytes(parcelName); + cr.Data.ClassifiedFlags = classifiedFlags; + cr.Data.PriceForListing = price; - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; - for (int i = 0; i < EstateManagers.Length; i++) - { - returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; - } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + OutPacket(cr, ThrottleOutPacketType.Task); } - public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) + public void SendAgentDropGroup(UUID groupID) { - ListBannedUsers = new List(); - - for (int i = 0; i < bl.Length; i++) - { - if (bl[i] == null) - continue; - if (bl[i].BannedUserID == UUID.Zero) - continue; - BannedUsers.Add(bl[i].BannedUserID); - } + AgentDropGroupPacket dg = + (AgentDropGroupPacket)PacketPool.Instance.GetPacket( + PacketType.AgentDropGroup); - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); + dg.AgentData.AgentID = AgentId; + dg.AgentData.GroupID = groupID; - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + OutPacket(dg, ThrottleOutPacketType.Task); + } - for (int i = 0; i < (6 + BannedUsers.Count); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + public void SendAvatarNotesReply(UUID targetID, string text) + { + AvatarNotesReplyPacket an = + (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarNotesReply); - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); + an.AgentData.AgentID = AgentId; - foreach (UUID banned in BannedUsers) + an.Data = new AvatarNotesReplyPacket.DataBlock(); + an.Data.TargetID = targetID; + an.Data.Notes = Utils.StringToBytes(text); + + OutPacket(an, ThrottleOutPacketType.Task); + } + + public void SendAvatarPicksReply(UUID targetID, Dictionary picks) + { + AvatarPicksReplyPacket ap = + (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarPicksReply); + + ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); + ap.AgentData.AgentID = AgentId; + ap.AgentData.TargetID = targetID; + + ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; + + int i = 0; + foreach (KeyValuePair pick in picks) { - returnblock[j].Parameter = banned.GetBytes(); j++; + ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); + ap.Data[i].PickID = pick.Key; + ap.Data[i].PickName = Utils.StringToBytes(pick.Value); + i++; } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + + OutPacket(ap, ThrottleOutPacketType.Task); } - public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) + public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) { - RegionInfoPacket rinfopack = new RegionInfoPacket(); - RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; - rinfoblk.BillableFactor = args.billableFactor; - rinfoblk.EstateID = args.estateID; - rinfoblk.MaxAgents = args.maxAgents; - rinfoblk.ObjectBonusFactor = args.objectBonusFactor; - rinfoblk.ParentEstateID = args.parentEstateID; - rinfoblk.PricePerMeter = args.pricePerMeter; - rinfoblk.RedirectGridX = args.redirectGridX; - rinfoblk.RedirectGridY = args.redirectGridY; - rinfoblk.RegionFlags = args.regionFlags; - rinfoblk.SimAccess = args.simAccess; - rinfoblk.SunHour = args.sunHour; - rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; - rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; - rinfoblk.UseEstateSun = args.useEstateSun; - rinfoblk.WaterHeight = args.waterHeight; - rinfoblk.SimName = Utils.StringToBytes(args.simName); - - rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); - rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; - rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; - rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; - rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; - rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; + AvatarClassifiedReplyPacket ac = + (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( + PacketType.AvatarClassifiedReply); - rinfopack.HasVariableBlocks = true; - rinfopack.RegionInfo = rinfoblk; - rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); - rinfopack.AgentData.AgentID = AgentId; - rinfopack.AgentData.SessionID = SessionId; + ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); + ac.AgentData.AgentID = AgentId; + ac.AgentData.TargetID = targetID; + ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; - OutPacket(rinfopack, ThrottleOutPacketType.Task); + int i = 0; + foreach (KeyValuePair classified in classifieds) + { + ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); + ac.Data[i].ClassifiedID = classified.Key; + ac.Data[i].Name = Utils.StringToBytes(classified.Value); + i++; + } + + OutPacket(ac, ThrottleOutPacketType.Task); } - public void SendEstateCovenantInformation(UUID covenant) + public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) { - EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); - EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); - edata.CovenantID = covenant; - edata.CovenantTimestamp = 0; - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); - einfopack.Data = edata; - OutPacket(einfopack, ThrottleOutPacketType.Task); + ParcelDwellReplyPacket pd = + (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( + PacketType.ParcelDwellReply); + + pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); + pd.AgentData.AgentID = AgentId; + + pd.Data = new ParcelDwellReplyPacket.DataBlock(); + pd.Data.LocalID = localID; + pd.Data.ParcelID = parcelID; + pd.Data.Dwell = dwell; + + OutPacket(pd, ThrottleOutPacketType.Land); } - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) + public void SendUserInfoReply(bool imViaEmail, bool visible, string email) { - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.MethodData.Invoice = invoice; - packet.AgentData.TransactionID = UUID.Random(); - packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; + UserInfoReplyPacket ur = + (UserInfoReplyPacket)PacketPool.Instance.GetPacket( + PacketType.UserInfoReply); - for (int i = 0; i < 10; i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } + string Visible = "hidden"; + if (visible) + Visible = "default"; - //Sending Estate Settings - returnblock[0].Parameter = Utils.StringToBytes(estateName); - // TODO: remove this cruft once MasterAvatar is fully deprecated - // - returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); - returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); + ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); + ur.AgentData.AgentID = AgentId; - returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); - returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); - returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); - returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); - returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? - returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? - returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); + ur.UserData = new UserInfoReplyPacket.UserDataBlock(); + ur.UserData.IMViaEMail = imViaEmail; + ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); + ur.UserData.EMail = Utils.StringToBytes(email); - packet.ParamList = returnblock; - packet.Header.Reliable = false; - //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); - OutPacket(packet, ThrottleOutPacketType.Task); + OutPacket(ur, ThrottleOutPacketType.Task); } - #endregion + public void SendCreateGroupReply(UUID groupID, bool success, string message) + { + CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); - #region Land Data Sending Methods + createGroupReply.AgentData = + new CreateGroupReplyPacket.AgentDataBlock(); + createGroupReply.ReplyData = + new CreateGroupReplyPacket.ReplyDataBlock(); - public void SendLandParcelOverlay(byte[] data, int sequence_id) - { - ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); - packet.ParcelData.Data = data; - packet.ParcelData.SequenceID = sequence_id; - packet.Header.Zerocoded = true; - OutPacket(packet, ThrottleOutPacketType.Task); + createGroupReply.AgentData.AgentID = AgentId; + createGroupReply.ReplyData.GroupID = groupID; + + createGroupReply.ReplyData.Success = success; + createGroupReply.ReplyData.Message = Utils.StringToBytes(message); + OutPacket(createGroupReply, ThrottleOutPacketType.Task); } - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + public void SendUseCachedMuteList() { - ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); - // TODO: don't create new blocks if recycling an old packet + UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); - updatePacket.ParcelData.AABBMax = landData.AABBMax; - updatePacket.ParcelData.AABBMin = landData.AABBMin; - updatePacket.ParcelData.Area = landData.Area; - updatePacket.ParcelData.AuctionID = landData.AuctionID; - updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; + useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); + useCachedMuteList.AgentData.AgentID = AgentId; - updatePacket.ParcelData.Bitmap = landData.Bitmap; + OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); + } - updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); - updatePacket.ParcelData.Category = (byte)landData.Category; - updatePacket.ParcelData.ClaimDate = landData.ClaimDate; - updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; - updatePacket.ParcelData.GroupID = landData.GroupID; - updatePacket.ParcelData.GroupPrims = landData.GroupPrims; - updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; - updatePacket.ParcelData.LandingType = landData.LandingType; - updatePacket.ParcelData.LocalID = landData.LocalID; + public void SendMuteListUpdate(string filename) + { + MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); - if (landData.Area > 0) - { - updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; - } - else - { - updatePacket.ParcelData.MaxPrims = 0; - } + muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); + muteListUpdate.MuteData.AgentID = AgentId; + muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); - updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; - updatePacket.ParcelData.MediaID = landData.MediaID; - updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); - updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); - updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); - updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; - updatePacket.ParcelData.OtherCount = 0; //unemplemented - updatePacket.ParcelData.OtherPrims = landData.OtherPrims; - updatePacket.ParcelData.OwnerID = landData.OwnerID; - updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; - updatePacket.ParcelData.ParcelFlags = landData.Flags; - updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; - updatePacket.ParcelData.PassHours = landData.PassHours; - updatePacket.ParcelData.PassPrice = landData.PassPrice; - updatePacket.ParcelData.PublicCount = 0; //unemplemented + OutPacket(muteListUpdate, ThrottleOutPacketType.Task); + } - updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > - 0); - updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > - 0); - updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) > - 0); - updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) > - 0); + public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) + { + PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); - updatePacket.ParcelData.RentPrice = 0; - updatePacket.ParcelData.RequestResult = request_result; - updatePacket.ParcelData.SalePrice = landData.SalePrice; - updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; - updatePacket.ParcelData.SelfCount = 0; //unemplemented - updatePacket.ParcelData.SequenceID = sequence_id; - if (landData.SimwideArea > 0) - { - updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; - } - else - { - updatePacket.ParcelData.SimWideMaxPrims = 0; - } - updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; - updatePacket.ParcelData.SnapSelection = snap_selection; - updatePacket.ParcelData.SnapshotID = landData.SnapshotID; - updatePacket.ParcelData.Status = (byte)landData.Status; - updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + - landData.SelectedPrims; - updatePacket.ParcelData.UserLocation = landData.UserLocation; - updatePacket.ParcelData.UserLookAt = landData.UserLookAt; - updatePacket.Header.Zerocoded = true; + pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); + pickInfoReply.AgentData.AgentID = AgentId; - try - { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - eq.ParcelProperties(updatePacket, this.AgentId); - } - } - catch (Exception ex) - { - m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending parcel data via UDP"); - OutPacket(updatePacket, ThrottleOutPacketType.Task); - } + pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); + pickInfoReply.Data.PickID = pickID; + pickInfoReply.Data.CreatorID = creatorID; + pickInfoReply.Data.TopPick = topPick; + pickInfoReply.Data.ParcelID = parcelID; + pickInfoReply.Data.Name = Utils.StringToBytes(name); + pickInfoReply.Data.Desc = Utils.StringToBytes(desc); + pickInfoReply.Data.SnapshotID = snapshotID; + pickInfoReply.Data.User = Utils.StringToBytes(user); + pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); + pickInfoReply.Data.SimName = Utils.StringToBytes(simName); + pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); + pickInfoReply.Data.SortOrder = sortOrder; + pickInfoReply.Data.Enabled = enabled; + + OutPacket(pickInfoReply, ThrottleOutPacketType.Task); } - public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) - { - ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); - replyPacket.Data.AgentID = AgentId; - replyPacket.Data.Flags = accessFlag; - replyPacket.Data.LocalID = localLandID; - replyPacket.Data.SequenceID = 0; + #endregion Scene/Avatar to Client - List list = new List(); - foreach (UUID avatar in avatars) - { - ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); - block.Flags = accessFlag; - block.ID = avatar; - block.Time = 0; - list.Add(block); - } + // Gesture - replyPacket.List = list.ToArray(); - replyPacket.Header.Zerocoded = true; - OutPacket(replyPacket, ThrottleOutPacketType.Task); - } + #region Appearance/ Wearables Methods - public void SendForceClientSelectObjects(List ObjectIDs) + public void SendWearables(AvatarWearable[] wearables, int serial) { - bool firstCall = true; - const int MAX_OBJECTS_PER_PACKET = 251; - ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); - ForceObjectSelectPacket.DataBlock[] data; - while (ObjectIDs.Count > 0) - { - if (firstCall) - { - pack._Header.ResetList = true; - firstCall = false; - } - else - { - pack._Header.ResetList = false; - } + AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); + aw.AgentData.AgentID = AgentId; + aw.AgentData.SerialNum = (uint)serial; + aw.AgentData.SessionID = m_sessionId; - if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) - { - data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; - } - else - { - data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; - } + // TODO: don't create new blocks if recycling an old packet + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + for (int i = 0; i < wearables.Length; i++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = wearables[i].AssetID; + awb.ItemID = wearables[i].ItemID; + aw.WearableData[i] = awb; - int i; - for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) - { - data[i] = new ForceObjectSelectPacket.DataBlock(); - data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); - ObjectIDs.RemoveAt(0); - } - pack.Data = data; - pack.Header.Zerocoded = true; - OutPacket(pack, ThrottleOutPacketType.Task); +// m_log.DebugFormat( +// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", +// awb.ItemID, awb.AssetID, i, Name); } - } - public void SendCameraConstraint(Vector4 ConstraintPlane) - { - CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); - cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); - cpack.CameraCollidePlane.Plane = ConstraintPlane; - //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); - OutPacket(cpack, ThrottleOutPacketType.Task); + OutPacket(aw, ThrottleOutPacketType.Task); } - public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) + public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { - - - int notifyCount = ownersAndCount.Count; - ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); + AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); + // TODO: don't create new blocks if recycling an old packet + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + avp.ObjectData.TextureEntry = textureEntry; - if (notifyCount > 0) + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) { - if (notifyCount > 32) - { - m_log.InfoFormat( - "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" - + " - a developer might want to investigate whether this is a hard limit", 32); - - notifyCount = 32; - } - - ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock - = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; - - int num = 0; - foreach (UUID owner in ownersAndCount.Keys) - { - dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); - dataBlock[num].Count = ownersAndCount[owner]; + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; + } - if (land.GroupID == owner || groups.Contains(owner)) - dataBlock[num].IsGroupOwned = true; + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + OutPacket(avp, ThrottleOutPacketType.Task); + } - dataBlock[num].OnlineStatus = true; //TODO: fix me later - dataBlock[num].OwnerID = owner; + public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + { + //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); - num++; + AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); + // TODO: don't create new blocks if recycling an old packet + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = sourceAgentId; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; + ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; - if (num >= notifyCount) - { - break; - } - } + for (int i = 0; i < animations.Length; ++i) + { + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; - pack.Data = dataBlock; + ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[i].ObjectID = objectIDs[i]; + if (objectIDs[i] == UUID.Zero) + ani.AnimationSourceList[i].ObjectID = sourceAgentId; } - pack.Header.Zerocoded = true; - this.OutPacket(pack, ThrottleOutPacketType.Task); + ani.Header.Reliable = false; + OutPacket(ani, ThrottleOutPacketType.Task); } #endregion - #region Helper Methods + #region Avatar Packet/data sending Methods - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, - Vector3 velocity, - Quaternion rotation) + /// + /// send a objectupdate packet with information about the clients avatar + /// + public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, + uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) { - byte[] bytes = new byte[60]; - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + objupdate.RegionData.RegionHandle = regionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); - dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatarLocalID; + objupdate.ObjectData[0].FullID = avatarID; + objupdate.ObjectData[0].ParentID = parentID; + objupdate.ObjectData[0].NameValue = + Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); - uint ID = localID; + Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = 0; - bytes[i++] = 1; - i += 14; - bytes[i++] = 128; - bytes[i++] = 63; + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); - byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; + objupdate.Header.Zerocoded = true; + OutPacket(objupdate, ThrottleOutPacketType.Task); + } - Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); + /// + /// Send a terse positional/rotation/velocity update about an avatar + /// to the client. This avatar can be that of the client itself. + /// + public virtual void SendAvatarTerseUpdate(ulong regionHandle, + ushort timeDilation, uint localID, Vector3 position, + Vector3 velocity, Quaternion rotation, UUID agentid) + { + if (rotation.X == rotation.Y && + rotation.Y == rotation.Z && + rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - internDirec = internDirec / 128.0f; - internDirec.X += 1; - internDirec.Y += 1; - internDirec.Z += 1; - - ushort InternVelocityX = (ushort)(32768 * internDirec.X); - ushort InternVelocityY = (ushort)(32768 * internDirec.Y); - ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); - - ushort ac = 32767; - bytes[i++] = (byte)(InternVelocityX % 256); - bytes[i++] = (byte)((InternVelocityX >> 8) % 256); - bytes[i++] = (byte)(InternVelocityY % 256); - bytes[i++] = (byte)((InternVelocityY >> 8) % 256); - bytes[i++] = (byte)(InternVelocityZ % 256); - bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = + CreateAvatarImprovedBlock(localID, position, velocity,rotation); + + lock (m_avatarTerseUpdates) + { + m_avatarTerseUpdates.Add(terseBlock); - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + // If packet is full or own movement packet, send it. + if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) + { + ProcessAvatarTerseUpdates(this, null); + } + else if (m_avatarTerseUpdates.Count == 1) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Start(); + } + } + } - //rotation - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) + { + lock (m_avatarTerseUpdates) + { + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); - //rotation vel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; + terse.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - dat.Data = bytes; + int max = m_avatarTerseUpdatesPerPacket; + if (max > m_avatarTerseUpdates.Count) + max = m_avatarTerseUpdates.Count; - return (dat); - } + int count = 0; + int size = 0; - /// - /// - /// - /// - /// - /// - /// - protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, - Vector3 position, - Quaternion rotation, - Vector3 velocity, - Vector3 rotationalvelocity, - byte state) - { - uint ID = localID; - byte[] bytes = new byte[60]; + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; - int i = 0; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - dat.TextureEntry = new byte[0]; - bytes[i++] = (byte)(ID % 256); - bytes[i++] = (byte)((ID >> 8) % 256); - bytes[i++] = (byte)((ID >> 16) % 256); - bytes[i++] = (byte)((ID >> 24) % 256); - bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); - bytes[i++] = 0; + for (count = 0 ; count < max ; count++) + { + int length = 0; + m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; + } - byte[] pb = position.GetBytes(); - Array.Copy(pb, 0, bytes, i, pb.Length); - i += 12; - ushort ac = 32767; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; - ushort velx, vely, velz; - Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); + for (int i = 0 ; i < count ; i++) + { + terse.ObjectData[i] = m_avatarTerseUpdates[0]; + m_avatarTerseUpdates.RemoveAt(0); + } - vel = vel / 128.0f; - vel.X += 1; - vel.Y += 1; - vel.Z += 1; - //vel - velx = (ushort)(32768 * (vel.X)); - vely = (ushort)(32768 * (vel.Y)); - velz = (ushort)(32768 * (vel.Z)); + terse.Header.Reliable = false; + terse.Header.Zerocoded = true; + OutPacket(terse, ThrottleOutPacketType.Task); - bytes[i++] = (byte)(velx % 256); - bytes[i++] = (byte)((velx >> 8) % 256); - bytes[i++] = (byte)(vely % 256); - bytes[i++] = (byte)((vely >> 8) % 256); - bytes[i++] = (byte)(velz % 256); - bytes[i++] = (byte)((velz >> 8) % 256); + if (m_avatarTerseUpdates.Count == 0) + { + lock (m_avatarTerseUpdateTimer) + m_avatarTerseUpdateTimer.Stop(); + } + } + } - //accel - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); - bytes[i++] = (byte)(ac % 256); - bytes[i++] = (byte)((ac >> 8) % 256); + public void SendCoarseLocationUpdate(List users, List CoarseLocations) + { + if (!IsActive) return; // We don't need to update inactive clients. - ushort rw, rx, ry, rz; - rw = (ushort)(32768 * (rotation.W + 1)); - rx = (ushort)(32768 * (rotation.X + 1)); - ry = (ushort)(32768 * (rotation.Y + 1)); - rz = (ushort)(32768 * (rotation.Z + 1)); + CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); + // TODO: don't create new blocks if recycling an old packet + int total = CoarseLocations.Count; + CoarseLocationUpdatePacket.IndexBlock ib = + new CoarseLocationUpdatePacket.IndexBlock(); + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; - //rot - bytes[i++] = (byte)(rx % 256); - bytes[i++] = (byte)((rx >> 8) % 256); - bytes[i++] = (byte)(ry % 256); - bytes[i++] = (byte)((ry >> 8) % 256); - bytes[i++] = (byte)(rz % 256); - bytes[i++] = (byte)((rz >> 8) % 256); - bytes[i++] = (byte)(rw % 256); - bytes[i++] = (byte)((rw >> 8) % 256); + for (int i = 0; i < total; i++) + { + CoarseLocationUpdatePacket.LocationBlock lb = + new CoarseLocationUpdatePacket.LocationBlock(); + lb.X = (byte)CoarseLocations[i].X; + lb.Y = (byte)CoarseLocations[i].Y; - //rotation vel - Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); + lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); + loc.Location[i] = lb; + loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); + loc.AgentData[i].AgentID = users[i]; + } + ib.You = -1; + ib.Prey = -1; + loc.Index = ib; + loc.Header.Reliable = false; + loc.Header.Zerocoded = true; - rvel = rvel / 128.0f; - rvel.X += 1; - rvel.Y += 1; - rvel.Z += 1; - //vel - ushort rvelx = (ushort)(32768 * (rvel.X)); - ushort rvely = (ushort)(32768 * (rvel.Y)); - ushort rvelz = (ushort)(32768 * (rvel.Z)); + OutPacket(loc, ThrottleOutPacketType.Task); + } - bytes[i++] = (byte)(rvelx % 256); - bytes[i++] = (byte)((rvelx >> 8) % 256); - bytes[i++] = (byte)(rvely % 256); - bytes[i++] = (byte)((rvely >> 8) % 256); - bytes[i++] = (byte)(rvelz % 256); - bytes[i++] = (byte)((rvelz >> 8) % 256); - dat.Data = bytes; + #endregion - return dat; - } + #region Primitive Packet/data Sending Methods /// - /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// /// - /// - /// - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + /// + /// + /// + public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) { - ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); - SetDefaultPrimPacketValues(objupdate); - objupdate.UpdateFlags = flags; - SetPrimPacketShapeData(objupdate, primShape); + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; - if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) - { - objupdate.Data = new byte[1]; - objupdate.Data[0] = primShape.State; - } - return objupdate; + ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); + // TODO: don't create new blocks if recycling an old packet + attach.AgentData.AgentID = AgentId; + attach.AgentData.SessionID = m_sessionId; + attach.AgentData.AttachmentPoint = attachPoint; + attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; + attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); + attach.ObjectData[0].ObjectLocalID = localID; + attach.ObjectData[0].Rotation = rotation; + attach.Header.Zerocoded = true; + OutPacket(attach, ThrottleOutPacketType.Task); } - protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) - { - objectData.TextureEntry = primData.TextureEntry; - objectData.PCode = primData.PCode; - objectData.State = primData.State; - objectData.PathBegin = primData.PathBegin; - objectData.PathEnd = primData.PathEnd; - objectData.PathScaleX = primData.PathScaleX; - objectData.PathScaleY = primData.PathScaleY; - objectData.PathShearX = primData.PathShearX; - objectData.PathShearY = primData.PathShearY; - objectData.PathSkew = primData.PathSkew; - objectData.ProfileBegin = primData.ProfileBegin; - objectData.ProfileEnd = primData.ProfileEnd; - objectData.Scale = primData.Scale; - objectData.PathCurve = primData.PathCurve; - objectData.ProfileCurve = primData.ProfileCurve; - objectData.ProfileHollow = primData.ProfileHollow; - objectData.PathRadiusOffset = primData.PathRadiusOffset; - objectData.PathRevolutions = primData.PathRevolutions; - objectData.PathTaperX = primData.PathTaperX; - objectData.PathTaperY = primData.PathTaperY; - objectData.PathTwist = primData.PathTwist; - objectData.PathTwistBegin = primData.PathTwistBegin; - objectData.ExtraParams = primData.ExtraParams; - } - - /// - /// Set some default values in a ObjectUpdatePacket - /// - /// - protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, + uint flags, UUID objectID, UUID ownerID, string text, byte[] color, + uint parentID, byte[] particleSystem, byte clickAction, byte material) { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 3; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - objdata.State = 0; - objdata.Data = new byte[0]; + byte[] textureanim = new byte[0]; - objdata.ObjectData = new byte[60]; - objdata.ObjectData[46] = 128; - objdata.ObjectData[47] = 63; + SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, + acc, rotation, rvel, flags, + objectID, ownerID, text, color, parentID, particleSystem, + clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0); } - /// - /// - /// - /// - public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity, + uint flags, + UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, + byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) { - ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); - // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - SetDefaultAvatarPacketValues(ref objdata); - objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); - objdata.PathCurve = 16; - objdata.ProfileCurve = 1; - objdata.PathScaleX = 100; - objdata.PathScaleY = 100; - objdata.ParentID = 0; - objdata.OwnerID = UUID.Zero; - objdata.Scale = new Vector3(1, 1, 1); - objdata.PCode = (byte)PCode.Avatar; - if (textureEntry != null) + if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; + if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) + return; + + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; + + ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); + + objectData.ID = localID; + objectData.FullID = objectID; + objectData.OwnerID = ownerID; + + objectData.Text = Util.StringToBytes256(text); + objectData.TextColor[0] = color[0]; + objectData.TextColor[1] = color[1]; + objectData.TextColor[2] = color[2]; + objectData.TextColor[3] = color[3]; + objectData.ParentID = parentID; + objectData.PSBlock = particleSystem; + objectData.ClickAction = clickAction; + objectData.Material = material; + objectData.Flags = 0; + + if (attachment) { - objdata.TextureEntry = textureEntry; + // Necessary??? + objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); + objectData.JointPivot = new Vector3(0, 0, 0); + + // Item from inventory??? + objectData.NameValue = + Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); + objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); } - Vector3 pos = new Vector3(objdata.ObjectData, 16); - pos.X = 100f; - objdata.ID = 8880000; - objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); - //Vector3 pos2 = new Vector3(100f, 100f, 23f); - //objdata.FullID=user.AgentId; + + // Xantor 20080528: Send sound info as well + // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again + objectData.Sound = SoundId; + if (SoundId == UUID.Zero) + { + objectData.OwnerID = UUID.Zero; + objectData.Gain = 0.0f; + objectData.Radius = 0.0f; + objectData.Flags = 0; + } + else + { + objectData.OwnerID = ownerID; + objectData.Gain = (float)SoundGain; + objectData.Radius = (float)SoundRadius; + objectData.Flags = SoundFlags; + } + byte[] pb = pos.GetBytes(); - Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); - return objdata; - } + byte[] vel = velocity.GetBytes(); + Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); - /// - /// - /// - /// - protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) - { - objdata.PSBlock = new byte[0]; - objdata.ExtraParams = new byte[1]; - objdata.MediaURL = new byte[0]; - objdata.NameValue = new byte[0]; - objdata.Text = new byte[0]; - objdata.TextColor = new byte[4]; - objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); - objdata.JointPivot = new Vector3(0, 0, 0); - objdata.Material = 4; - objdata.TextureAnim = new byte[0]; - objdata.Sound = UUID.Zero; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); - objdata.TextureEntry = ntex.GetBytes(); + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); - objdata.State = 0; - objdata.Data = new byte[0]; + byte[] rvel = rotational_velocity.GetBytes(); + Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); - objdata.ObjectData = new byte[76]; - objdata.ObjectData[15] = 128; - objdata.ObjectData[16] = 63; - objdata.ObjectData[56] = 128; - objdata.ObjectData[61] = 102; - objdata.ObjectData[62] = 40; - objdata.ObjectData[63] = 61; - objdata.ObjectData[64] = 189; - } + if (textureanim.Length > 0) + { + objectData.TextureAnim = textureanim; + } - public void SendNameReply(UUID profileId, string firstname, string lastname) - { - UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); - // TODO: don't create new blocks if recycling an old packet - packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; - packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); - packet.UUIDNameBlock[0].ID = profileId; - packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); - packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); + lock (m_primFullUpdates) + { + if (m_primFullUpdates.Count == 0) + m_primFullUpdateTimer.Start(); - OutPacket(packet, ThrottleOutPacketType.Task); + m_primFullUpdates.Add(objectData); + + if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) + ProcessPrimFullUpdates(this, null); + } } - #endregion + void HandleQueueEmpty(ThrottleOutPacketType queue) + { + switch (queue) + { + case ThrottleOutPacketType.Texture: + ProcessTextureRequests(); + break; + } + } - /// - /// This is a different way of processing packets then ProcessInPacket - /// - protected virtual void RegisterLocalPacketHandlers() + void ProcessTextureRequests() { - AddLocalPacketHandler(PacketType.LogoutRequest, Logout); - AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); - AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); - AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); - AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); - AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); - AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); + if (m_imageManager != null) + m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); } - private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) + void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) { - MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; - // validate the agent owns the agentID and sessionID - if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && - money.AgentData.SessionID == sender.SessionId) + lock (m_primFullUpdates) { - handlerMoneyTransferRequest = OnMoneyTransferRequest; - if (handlerMoneyTransferRequest != null) + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) { - handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, - money.MoneyData.Amount, money.MoneyData.TransactionType, - Util.FieldToString(money.MoneyData.Description)); + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + + return; } - return true; - } + ObjectUpdatePacket outPacket = + (ObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ObjectUpdate); - return false; - } + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); - private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) - { - ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; - if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) - { - handlerParcelBuy = OnParcelBuy; - if (handlerParcelBuy != null) + int max = m_primFullUpdates.Count; + if (max > m_primFullUpdatesPerPacket) + max = m_primFullUpdatesPerPacket; + + int count = 0; + int size = 0; + + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + + for (count = 0 ; count < max ; count++) { - handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, - parcel.Data.IsGroupOwned, - parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, - parcel.ParcelData.Price, - false); + int length = 0; + m_primFullUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; } - return true; - } - return false; - } - private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) - { - UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; - + outPacket.ObjectData = + new ObjectUpdatePacket.ObjectDataBlock[count]; - for (int i = 0; i < upack.UUIDNameBlock.Length; i++) - { - handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; - if (handlerUUIDGroupNameRequest != null) + for (int index = 0 ; index < count ; index++) { - handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); + outPacket.ObjectData[index] = m_primFullUpdates[0]; + m_primFullUpdates.RemoveAt(0); } - } - return true; + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task); + + if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) + lock (m_primFullUpdateTimer) + m_primFullUpdateTimer.Stop(); + } } - public bool HandleGenericMessage(IClientAPI sender, Packet pack) + /// + /// + /// + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, + Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) { - GenericMessagePacket gmpack = (GenericMessagePacket) pack; - if (m_genericPacketHandlers.Count == 0) return false; - if (gmpack.AgentData.SessionID != SessionId) return false; + if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD + return; - handlerGenericMessage = null; + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) + rotation = Quaternion.Identity; - string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = + CreatePrimImprovedBlock(localID, position, rotation, + velocity, rotationalvelocity, state); - if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) + lock (m_primTerseUpdates) { - List msg = new List(); - List msgBytes = new List(); + if (m_primTerseUpdates.Count == 0) + m_primTerseUpdateTimer.Start(); - if (handlerGenericMessage != null) - { - foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) - { - msg.Add(Util.FieldToString(block.Parameter)); - msgBytes.Add(block.Parameter); - } - try - { - if (OnBinaryGenericMessage != null) - { - OnBinaryGenericMessage(this, method, msgBytes.ToArray()); - } - handlerGenericMessage(sender, method, msg); - return true; - } - catch (Exception e) - { - m_log.Error("[GENERICMESSAGE] " + e); - } - } + m_primTerseUpdates.Add(objectData); + + if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) + ProcessPrimTerseUpdates(this, null); } - m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); - return false; } - public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) + void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) { - - ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; - if (ogpack.AgentData.SessionID != SessionId) return false; - - handlerObjectGroupRequest = OnObjectGroupRequest; - if (handlerObjectGroupRequest != null) + lock (m_primTerseUpdates) { - for (int i = 0; i < ogpack.ObjectData.Length; i++) + if (m_primTerseUpdates.Count == 0) { - handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); + + return; } - } - return true; - } - private bool HandleViewerEffect(IClientAPI sender, Packet Pack) - { - ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; - if (viewer.AgentData.SessionID != SessionId) return false; - handlerViewerEffect = OnViewerEffect; - if (handlerViewerEffect != null) - { - int length = viewer.Effect.Length; - List args = new List(length); - for (int i = 0; i < length; i++) + ImprovedTerseObjectUpdatePacket outPacket = + (ImprovedTerseObjectUpdatePacket) + PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + + outPacket.RegionData.RegionHandle = + Scene.RegionInfo.RegionHandle; + outPacket.RegionData.TimeDilation = + (ushort)(Scene.TimeDilation * ushort.MaxValue); + + int max = m_primTerseUpdates.Count; + if (max > m_primTerseUpdatesPerPacket) + max = m_primTerseUpdatesPerPacket; + + int count = 0; + int size = 0; + + byte[] zerobuffer = new byte[1024]; + byte[] blockbuffer = new byte[1024]; + + for (count = 0 ; count < max ; count++) { - //copy the effects block arguments into the event handler arg. - ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); - argument.AgentID = viewer.Effect[i].AgentID; - argument.Color = viewer.Effect[i].Color; - argument.Duration = viewer.Effect[i].Duration; - argument.ID = viewer.Effect[i].ID; - argument.Type = viewer.Effect[i].Type; - argument.TypeData = viewer.Effect[i].TypeData; - args.Add(argument); + int length = 0; + m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); + length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); + if (size + length > m_packetMTU) + break; + size += length; } - handlerViewerEffect(sender, args); - } + outPacket.ObjectData = + new ImprovedTerseObjectUpdatePacket. + ObjectDataBlock[count]; - return true; - } + for (int index = 0 ; index < count ; index++) + { + outPacket.ObjectData[index] = m_primTerseUpdates[0]; + m_primTerseUpdates.RemoveAt(0); + } - public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) - { - ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); - scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); - // TODO: don't create new blocks if recycling an old packet - scriptQuestion.Data.TaskID = taskID; - scriptQuestion.Data.ItemID = itemID; - scriptQuestion.Data.Questions = question; - scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); - scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); + outPacket.Header.Reliable = false; + outPacket.Header.Zerocoded = true; + OutPacket(outPacket, ThrottleOutPacketType.Task); - OutPacket(scriptQuestion, ThrottleOutPacketType.Task); + if (m_primTerseUpdates.Count == 0) + lock (m_primTerseUpdateTimer) + m_primTerseUpdateTimer.Stop(); + } } - private void InitDefaultAnimations() + public void FlushPrimUpdates() { - using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) + while (m_primFullUpdates.Count > 0) { - XmlDocument doc = new XmlDocument(); - doc.Load(reader); - if (doc.DocumentElement != null) - foreach (XmlNode nod in doc.DocumentElement.ChildNodes) - { - if (nod.Attributes["name"] != null) - { - string name = nod.Attributes["name"].Value.ToLower(); - string id = nod.InnerText; - m_defaultAnimations.Add(name, (UUID)id); - } - } + ProcessPrimFullUpdates(this, null); + } + while (m_primTerseUpdates.Count > 0) + { + ProcessPrimTerseUpdates(this, null); + } + while (m_avatarTerseUpdates.Count > 0) + { + ProcessAvatarTerseUpdates(this, null); } } - public UUID GetDefaultAnimation(string name) + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) { - if (m_defaultAnimations.ContainsKey(name)) - return m_defaultAnimations[name]; - return UUID.Zero; + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = AssetType; + newPack.AssetBlock.Success = Success; + newPack.AssetBlock.UUID = AssetFullID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - /// - /// Handler called when we receive a logout packet. - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client, Packet packet) + public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) { - if (packet.Type == PacketType.LogoutRequest) - { - if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; - } - - return Logout(client); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = AssetType; + newPack.XferID.VFileID = vFileID; + newPack.XferID.FilePath = FilePath; + newPack.XferID.Filename = FileName; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); } - /// - /// - /// - /// - /// - protected virtual bool Logout(IClientAPI client) + public void SendConfirmXfer(ulong xferID, uint PacketID) { - m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); - - handlerLogout = OnLogout; + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = PacketID; + newPack.Header.Zerocoded = true; + OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + public void SendInitiateDownload(string simFileName, string clientFileName) + { + InitiateDownloadPacket newPack = new InitiateDownloadPacket(); + newPack.AgentData.AgentID = AgentId; + newPack.FileData.SimFilename = Utils.StringToBytes(simFileName); + newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); + OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + public void SendImageFirstPart( + ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = numParts; + im.ImageID.ID = ImageUUID; - if (handlerLogout != null) - { - handlerLogout(client); - } + if (ImageSize > 0) + im.ImageID.Size = ImageSize; - return true; + im.ImageData.Data = ImageData; + im.ImageID.Codec = imageCodec; + im.Header.Zerocoded = true; + OutPacket(im, ThrottleOutPacketType.Texture); } - /// - /// Send a response back to a client when it asks the asset server (via the region server) if it has - /// its appearance texture cached. - /// - /// At the moment, we always reply that there is no cached texture. - /// - /// - /// - /// - protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) { - //m_log.Debug("texture cached: " + packet.ToString()); - AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; - AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = partNumber; + im.ImageID.ID = imageUuid; + im.ImageData.Data = imageData; - if (cachedtex.AgentData.SessionID != SessionId) return false; + OutPacket(im, ThrottleOutPacketType.Texture); + } - // TODO: don't create new blocks if recycling an old packet - cachedresp.AgentData.AgentID = AgentId; - cachedresp.AgentData.SessionID = m_sessionId; - cachedresp.AgentData.SerialNum = m_cachedTextureSerial; - m_cachedTextureSerial++; - cachedresp.WearableData = - new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; + public void SendImageNotFound(UUID imageid) + { + ImageNotInDatabasePacket notFoundPacket + = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); - for (int i = 0; i < cachedtex.WearableData.Length; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - cachedresp.WearableData[i].HostName = new byte[0]; - } + notFoundPacket.ImageID.ID = imageid; - cachedresp.Header.Zerocoded = true; - OutPacket(cachedresp, ThrottleOutPacketType.Task); - - return true; + OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); } - protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + public void SendShutdownConnectionNotice() { - MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); - Scene tScene = (Scene)m_scene; - - for (int i = 0; i < multipleupdate.ObjectData.Length; i++) - { - MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; + OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); + } - // Can't act on Null Data - if (block.Data != null) - { - uint localId = block.ObjectLocalID; - SceneObjectPart part = tScene.GetSceneObjectPart(localId); + public void SendSimStats(SimStats stats) + { + SimStatsPacket pack = new SimStatsPacket(); + pack.Region = new SimStatsPacket.RegionBlock(); + pack.Region.RegionX = stats.RegionX; + pack.Region.RegionY = stats.RegionY; + pack.Region.RegionFlags = stats.RegionFlags; + pack.Region.ObjectCapacity = stats.ObjectCapacity; + //pack.Region = //stats.RegionBlock; + pack.Stat = stats.StatsBlock; - if (part == null) - { - // It's a ghost! tell the client to delete it from view. - simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); - } - else - { - // UUID partId = part.UUID; - UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; + pack.Header.Reliable = false; - switch (block.Type) - { - case 1: - Vector3 pos1 = new Vector3(block.Data, 0); + OutPacket(pack, ThrottleOutPacketType.Task); + } - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - handlerUpdatePrimSinglePosition(localId, pos1, this); - } - break; - case 2: - Quaternion rot1 = new Quaternion(block.Data, 0, true); + public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, + uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, + uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, + UUID LastOwnerID, string ObjectName, string Description) + { + ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); + // TODO: don't create new blocks if recycling an old packet - handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; - if (handlerUpdatePrimSingleRotation != null) - { - // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); - handlerUpdatePrimSingleRotation(localId, rot1, this); - } - break; - case 3: - Vector3 rotPos = new Vector3(block.Data, 0); - Quaternion rot2 = new Quaternion(block.Data, 12, true); + ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); + objPropDB.RequestFlags = RequestFlags; + objPropDB.ObjectID = ObjectUUID; + if (OwnerID == GroupID) + objPropDB.OwnerID = UUID.Zero; + else + objPropDB.OwnerID = OwnerID; + objPropDB.GroupID = GroupID; + objPropDB.BaseMask = BaseMask; + objPropDB.OwnerMask = OwnerMask; + objPropDB.GroupMask = GroupMask; + objPropDB.EveryoneMask = EveryoneMask; + objPropDB.NextOwnerMask = NextOwnerMask; - handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; - if (handlerUpdatePrimSingleRotationPosition != null) - { - // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); - // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); - handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); - } - break; - case 4: - case 20: - Vector3 scale4 = new Vector3(block.Data, 0); + // TODO: More properties are needed in SceneObjectPart! + objPropDB.OwnershipCost = OwnershipCost; + objPropDB.SaleType = SaleType; + objPropDB.SalePrice = SalePrice; + objPropDB.Category = Category; + objPropDB.LastOwnerID = LastOwnerID; + objPropDB.Name = Util.StringToBytes256(ObjectName); + objPropDB.Description = Util.StringToBytes256(Description); + objPropFamilyPack.ObjectData = objPropDB; + objPropFamilyPack.Header.Zerocoded = true; + OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); + } - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { -// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); - handlerUpdatePrimScale(localId, scale4, this); - } - break; - case 5: + public void SendObjectPropertiesReply( + UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, + UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, + UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, + string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, + uint BaseMask, byte saleType, int salePrice) + { + ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + // TODO: don't create new blocks if recycling an old packet - Vector3 scale1 = new Vector3(block.Data, 12); - Vector3 pos11 = new Vector3(block.Data, 0); + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; + proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); + proper.ObjectData[0].ItemID = ItemID; + proper.ObjectData[0].CreationDate = CreationDate; + proper.ObjectData[0].CreatorID = CreatorUUID; + proper.ObjectData[0].FolderID = FolderUUID; + proper.ObjectData[0].FromTaskID = FromTaskUUID; + proper.ObjectData[0].GroupID = GroupUUID; + proper.ObjectData[0].InventorySerial = InventorySerial; - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale1, this); + proper.ObjectData[0].LastOwnerID = LastOwnerUUID; + // proper.ObjectData[0].LastOwnerID = UUID.Zero; - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos11, this); - } - } - break; - case 9: - Vector3 pos2 = new Vector3(block.Data, 0); + proper.ObjectData[0].ObjectID = ObjectUUID; + if (OwnerUUID == GroupUUID) + proper.ObjectData[0].OwnerID = UUID.Zero; + else + proper.ObjectData[0].OwnerID = OwnerUUID; + proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle); + proper.ObjectData[0].TextureID = TextureID; + proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle); + proper.ObjectData[0].Name = Util.StringToBytes256(ItemName); + proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription); + proper.ObjectData[0].OwnerMask = OwnerMask; + proper.ObjectData[0].NextOwnerMask = NextOwnerMask; + proper.ObjectData[0].GroupMask = GroupMask; + proper.ObjectData[0].EveryoneMask = EveryoneMask; + proper.ObjectData[0].BaseMask = BaseMask; + // proper.ObjectData[0].AggregatePerms = 53; + // proper.ObjectData[0].AggregatePermTextures = 0; + // proper.ObjectData[0].AggregatePermTexturesOwner = 0; + proper.ObjectData[0].SaleType = saleType; + proper.ObjectData[0].SalePrice = salePrice; + proper.Header.Zerocoded = true; + OutPacket(proper, ThrottleOutPacketType.Task); + } - handlerUpdateVector = OnUpdatePrimGroupPosition; + #endregion - if (handlerUpdateVector != null) - { + #region Estate Data Sending Methods - handlerUpdateVector(localId, pos2, this); - } - break; - case 10: - Quaternion rot3 = new Quaternion(block.Data, 0, true); - - handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - { - // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); - handlerUpdatePrimRotation(localId, rot3, this); - } - break; - case 11: - Vector3 pos3 = new Vector3(block.Data, 0); - Quaternion rot4 = new Quaternion(block.Data, 12, true); - - handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; - if (handlerUpdatePrimGroupRotation != null) - { - // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); - handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); - } - break; - case 12: - case 28: - Vector3 scale7 = new Vector3(block.Data, 0); - - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { -// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); - handlerUpdatePrimGroupScale(localId, scale7, this); - } - break; - case 13: - Vector3 scale2 = new Vector3(block.Data, 12); - Vector3 pos4 = new Vector3(block.Data, 0); - - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale2, this); - - // Change the position based on scale (for bug number 246) - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos4, this); - } - } - break; - case 29: - Vector3 scale5 = new Vector3(block.Data, 12); - Vector3 pos5 = new Vector3(block.Data, 0); - - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimGroupScale(localId, scale5, this); - handlerUpdateVector = OnUpdatePrimGroupPosition; - - if (handlerUpdateVector != null) - { - handlerUpdateVector(localId, pos5, this); - } - } - break; - case 21: - Vector3 scale6 = new Vector3(block.Data, 12); - Vector3 pos6 = new Vector3(block.Data, 0); - - handlerUpdatePrimScale = OnUpdatePrimScale; - if (handlerUpdatePrimScale != null) - { - // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); - handlerUpdatePrimScale(localId, scale6, this); - handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; - if (handlerUpdatePrimSinglePosition != null) - { - handlerUpdatePrimSinglePosition(localId, pos6, this); - } - } - break; - default: - m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); - break; - } - } - } + private static bool convertParamStringToBool(byte[] field) + { + string s = Utils.BytesToString(field); + if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") + { + return true; } - return true; + return false; } - public void RequestMapLayer() + public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) { - //should be getting the map layer from the grid server - //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) - MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); - // TODO: don't create new blocks if recycling an old packet - mapReply.AgentData.AgentID = AgentId; - mapReply.AgentData.Flags = 0; - mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; - mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); - mapReply.LayerData[0].Bottom = 0; - mapReply.LayerData[0].Left = 0; - mapReply.LayerData[0].Top = 30000; - mapReply.LayerData[0].Right = 30000; - mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); - mapReply.Header.Zerocoded = true; - OutPacket(mapReply, ThrottleOutPacketType.Land); - } + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) - { - /* - IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); - MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); - mbReply.AgentData.AgentId = AgentId; - int len; - if (simMapProfiles == null) - len = 0; - else - len = simMapProfiles.Count; + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; - mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; - int iii; - for (iii = 0; iii < len; iii++) + for (int i = 0; i < (6 + EstateManagers.Length); i++) { - Hashtable mp = (Hashtable)simMapProfiles[iii]; - mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); - mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); - mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); - mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); - mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); - mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); - mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); - mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); - mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); } - this.OutPacket(mbReply, ThrottleOutPacketType.Land); - */ - } - - /// - /// returns a byte array of the client set throttles Gets multiplied by the multiplier - /// - /// - /// non 1 multiplier for subdividing the throttles between individual regions - /// - public byte[] GetThrottlesPacked(float multiplier) - { - return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier); - } - /// - /// sets the throttles from values supplied by the client - /// - /// - public void SetChildAgentThrottle(byte[] throttles) - { - m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); - } + int j = 0; - /// - /// Method gets called when a new packet has arrived from the UDP - /// server. This happens after it's been decoded into a libsl object. - /// - /// object containing the packet. - public virtual void InPacket(object NewPack) - { - // Cast NewPack to Packet. - m_PacketHandler.InPacket((Packet) NewPack); + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(EstateManagers.Length.ToString()); j++; + for (int i = 0; i < EstateManagers.Length; i++) + { + returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); } - /// - /// This is the starting point for sending a simulator packet out to the client. - /// - /// Please do not call this from outside the LindenUDP client stack. - /// - /// - /// Corresponds to the type of data that is going out. Enum - public void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) + public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) { - m_PacketHandler.OutPacket(NewPack, throttlePacketType); - } + ListBannedUsers = new List(); - public bool AddMoney(int debit) - { - if (m_moneyBalance + debit >= 0) + for (int i = 0; i < bl.Length; i++) { - m_moneyBalance += debit; - SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); - return true; + if (bl[i] == null) + continue; + if (bl[i].BannedUserID == UUID.Zero) + continue; + BannedUsers.Add(bl[i].BannedUserID); } - return false; - } - /// - /// Breaks down the genericMessagePacket into specific events - /// - /// - /// - /// - public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) - { - switch (gmMethod) - { - case "autopilot": - float locx; - float locy; - float locz; + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - try - { - uint regionX; - uint regionY; - Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; - locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; - locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); - } - catch (InvalidCastException) - { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; - } + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; - handlerAutoPilotGo = OnAutoPilotGo; - if (handlerAutoPilotGo != null) - { - handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); - } - m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); + for (int i = 0; i < (6 + BannedUsers.Count); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - break; - default: - m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); - for (int hi = 0; hi < gmParams.Length; hi++) - { - Console.WriteLine(gmParams[hi].ToString()); - } - //gmpack.MethodData. - break; - + foreach (UUID banned in BannedUsers) + { + returnblock[j].Parameter = banned.GetBytes(); j++; } + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); } - /// - /// Entryway from the client to the simulator. All UDP packets from the client will end up here - /// - /// OpenMetaverse.packet - public void ProcessInPacket(Packet Pack) + public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) { + RegionInfoPacket rinfopack = new RegionInfoPacket(); + RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; + rinfoblk.BillableFactor = args.billableFactor; + rinfoblk.EstateID = args.estateID; + rinfoblk.MaxAgents = args.maxAgents; + rinfoblk.ObjectBonusFactor = args.objectBonusFactor; + rinfoblk.ParentEstateID = args.parentEstateID; + rinfoblk.PricePerMeter = args.pricePerMeter; + rinfoblk.RedirectGridX = args.redirectGridX; + rinfoblk.RedirectGridY = args.redirectGridY; + rinfoblk.RegionFlags = args.regionFlags; + rinfoblk.SimAccess = args.simAccess; + rinfoblk.SunHour = args.sunHour; + rinfoblk.TerrainLowerLimit = args.terrainLowerLimit; + rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit; + rinfoblk.UseEstateSun = args.useEstateSun; + rinfoblk.WaterHeight = args.waterHeight; + rinfoblk.SimName = Utils.StringToBytes(args.simName); + + rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); + rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; + rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; + rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; + rinfopack.RegionInfo2.ProductName = Utils.EmptyBytes; + rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; - if (ProcessPacketMethod(Pack)) - { - return; - } + rinfopack.HasVariableBlocks = true; + rinfopack.RegionInfo = rinfoblk; + rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; - const bool m_checkPackets = true; - // Main packet processing conditional - switch (Pack.Type) - { - #region Scene/Avatar + OutPacket(rinfopack, ThrottleOutPacketType.Task); + } - case PacketType.AvatarPropertiesRequest: - AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; + public void SendEstateCovenantInformation(UUID covenant) + { + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); + EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); + edata.CovenantID = covenant; + edata.CovenantTimestamp = 0; + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); + einfopack.Data = edata; + OutPacket(einfopack, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avatarProperties.AgentData.SessionID != SessionId || - avatarProperties.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) + { + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.MethodData.Invoice = invoice; + packet.AgentData.TransactionID = UUID.Random(); + packet.MethodData.Method = Utils.StringToBytes("estateupdateinfo"); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10]; - handlerRequestAvatarProperties = OnRequestAvatarProperties; - if (handlerRequestAvatarProperties != null) - { - handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); - } + for (int i = 0; i < 10; i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } - break; + //Sending Estate Settings + returnblock[0].Parameter = Utils.StringToBytes(estateName); + // TODO: remove this cruft once MasterAvatar is fully deprecated + // + returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); + returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); - case PacketType.ChatFromViewer: - ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + returnblock[3].Parameter = Utils.StringToBytes(estateFlags.ToString()); + returnblock[4].Parameter = Utils.StringToBytes(sunPosition.ToString()); + returnblock[5].Parameter = Utils.StringToBytes(parentEstate.ToString()); + returnblock[6].Parameter = Utils.StringToBytes(covenant.ToString()); + returnblock[7].Parameter = Utils.StringToBytes("1160895077"); // what is this? + returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? + returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); - #region Packet Session and User Check - if (m_checkPackets) - { - if (inchatpack.AgentData.SessionID != SessionId || - inchatpack.AgentData.AgentID != AgentId) - break; - } - #endregion + packet.ParamList = returnblock; + packet.Header.Reliable = false; + //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); + OutPacket(packet, ThrottleOutPacketType.Task); + } - string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; - byte[] message = inchatpack.ChatData.Message; - byte type = inchatpack.ChatData.Type; - Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; - // UUID fromAgentID = AgentId; + #endregion - int channel = inchatpack.ChatData.Channel; + #region Land Data Sending Methods - if (OnChatFromClient != null) - { - OSChatMessage args = new OSChatMessage(); - args.Channel = channel; - args.From = fromName; - args.Message = Utils.BytesToString(message); - args.Type = (ChatTypeEnum)type; - args.Position = fromPos; + public void SendLandParcelOverlay(byte[] data, int sequence_id) + { + ParcelOverlayPacket packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); + packet.ParcelData.Data = data; + packet.ParcelData.SequenceID = sequence_id; + packet.Header.Zerocoded = true; + OutPacket(packet, ThrottleOutPacketType.Task); + } - args.Scene = Scene; - args.Sender = this; - args.SenderUUID = this.AgentId; + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + { + ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties); + // TODO: don't create new blocks if recycling an old packet - handlerChatFromClient = OnChatFromClient; - if (handlerChatFromClient != null) - handlerChatFromClient(this, args); - } - break; + updatePacket.ParcelData.AABBMax = landData.AABBMax; + updatePacket.ParcelData.AABBMin = landData.AABBMin; + updatePacket.ParcelData.Area = landData.Area; + updatePacket.ParcelData.AuctionID = landData.AuctionID; + updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; - case PacketType.AvatarPropertiesUpdate: - AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; + updatePacket.ParcelData.Bitmap = landData.Bitmap; - #region Packet Session and User Check - if (m_checkPackets) - { - if (avatarProps.AgentData.SessionID != SessionId || - avatarProps.AgentData.AgentID != AgentId) - break; - } - #endregion + updatePacket.ParcelData.Desc = Utils.StringToBytes(landData.Description); + updatePacket.ParcelData.Category = (byte)landData.Category; + updatePacket.ParcelData.ClaimDate = landData.ClaimDate; + updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice; + updatePacket.ParcelData.GroupID = landData.GroupID; + updatePacket.ParcelData.GroupPrims = landData.GroupPrims; + updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned; + updatePacket.ParcelData.LandingType = landData.LandingType; + updatePacket.ParcelData.LocalID = landData.LocalID; - handlerUpdateAvatarProperties = OnUpdateAvatarProperties; - if (handlerUpdateAvatarProperties != null) - { - AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; - UserProfileData UserProfile = new UserProfileData(); - UserProfile.ID = AgentId; - UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); - UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); - UserProfile.FirstLifeImage = Properties.FLImageID; - UserProfile.Image = Properties.ImageID; - UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); + if (landData.Area > 0) + { + updatePacket.ParcelData.MaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.MaxPrims = 0; + } - handlerUpdateAvatarProperties(this, UserProfile); - } - break; + updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; + updatePacket.ParcelData.MediaID = landData.MediaID; + updatePacket.ParcelData.MediaURL = Util.StringToBytes256(landData.MediaURL); + updatePacket.ParcelData.MusicURL = Util.StringToBytes256(landData.MusicURL); + updatePacket.ParcelData.Name = Util.StringToBytes256(landData.Name); + updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; + updatePacket.ParcelData.OtherCount = 0; //TODO: Unimplemented + updatePacket.ParcelData.OtherPrims = landData.OtherPrims; + updatePacket.ParcelData.OwnerID = landData.OwnerID; + updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; + updatePacket.ParcelData.ParcelFlags = landData.Flags; + updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; + updatePacket.ParcelData.PassHours = landData.PassHours; + updatePacket.ParcelData.PassPrice = landData.PassPrice; + updatePacket.ParcelData.PublicCount = 0; //TODO: Unimplemented - case PacketType.ScriptDialogReply: - ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; + updatePacket.ParcelData.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0; + updatePacket.ParcelData.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0; + updatePacket.ParcelData.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0; + updatePacket.ParcelData.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0; - #region Packet Session and User Check - if (m_checkPackets) - { - if (rdialog.AgentData.SessionID != SessionId || - rdialog.AgentData.AgentID != AgentId) - break; - } - #endregion + updatePacket.ParcelData.RentPrice = 0; + updatePacket.ParcelData.RequestResult = request_result; + updatePacket.ParcelData.SalePrice = landData.SalePrice; + updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; + updatePacket.ParcelData.SelfCount = 0; //TODO: Unimplemented + updatePacket.ParcelData.SequenceID = sequence_id; + if (landData.SimwideArea > 0) + { + updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity; + } + else + { + updatePacket.ParcelData.SimWideMaxPrims = 0; + } + updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims; + updatePacket.ParcelData.SnapSelection = snap_selection; + updatePacket.ParcelData.SnapshotID = landData.SnapshotID; + updatePacket.ParcelData.Status = (byte)landData.Status; + updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + + landData.SelectedPrims; + updatePacket.ParcelData.UserLocation = landData.UserLocation; + updatePacket.ParcelData.UserLookAt = landData.UserLookAt; + updatePacket.Header.Zerocoded = true; - int ch = rdialog.Data.ChatChannel; - byte[] msg = rdialog.Data.ButtonLabel; - if (OnChatFromClient != null) - { - OSChatMessage args = new OSChatMessage(); - args.Channel = ch; - args.From = String.Empty; - args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; - args.Position = new Vector3(); - args.Scene = Scene; - args.Sender = this; - handlerChatFromClient2 = OnChatFromClient; - if (handlerChatFromClient2 != null) - handlerChatFromClient2(this, args); - } + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + eq.ParcelProperties(updatePacket, this.AgentId); + } + } + catch (Exception ex) + { + m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); + m_log.Warn("sending parcel data via UDP"); + OutPacket(updatePacket, ThrottleOutPacketType.Task); + } + } - break; + public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) + { + ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); + replyPacket.Data.AgentID = AgentId; + replyPacket.Data.Flags = accessFlag; + replyPacket.Data.LocalID = localLandID; + replyPacket.Data.SequenceID = 0; - case PacketType.ImprovedInstantMessage: - ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; + List list = new List(); + foreach (UUID avatar in avatars) + { + ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); + block.Flags = accessFlag; + block.ID = avatar; + block.Time = 0; + list.Add(block); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (msgpack.AgentData.SessionID != SessionId || - msgpack.AgentData.AgentID != AgentId) - break; - } - #endregion + replyPacket.List = list.ToArray(); + replyPacket.Header.Zerocoded = true; + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } - string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); - string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); - handlerInstantMessage = OnInstantMessage; + public void SendForceClientSelectObjects(List ObjectIDs) + { + bool firstCall = true; + const int MAX_OBJECTS_PER_PACKET = 251; + ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); + ForceObjectSelectPacket.DataBlock[] data; + while (ObjectIDs.Count > 0) + { + if (firstCall) + { + pack._Header.ResetList = true; + firstCall = false; + } + else + { + pack._Header.ResetList = false; + } - if (handlerInstantMessage != null) - { - GridInstantMessage im = new GridInstantMessage(Scene, - msgpack.AgentData.AgentID, - IMfromName, - msgpack.MessageBlock.ToAgentID, - msgpack.MessageBlock.Dialog, - msgpack.MessageBlock.FromGroup, - IMmessage, - msgpack.MessageBlock.ID, - msgpack.MessageBlock.Offline != 0 ? true : false, - msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET) + { + data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; + } + else + { + data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count]; + } - handlerInstantMessage(this, im); - } - break; + int i; + for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++) + { + data[i] = new ForceObjectSelectPacket.DataBlock(); + data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]); + ObjectIDs.RemoveAt(0); + } + pack.Data = data; + pack.Header.Zerocoded = true; + OutPacket(pack, ThrottleOutPacketType.Task); + } + } - case PacketType.AcceptFriendship: - AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; + public void SendCameraConstraint(Vector4 ConstraintPlane) + { + CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint); + cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock(); + cpack.CameraCollidePlane.Plane = ConstraintPlane; + //m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane); + OutPacket(cpack, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (afriendpack.AgentData.SessionID != SessionId || - afriendpack.AgentData.AgentID != AgentId) - break; - } - #endregion + public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) + { + - // My guess is this is the folder to stick the calling card into - List callingCardFolders = new List(); + int notifyCount = ownersAndCount.Count; + ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); - UUID agentID = afriendpack.AgentData.AgentID; - UUID transactionID = afriendpack.TransactionBlock.TransactionID; + if (notifyCount > 0) + { + if (notifyCount > 32) + { + m_log.InfoFormat( + "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" + + " - a developer might want to investigate whether this is a hard limit", 32); - for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) - { - callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); - } + notifyCount = 32; + } - handlerApproveFriendRequest = OnApproveFriendRequest; - if (handlerApproveFriendRequest != null) - { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); - } - break; + ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock + = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; - case PacketType.DeclineFriendship: - DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; + int num = 0; + foreach (UUID owner in ownersAndCount.Keys) + { + dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); + dataBlock[num].Count = ownersAndCount[owner]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (dfriendpack.AgentData.SessionID != SessionId || - dfriendpack.AgentData.AgentID != AgentId) - break; - } - #endregion + if (land.GroupID == owner || groups.Contains(owner)) + dataBlock[num].IsGroupOwned = true; - if (OnDenyFriendRequest != null) - { - OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, - dfriendpack.TransactionBlock.TransactionID, - null); - } - break; + dataBlock[num].OnlineStatus = true; //TODO: fix me later + dataBlock[num].OwnerID = owner; - case PacketType.TerminateFriendship: - TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; + num++; - #region Packet Session and User Check - if (m_checkPackets) + if (num >= notifyCount) { - if (tfriendpack.AgentData.SessionID != SessionId || - tfriendpack.AgentData.AgentID != AgentId) - break; + break; } - #endregion - - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; - UUID exFriendID = tfriendpack.ExBlock.OtherID; + } - handlerTerminateFriendship = OnTerminateFriendship; - if (handlerTerminateFriendship != null) - { - handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); - } - break; + pack.Data = dataBlock; + } + pack.Header.Zerocoded = true; + this.OutPacket(pack, ThrottleOutPacketType.Task); + } - case PacketType.RezObject: - RezObjectPacket rezPacket = (RezObjectPacket)Pack; + #endregion - #region Packet Session and User Check - if (m_checkPackets) - { - if (rezPacket.AgentData.SessionID != SessionId || - rezPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + #region Helper Methods - handlerRezObject = OnRezObject; - if (handlerRezObject != null) - { - handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, - rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, - rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, - rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, - rezPacket.RezData.FromTaskID); - } - break; + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, + Vector3 velocity, + Quaternion rotation) + { + byte[] bytes = new byte[60]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); - case PacketType.DeRezObject: - DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; + dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; - #region Packet Session and User Check - if (m_checkPackets) - { - if (DeRezPacket.AgentData.SessionID != SessionId || - DeRezPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + uint ID = localID; - handlerDeRezObject = OnDeRezObject; - if (handlerDeRezObject != null) - { - List deRezIDs = new List(); + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = 0; + bytes[i++] = 1; + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; - foreach (DeRezObjectPacket.ObjectDataBlock data in - DeRezPacket.ObjectData) - { - deRezIDs.Add(data.ObjectLocalID); - } - // It just so happens that the values on the DeRezAction enumerator match the Destination - // values given by a Second Life client - handlerDeRezObject(this, deRezIDs, - DeRezPacket.AgentBlock.GroupID, - (DeRezAction)DeRezPacket.AgentBlock.Destination, - DeRezPacket.AgentBlock.DestinationID); - - } - break; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; - case PacketType.ModifyLand: - ModifyLandPacket modify = (ModifyLandPacket)Pack; + Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); - #region Packet Session and User Check - if (m_checkPackets) - { - if (modify.AgentData.SessionID != SessionId || - modify.AgentData.AgentID != AgentId) - break; - } + internDirec = internDirec / 128.0f; + internDirec.X += 1; + internDirec.Y += 1; + internDirec.Z += 1; - #endregion - //m_log.Info("[LAND]: LAND:" + modify.ToString()); - if (modify.ParcelData.Length > 0) - { - if (OnModifyTerrain != null) - { - for (int i = 0; i < modify.ParcelData.Length; i++) - { - handlerModifyTerrain = OnModifyTerrain; - if (handlerModifyTerrain != null) - { - handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, - modify.ModifyBlock.BrushSize, - modify.ModifyBlock.Action, modify.ParcelData[i].North, - modify.ParcelData[i].West, modify.ParcelData[i].South, - modify.ParcelData[i].East, AgentId); - } - } - } - } + ushort InternVelocityX = (ushort)(32768 * internDirec.X); + ushort InternVelocityY = (ushort)(32768 * internDirec.Y); + ushort InternVelocityZ = (ushort)(32768 * internDirec.Z); - break; + ushort ac = 32767; + bytes[i++] = (byte)(InternVelocityX % 256); + bytes[i++] = (byte)((InternVelocityX >> 8) % 256); + bytes[i++] = (byte)(InternVelocityY % 256); + bytes[i++] = (byte)((InternVelocityY >> 8) % 256); + bytes[i++] = (byte)(InternVelocityZ % 256); + bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); - case PacketType.RegionHandshakeReply: + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - handlerRegionHandShakeReply = OnRegionHandShakeReply; - if (handlerRegionHandShakeReply != null) - { - handlerRegionHandShakeReply(this); - } + //rotation + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - break; + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - case PacketType.AgentWearablesRequest: - handlerRequestWearables = OnRequestWearables; + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - if (handlerRequestWearables != null) - { - handlerRequestWearables(); - } + dat.Data = bytes; - handlerRequestAvatarsData = OnRequestAvatarsData; + return (dat); + } - if (handlerRequestAvatarsData != null) - { - handlerRequestAvatarsData(this); - } + /// + /// + /// + /// + /// + /// + /// + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, + Vector3 position, + Quaternion rotation, + Vector3 velocity, + Vector3 rotationalvelocity, + byte state) + { + uint ID = localID; + byte[] bytes = new byte[60]; - break; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock(); + dat.TextureEntry = new byte[0]; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4)); + bytes[i++] = 0; - case PacketType.AgentSetAppearance: - AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + byte[] pb = position.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; - #region Packet Session and User Check - if (m_checkPackets) - { - if (appear.AgentData.SessionID != SessionId || - appear.AgentData.AgentID != AgentId) - break; - } - #endregion + ushort velx, vely, velz; + Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); - handlerSetAppearance = OnSetAppearance; - if (handlerSetAppearance != null) - { - // Temporarily protect ourselves from the mantis #951 failure. - // However, we could do this for several other handlers where a failure isn't terminal - // for the client session anyway, in order to protect ourselves against bad code in plugins - try - { - byte[] visualparams = new byte[appear.VisualParam.Length]; - for (int i = 0; i < appear.VisualParam.Length; i++) - visualparams[i] = appear.VisualParam[i].ParamValue; + vel = vel / 128.0f; + vel.X += 1; + vel.Y += 1; + vel.Z += 1; + //vel + velx = (ushort)(32768 * (vel.X)); + vely = (ushort)(32768 * (vel.Y)); + velz = (ushort)(32768 * (vel.Z)); - Primitive.TextureEntry te = null; - if (appear.ObjectData.TextureEntry.Length > 1) - te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); + bytes[i++] = (byte)(velx % 256); + bytes[i++] = (byte)((velx >> 8) % 256); + bytes[i++] = (byte)(vely % 256); + bytes[i++] = (byte)((vely >> 8) % 256); + bytes[i++] = (byte)(velz % 256); + bytes[i++] = (byte)((velz >> 8) % 256); - handlerSetAppearance(te, visualparams); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", - e); - } - } + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); - break; - - case PacketType.AgentIsNowWearing: - if (OnAvatarNowWearing != null) - { - AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); - #region Packet Session and User Check - if (m_checkPackets) - { - if (nowWearing.AgentData.SessionID != SessionId || - nowWearing.AgentData.AgentID != AgentId) - break; - } - #endregion + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); - AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); - for (int i = 0; i < nowWearing.WearableData.Length; i++) - { - AvatarWearingArgs.Wearable wearable = - new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, - nowWearing.WearableData[i].WearableType); - wearingArgs.NowWearing.Add(wearable); - } + //rotation vel + Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); - handlerAvatarNowWearing = OnAvatarNowWearing; - if (handlerAvatarNowWearing != null) - { - handlerAvatarNowWearing(this, wearingArgs); - } - } - break; + rvel = rvel / 128.0f; + rvel.X += 1; + rvel.Y += 1; + rvel.Z += 1; + //vel + ushort rvelx = (ushort)(32768 * (rvel.X)); + ushort rvely = (ushort)(32768 * (rvel.Y)); + ushort rvelz = (ushort)(32768 * (rvel.Z)); - case PacketType.RezSingleAttachmentFromInv: - handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; - if (handlerRezSingleAttachment != null) - { - RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; + bytes[i++] = (byte)(rvelx % 256); + bytes[i++] = (byte)((rvelx >> 8) % 256); + bytes[i++] = (byte)(rvely % 256); + bytes[i++] = (byte)((rvely >> 8) % 256); + bytes[i++] = (byte)(rvelz % 256); + bytes[i++] = (byte)((rvelz >> 8) % 256); + dat.Data = bytes; - #region Packet Session and User Check - if (m_checkPackets) - { - if (rez.AgentData.SessionID != SessionId || - rez.AgentData.AgentID != AgentId) - break; - } - #endregion + return dat; + } - handlerRezSingleAttachment(this, rez.ObjectData.ItemID, - rez.ObjectData.AttachmentPt); - } + /// + /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + { + ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock(); + SetDefaultPrimPacketValues(objupdate); + objupdate.UpdateFlags = flags; + SetPrimPacketShapeData(objupdate, primShape); - break; + if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass)) + { + objupdate.Data = new byte[1]; + objupdate.Data[0] = primShape.State; + } + return objupdate; + } - case PacketType.RezMultipleAttachmentsFromInv: - handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; - if (handlerRezMultipleAttachments != null) - { - RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; - handlerRezMultipleAttachments(this, rez.HeaderData, - rez.ObjectData); - } + protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) + { + objectData.TextureEntry = primData.TextureEntry; + objectData.PCode = primData.PCode; + objectData.State = primData.State; + objectData.PathBegin = primData.PathBegin; + objectData.PathEnd = primData.PathEnd; + objectData.PathScaleX = primData.PathScaleX; + objectData.PathScaleY = primData.PathScaleY; + objectData.PathShearX = primData.PathShearX; + objectData.PathShearY = primData.PathShearY; + objectData.PathSkew = primData.PathSkew; + objectData.ProfileBegin = primData.ProfileBegin; + objectData.ProfileEnd = primData.ProfileEnd; + objectData.Scale = primData.Scale; + objectData.PathCurve = primData.PathCurve; + objectData.ProfileCurve = primData.ProfileCurve; + objectData.ProfileHollow = primData.ProfileHollow; + objectData.PathRadiusOffset = primData.PathRadiusOffset; + objectData.PathRevolutions = primData.PathRevolutions; + objectData.PathTaperX = primData.PathTaperX; + objectData.PathTaperY = primData.PathTaperY; + objectData.PathTwist = primData.PathTwist; + objectData.PathTwistBegin = primData.PathTwistBegin; + objectData.ExtraParams = primData.ExtraParams; + } - break; + /// + /// Set some default values in a ObjectUpdatePacket + /// + /// + protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 3; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + objdata.State = 0; + objdata.Data = new byte[0]; - case PacketType.DetachAttachmentIntoInv: - handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; - if (handlerDetachAttachmentIntoInv != null) - { - DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; + objdata.ObjectData = new byte[60]; + objdata.ObjectData[46] = 128; + objdata.ObjectData[47] = 63; + } - #region Packet Session and User Check - // UNSUPPORTED ON THIS PACKET - #endregion + /// + /// + /// + /// + public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + { + ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock(); + // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); - UUID itemID = detachtoInv.ObjectData.ItemID; - // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; + SetDefaultAvatarPacketValues(ref objdata); + objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objdata.PathCurve = 16; + objdata.ProfileCurve = 1; + objdata.PathScaleX = 100; + objdata.PathScaleY = 100; + objdata.ParentID = 0; + objdata.OwnerID = UUID.Zero; + objdata.Scale = new Vector3(1, 1, 1); + objdata.PCode = (byte)PCode.Avatar; + if (textureEntry != null) + { + objdata.TextureEntry = textureEntry; + } + Vector3 pos = new Vector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User "); + //Vector3 pos2 = new Vector3(100f, 100f, 23f); + //objdata.FullID=user.AgentId; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); - handlerDetachAttachmentIntoInv(itemID, this); - } - break; + return objdata; + } - case PacketType.ObjectAttach: - if (OnObjectAttach != null) - { - ObjectAttachPacket att = (ObjectAttachPacket)Pack; + /// + /// + /// + /// + protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); + objdata.JointPivot = new Vector3(0, 0, 0); + objdata.Material = 4; + objdata.TextureAnim = new byte[0]; + objdata.Sound = UUID.Zero; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); + objdata.TextureEntry = ntex.GetBytes(); - #region Packet Session and User Check - if (m_checkPackets) - { - if (att.AgentData.SessionID != SessionId || - att.AgentData.AgentID != AgentId) - break; - } - #endregion + objdata.State = 0; + objdata.Data = new byte[0]; - handlerObjectAttach = OnObjectAttach; + objdata.ObjectData = new byte[76]; + objdata.ObjectData[15] = 128; + objdata.ObjectData[16] = 63; + objdata.ObjectData[56] = 128; + objdata.ObjectData[61] = 102; + objdata.ObjectData[62] = 40; + objdata.ObjectData[63] = 61; + objdata.ObjectData[64] = 189; + } - if (handlerObjectAttach != null) - { - if (att.ObjectData.Length > 0) - { - handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); - } - } - } - break; + public void SendNameReply(UUID profileId, string firstname, string lastname) + { + UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); + // TODO: don't create new blocks if recycling an old packet + packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; + packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); + packet.UUIDNameBlock[0].ID = profileId; + packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); + packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); - case PacketType.ObjectDetach: - ObjectDetachPacket dett = (ObjectDetachPacket)Pack; + OutPacket(packet, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (dett.AgentData.SessionID != SessionId || - dett.AgentData.AgentID != AgentId) - break; - } - #endregion + public ulong GetGroupPowers(UUID groupID) + { + if (groupID == m_activeGroupID) + return m_activeGroupPowers; - for (int j = 0; j < dett.ObjectData.Length; j++) - { - uint obj = dett.ObjectData[j].ObjectLocalID; - handlerObjectDetach = OnObjectDetach; - if (handlerObjectDetach != null) - { - handlerObjectDetach(obj, this); - } + if (m_groupPowers.ContainsKey(groupID)) + return m_groupPowers[groupID]; - } - break; + return 0; + } - case PacketType.ObjectDrop: - ObjectDropPacket dropp = (ObjectDropPacket)Pack; + /// + /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. + /// + public bool ChildAgentStatus() + { + return m_scene.PresenceChildStatus(AgentId); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (dropp.AgentData.SessionID != SessionId || - dropp.AgentData.AgentID != AgentId) - break; - } - #endregion + #endregion - for (int j = 0; j < dropp.ObjectData.Length; j++) - { - uint obj = dropp.ObjectData[j].ObjectLocalID; - handlerObjectDrop = OnObjectDrop; - if (handlerObjectDrop != null) - { - handlerObjectDrop(obj, this); - } - } - break; - - case PacketType.SetAlwaysRun: - SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (run.AgentData.SessionID != SessionId || - run.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerSetAlwaysRun = OnSetAlwaysRun; - if (handlerSetAlwaysRun != null) - handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); - - break; + /// + /// This is a different way of processing packets then ProcessInPacket + /// + protected virtual void RegisterLocalPacketHandlers() + { + AddLocalPacketHandler(PacketType.LogoutRequest, Logout); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); + AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); + AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); + AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); + } - case PacketType.CompleteAgentMovement: - handlerCompleteMovementToRegion = OnCompleteMovementToRegion; - if (handlerCompleteMovementToRegion != null) - { - handlerCompleteMovementToRegion(); - } - handlerCompleteMovementToRegion = null; + #region Packet Handlers - break; + private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) + { + MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; + // validate the agent owns the agentID and sessionID + if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && + money.AgentData.SessionID == sender.SessionId) + { + MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest; + if (handlerMoneyTransferRequest != null) + { + handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, + money.MoneyData.Amount, money.MoneyData.TransactionType, + Util.FieldToString(money.MoneyData.Description)); + } - case PacketType.AgentUpdate: - if (OnAgentUpdate != null) - { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + return true; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (agenUpdate.AgentData.SessionID != SessionId || - agenUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + return false; + } - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; + private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) + { + ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; + if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) + { + ParcelBuy handlerParcelBuy = OnParcelBuy; + if (handlerParcelBuy != null) + { + handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, + parcel.Data.IsGroupOwned, + parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, + parcel.ParcelData.Price, + false); + } + return true; + } + return false; + } - // We can only check when we have something to check - // against. + private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) + { + UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; + - if (lastarg != null) - { - update = - ( - (x.BodyRotation != lastarg.BodyRotation) || - (x.CameraAtAxis != lastarg.CameraAtAxis) || - (x.CameraCenter != lastarg.CameraCenter) || - (x.CameraLeftAxis != lastarg.CameraLeftAxis) || - (x.CameraUpAxis != lastarg.CameraUpAxis) || - (x.ControlFlags != lastarg.ControlFlags) || - (x.Far != lastarg.Far) || - (x.Flags != lastarg.Flags) || - (x.State != lastarg.State) || - (x.HeadRotation != lastarg.HeadRotation) || - (x.SessionID != lastarg.SessionID) || - (x.AgentID != lastarg.AgentID) - ); - } - else - update = true; + for (int i = 0; i < upack.UUIDNameBlock.Length; i++) + { + UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; + if (handlerUUIDGroupNameRequest != null) + { + handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); + } + } - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. + return true; + } - if (update) - { - AgentUpdateArgs arg = new AgentUpdateArgs(); - arg.AgentID = x.AgentID; - arg.BodyRotation = x.BodyRotation; - arg.CameraAtAxis = x.CameraAtAxis; - arg.CameraCenter = x.CameraCenter; - arg.CameraLeftAxis = x.CameraLeftAxis; - arg.CameraUpAxis = x.CameraUpAxis; - arg.ControlFlags = x.ControlFlags; - arg.Far = x.Far; - arg.Flags = x.Flags; - arg.HeadRotation = x.HeadRotation; - arg.SessionID = x.SessionID; - arg.State = x.State; - handlerAgentUpdate = OnAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime - if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + public bool HandleGenericMessage(IClientAPI sender, Packet pack) + { + GenericMessagePacket gmpack = (GenericMessagePacket) pack; + if (m_genericPacketHandlers.Count == 0) return false; + if (gmpack.AgentData.SessionID != SessionId) return false; - handlerAgentUpdate = null; - } + GenericMessage handlerGenericMessage = null; - } - break; + string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); - case PacketType.AgentAnimation: - AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) + { + List msg = new List(); + List msgBytes = new List(); - #region Packet Session and User Check - if (m_checkPackets) + if (handlerGenericMessage != null) + { + foreach (GenericMessagePacket.ParamListBlock block in gmpack.ParamList) { - if (AgentAni.AgentData.SessionID != SessionId || - AgentAni.AgentData.AgentID != AgentId) - break; + msg.Add(Util.FieldToString(block.Parameter)); + msgBytes.Add(block.Parameter); } - #endregion - - handlerStartAnim = null; - handlerStopAnim = null; - - for (int i = 0; i < AgentAni.AnimationList.Length; i++) + try { - if (AgentAni.AnimationList[i].StartAnim) - { - handlerStartAnim = OnStartAnim; - if (handlerStartAnim != null) - { - handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); - } - } - else + if (OnBinaryGenericMessage != null) { - handlerStopAnim = OnStopAnim; - if (handlerStopAnim != null) - { - handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); - } + OnBinaryGenericMessage(this, method, msgBytes.ToArray()); } + handlerGenericMessage(sender, method, msg); + return true; } - break; - - case PacketType.AgentRequestSit: - if (OnAgentRequestSit != null) + catch (Exception e) { - AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentRequestSit.AgentData.SessionID != SessionId || - agentRequestSit.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerAgentRequestSit = OnAgentRequestSit; - if (handlerAgentRequestSit != null) - handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, - agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + m_log.Error("[GENERICMESSAGE] " + e); } - break; - - case PacketType.AgentSit: - if (OnAgentSit != null) - { - AgentSitPacket agentSit = (AgentSitPacket)Pack; + } + } + m_log.Error("[GENERICMESSAGE] Not handling GenericMessage with method-type of: " + method); + return false; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (agentSit.AgentData.SessionID != SessionId || - agentSit.AgentData.AgentID != AgentId) - break; - } - #endregion + public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) + { - handlerAgentSit = OnAgentSit; - if (handlerAgentSit != null) - { - OnAgentSit(this, agentSit.AgentData.AgentID); - } - } - break; + ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; + if (ogpack.AgentData.SessionID != SessionId) return false; - case PacketType.SoundTrigger: - SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; + RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest; + if (handlerObjectGroupRequest != null) + { + for (int i = 0; i < ogpack.ObjectData.Length; i++) + { + handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, UUID.Zero); + } + } + return true; + } - #region Packet Session and User Check - if (m_checkPackets) - { - // UNSUPPORTED ON THIS PACKET - } - #endregion - - handlerSoundTrigger = OnSoundTrigger; - if (handlerSoundTrigger != null) - { - handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, - soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, - soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, - soundTriggerPacket.SoundData.Handle); - - } - break; + private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + { + ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; + if (viewer.AgentData.SessionID != SessionId) return false; + ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect; + if (handlerViewerEffect != null) + { + int length = viewer.Effect.Length; + List args = new List(length); + for (int i = 0; i < length; i++) + { + //copy the effects block arguments into the event handler arg. + ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg(); + argument.AgentID = viewer.Effect[i].AgentID; + argument.Color = viewer.Effect[i].Color; + argument.Duration = viewer.Effect[i].Duration; + argument.ID = viewer.Effect[i].ID; + argument.Type = viewer.Effect[i].Type; + argument.TypeData = viewer.Effect[i].TypeData; + args.Add(argument); + } - case PacketType.AvatarPickerRequest: - AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + handlerViewerEffect(sender, args); + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avRequestQuery.AgentData.SessionID != SessionId || - avRequestQuery.AgentData.AgentID != AgentId) - break; - } - #endregion + return true; + } - AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; - AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; - //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); + #endregion Packet Handlers - handlerAvatarPickerRequest = OnAvatarPickerRequest; - if (handlerAvatarPickerRequest != null) - { - handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, - Utils.BytesToString(querydata.Name)); - } - break; + public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) + { + ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); + scriptQuestion.Data = new ScriptQuestionPacket.DataBlock(); + // TODO: don't create new blocks if recycling an old packet + scriptQuestion.Data.TaskID = taskID; + scriptQuestion.Data.ItemID = itemID; + scriptQuestion.Data.Questions = question; + scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); + scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); - case PacketType.AgentDataUpdateRequest: - AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; + OutPacket(scriptQuestion, ThrottleOutPacketType.Task); + } - #region Packet Session and User Check - if (m_checkPackets) + private void InitDefaultAnimations() + { + using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) + { + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + if (doc.DocumentElement != null) + foreach (XmlNode nod in doc.DocumentElement.ChildNodes) { - if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || - avRequestDataUpdatePacket.AgentData.AgentID != AgentId) - break; + if (nod.Attributes["name"] != null) + { + string name = nod.Attributes["name"].Value.ToLower(); + string id = nod.InnerText; + m_defaultAnimations.Add(name, (UUID)id); + } } - #endregion + } + } - handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; + public UUID GetDefaultAnimation(string name) + { + if (m_defaultAnimations.ContainsKey(name)) + return m_defaultAnimations[name]; + return UUID.Zero; + } - if (handlerAgentDataUpdateRequest != null) - { - handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); - } + /// + /// Handler called when we receive a logout packet. + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client, Packet packet) + { + if (packet.Type == PacketType.LogoutRequest) + { + if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; + } + + return Logout(client); + } - break; - - case PacketType.UserInfoRequest: - handlerUserInfoRequest = OnUserInfoRequest; - if (handlerUserInfoRequest != null) - { - handlerUserInfoRequest(this); - } - else - { - SendUserInfoReply(false, true, ""); - } - break; - - case PacketType.UpdateUserInfo: - UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; + /// + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client) + { + m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); - #region Packet Session and User Check - if (m_checkPackets) - { - if (updateUserInfo.AgentData.SessionID != SessionId || - updateUserInfo.AgentData.AgentID != AgentId) - break; - } - #endregion + Action handlerLogout = OnLogout; - handlerUpdateUserInfo = OnUpdateUserInfo; - if (handlerUpdateUserInfo != null) - { - bool visible = true; - string DirectoryVisibility = - Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); - if (DirectoryVisibility == "hidden") - visible = false; + if (handlerLogout != null) + { + handlerLogout(client); + } - handlerUpdateUserInfo( - updateUserInfo.UserData.IMViaEMail, - visible, this); - } - break; - - case PacketType.SetStartLocationRequest: - SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; + return true; + } - #region Packet Session and User Check - if (m_checkPackets) - { - if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || - avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + /// + /// Send a response back to a client when it asks the asset server (via the region server) if it has + /// its appearance texture cached. + /// + /// At the moment, we always reply that there is no cached texture. + /// + /// + /// + /// + protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + { + //m_log.Debug("texture cached: " + packet.ToString()); + AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); - if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) - { - handlerSetStartLocationRequest = OnSetStartLocationRequest; - if (handlerSetStartLocationRequest != null) - { - handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, - avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, - avSetStartLocationRequestPacket.StartLocationData.LocationID); - } - } - break; + if (cachedtex.AgentData.SessionID != SessionId) return false; - case PacketType.AgentThrottle: - AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + // TODO: don't create new blocks if recycling an old packet + cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.SessionID = m_sessionId; + cachedresp.AgentData.SerialNum = m_cachedTextureSerial; + m_cachedTextureSerial++; + cachedresp.WearableData = + new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - #region Packet Session and User Check - if (m_checkPackets) - { - if (atpack.AgentData.SessionID != SessionId || - atpack.AgentData.AgentID != AgentId) - break; - } - #endregion + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } - m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles); - break; + cachedresp.Header.Zerocoded = true; + OutPacket(cachedresp, ThrottleOutPacketType.Task); + + return true; + } - case PacketType.AgentPause: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = true; - break; + protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + { + MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; + if (multipleupdate.AgentData.SessionID != SessionId) return false; + // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + Scene tScene = (Scene)m_scene; - case PacketType.AgentResume: - m_probesWithNoIngressPackets = 0; - m_clientBlocked = false; - SendStartPingCheck(0); + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; - break; + // Can't act on Null Data + if (block.Data != null) + { + uint localId = block.ObjectLocalID; + SceneObjectPart part = tScene.GetSceneObjectPart(localId); - case PacketType.ForceScriptControlRelease: - handlerForceReleaseControls = OnForceReleaseControls; - if (handlerForceReleaseControls != null) + if (part == null) { - handlerForceReleaseControls(this, AgentId); - } - break; - - #endregion - - #region Objects/m_sceneObjects - - case PacketType.ObjectLink: - ObjectLinkPacket link = (ObjectLinkPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (link.AgentData.SessionID != SessionId || - link.AgentData.AgentID != AgentId) - break; + // It's a ghost! tell the client to delete it from view. + simClient.SendKillObject(Scene.RegionInfo.RegionHandle, + localId); } - #endregion - - uint parentprimid = 0; - List childrenprims = new List(); - if (link.ObjectData.Length > 1) + else { - parentprimid = link.ObjectData[0].ObjectLocalID; + // UUID partId = part.UUID; + UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; - for (int i = 1; i < link.ObjectData.Length; i++) + switch (block.Type) { - childrenprims.Add(link.ObjectData[i].ObjectLocalID); - } - } - handlerLinkObjects = OnLinkObjects; - if (handlerLinkObjects != null) - { - handlerLinkObjects(this, parentprimid, childrenprims); - } - break; - - case PacketType.ObjectDelink: - ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (delink.AgentData.SessionID != SessionId || - delink.AgentData.AgentID != AgentId) - break; - } - #endregion + case 1: + Vector3 pos1 = new Vector3(block.Data, 0); - // It appears the prim at index 0 is not always the root prim (for - // instance, when one prim of a link set has been edited independently - // of the others). Therefore, we'll pass all the ids onto the delink - // method for it to decide which is the root. - List prims = new List(); - for (int i = 0; i < delink.ObjectData.Length; i++) - { - prims.Add(delink.ObjectData[i].ObjectLocalID); - } - handlerDelinkObjects = OnDelinkObjects; - if (handlerDelinkObjects != null) - { - handlerDelinkObjects(prims); - } + UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + handlerUpdatePrimSinglePosition(localId, pos1, this); + } + break; + case 2: + Quaternion rot1 = new Quaternion(block.Data, 0, true); - break; - - case PacketType.ObjectAdd: - if (OnAddPrim != null) - { - ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; + if (handlerUpdatePrimSingleRotation != null) + { + // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); + handlerUpdatePrimSingleRotation(localId, rot1, this); + } + break; + case 3: + Vector3 rotPos = new Vector3(block.Data, 0); + Quaternion rot2 = new Quaternion(block.Data, 12, true); - #region Packet Session and User Check - if (m_checkPackets) - { - if (addPacket.AgentData.SessionID != SessionId || - addPacket.AgentData.AgentID != AgentId) + UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; + if (handlerUpdatePrimSingleRotationPosition != null) + { + // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); + // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); + handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); + } break; - } - #endregion + case 4: + case 20: + Vector3 scale4 = new Vector3(block.Data, 0); - PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); - // m_log.Info("[REZData]: " + addPacket.ToString()); - //BypassRaycast: 1 - //RayStart: <69.79469, 158.2652, 98.40343> - //RayEnd: <61.97724, 141.995, 92.58341> - //RayTargetID: 00000000-0000-0000-0000-000000000000 + UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { +// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); + handlerUpdatePrimScale(localId, scale4, this); + } + break; + case 5: - //Check to see if adding the prim is allowed; useful for any module wanting to restrict the - //object from rezing initially + Vector3 scale1 = new Vector3(block.Data, 12); + Vector3 pos11 = new Vector3(block.Data, 0); - handlerAddPrim = OnAddPrim; - if (handlerAddPrim != null) - handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); - } - break; - - case PacketType.ObjectShape: - ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale1, this); - #region Packet Session and User Check - if (m_checkPackets) - { - if (shapePacket.AgentData.SessionID != SessionId || - shapePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos11, this); + } + } + break; + case 9: + Vector3 pos2 = new Vector3(block.Data, 0); - handlerUpdatePrimShape = null; - for (int i = 0; i < shapePacket.ObjectData.Length; i++) - { - handlerUpdatePrimShape = OnUpdatePrimShape; - if (handlerUpdatePrimShape != null) - { - UpdateShapeArgs shapeData = new UpdateShapeArgs(); - shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; - shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; - shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; - shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; - shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; - shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; - shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; - shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; - shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; - shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; - shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; - shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; - shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; - shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; - shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; - shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; - shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; - shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; - shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; - handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, - shapeData); - } - } - break; - - case PacketType.ObjectExtraParams: - ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + if (handlerUpdateVector != null) + { - #region Packet Session and User Check - if (m_checkPackets) - { - if (extraPar.AgentData.SessionID != SessionId || - extraPar.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerUpdateVector(localId, pos2, this); + } + break; + case 10: + Quaternion rot3 = new Quaternion(block.Data, 0, true); - handlerUpdateExtraParams = OnUpdateExtraParams; - if (handlerUpdateExtraParams != null) - { - for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) - { - handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, - extraPar.ObjectData[i].ParamType, - extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); - } - } - break; - case PacketType.ObjectDuplicate: - ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + { + // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); + handlerUpdatePrimRotation(localId, rot3, this); + } + break; + case 11: + Vector3 pos3 = new Vector3(block.Data, 0); + Quaternion rot4 = new Quaternion(block.Data, 12, true); - #region Packet Session and User Check - if (m_checkPackets) - { - if (dupe.AgentData.SessionID != SessionId || - dupe.AgentData.AgentID != AgentId) - break; - } - #endregion + handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; + if (handlerUpdatePrimGroupRotation != null) + { + // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); + handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); + } + break; + case 12: + case 28: + Vector3 scale7 = new Vector3(block.Data, 0); - ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { +// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); + handlerUpdatePrimGroupScale(localId, scale7, this); + } + break; + case 13: + Vector3 scale2 = new Vector3(block.Data, 12); + Vector3 pos4 = new Vector3(block.Data, 0); - handlerObjectDuplicate = null; + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale2, this); - for (int i = 0; i < dupe.ObjectData.Length; i++) - { - handlerObjectDuplicate = OnObjectDuplicate; - if (handlerObjectDuplicate != null) - { - handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, - dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, - AgentandGroupData.GroupID); + // Change the position based on scale (for bug number 246) + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos4, this); + } + } + break; + case 29: + Vector3 scale5 = new Vector3(block.Data, 12); + Vector3 pos5 = new Vector3(block.Data, 0); + + handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimGroupScale(localId, scale5, this); + handlerUpdateVector = OnUpdatePrimGroupPosition; + + if (handlerUpdateVector != null) + { + handlerUpdateVector(localId, pos5, this); + } + } + break; + case 21: + Vector3 scale6 = new Vector3(block.Data, 12); + Vector3 pos6 = new Vector3(block.Data, 0); + + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale6, this); + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos6, this); + } + } + break; + default: + m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + break; } } + } + } + return true; + } - break; + public void RequestMapLayer() + { + //should be getting the map layer from the grid server + //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) + MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); + // TODO: don't create new blocks if recycling an old packet + mapReply.AgentData.AgentID = AgentId; + mapReply.AgentData.Flags = 0; + mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + mapReply.LayerData[0].Bottom = 0; + mapReply.LayerData[0].Left = 0; + mapReply.LayerData[0].Top = 30000; + mapReply.LayerData[0].Right = 30000; + mapReply.LayerData[0].ImageID = new UUID("00000000-0000-1111-9999-000000000006"); + mapReply.Header.Zerocoded = true; + OutPacket(mapReply, ThrottleOutPacketType.Land); + } - case PacketType.RequestMultipleObjects: - RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; + public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY) + { + /* + IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); + MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); + mbReply.AgentData.AgentId = AgentId; + int len; + if (simMapProfiles == null) + len = 0; + else + len = simMapProfiles.Count; - #region Packet Session and User Check - if (m_checkPackets) - { - if (incomingRequest.AgentData.SessionID != SessionId || - incomingRequest.AgentData.AgentID != AgentId) - break; - } - #endregion + mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; + int iii; + for (iii = 0; iii < len; iii++) + { + Hashtable mp = (Hashtable)simMapProfiles[iii]; + mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); + mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); + mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); + mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); + mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); + mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); + mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); + mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); + mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + } + this.OutPacket(mbReply, ThrottleOutPacketType.Land); + */ + } + + /// + /// Sets the throttles from values supplied by the client + /// + /// + public void SetChildAgentThrottle(byte[] throttles) + { + m_udpClient.SetThrottles(throttles); + } - handlerObjectRequest = null; + /// + /// Get the current throttles for this client as a packed byte array + /// + /// Unused + /// + public byte[] GetThrottlesPacked(float multiplier) + { + return m_udpClient.GetThrottlesPacked(); + } - for (int i = 0; i < incomingRequest.ObjectData.Length; i++) + /// + /// Cruft? + /// + public virtual void InPacket(object NewPack) + { + throw new NotImplementedException(); + } + + /// + /// This is the starting point for sending a simulator packet out to the client + /// + /// Packet to send + /// Throttling category for the packet + private void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) + { + m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); + } + + public bool AddMoney(int debit) + { + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); + return true; + } + return false; + } + + /// + /// Breaks down the genericMessagePacket into specific events + /// + /// + /// + /// + public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) + { + switch (gmMethod) + { + case "autopilot": + float locx; + float locy; + float locz; + + try { - handlerObjectRequest = OnObjectRequest; - if (handlerObjectRequest != null) - { - handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); - } + uint regionX; + uint regionY; + Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(Utils.BytesToString(gmParams[0].Parameter)) - regionX; + locy = Convert.ToSingle(Utils.BytesToString(gmParams[1].Parameter)) - regionY; + locz = Convert.ToSingle(Utils.BytesToString(gmParams[2].Parameter)); + } + catch (InvalidCastException) + { + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; } - break; - case PacketType.ObjectSelect: - ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) + UpdateVector handlerAutoPilotGo = OnAutoPilotGo; + if (handlerAutoPilotGo != null) { - if (incomingselect.AgentData.SessionID != SessionId || - incomingselect.AgentData.AgentID != AgentId) - break; + handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); } - #endregion + m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz); - handlerObjectSelect = null; - for (int i = 0; i < incomingselect.ObjectData.Length; i++) + break; + default: + m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice + ". Dumping Params:"); + for (int hi = 0; hi < gmParams.Length; hi++) { - handlerObjectSelect = OnObjectSelect; - if (handlerObjectSelect != null) - { - handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); - } + Console.WriteLine(gmParams[hi].ToString()); } + //gmpack.MethodData. break; - case PacketType.ObjectDeselect: - ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; + + } + } + + /// + /// Entryway from the client to the simulator. All UDP packets from the client will end up here + /// + /// OpenMetaverse.packet + public void ProcessInPacket(Packet Pack) + { + + if (ProcessPacketMethod(Pack)) + { + return; + } + + const bool m_checkPackets = true; + + // Main packet processing conditional + switch (Pack.Type) + { + #region Scene/Avatar + + case PacketType.AvatarPropertiesRequest: + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (incomingdeselect.AgentData.SessionID != SessionId || - incomingdeselect.AgentData.AgentID != AgentId) + if (avatarProperties.AgentData.SessionID != SessionId || + avatarProperties.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectDeselect = null; - - for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) + RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties; + if (handlerRequestAvatarProperties != null) { - handlerObjectDeselect = OnObjectDeselect; - if (handlerObjectDeselect != null) - { - OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); - } + handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); } + break; - case PacketType.ObjectPosition: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectPositionPacket position = (ObjectPositionPacket)Pack; + + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (position.AgentData.SessionID != SessionId || - position.AgentData.AgentID != AgentId) + if (inchatpack.AgentData.SessionID != SessionId || + inchatpack.AgentData.AgentID != AgentId) break; } #endregion - - for (int i = 0; i < position.ObjectData.Length; i++) + string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; + byte[] message = inchatpack.ChatData.Message; + byte type = inchatpack.ChatData.Type; + Vector3 fromPos = new Vector3(); // ClientAvatar.Pos; + // UUID fromAgentID = AgentId; + + int channel = inchatpack.ChatData.Channel; + + if (OnChatFromClient != null) { - handlerUpdateVector = OnUpdatePrimGroupPosition; - if (handlerUpdateVector != null) - handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); - } + OSChatMessage args = new OSChatMessage(); + args.Channel = channel; + args.From = fromName; + args.Message = Utils.BytesToString(message); + args.Type = (ChatTypeEnum)type; + args.Position = fromPos; + + args.Scene = Scene; + args.Sender = this; + args.SenderUUID = this.AgentId; + ChatMessage handlerChatFromClient = OnChatFromClient; + if (handlerChatFromClient != null) + handlerChatFromClient(this, args); + } break; - case PacketType.ObjectScale: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectScalePacket scale = (ObjectScalePacket)Pack; + + case PacketType.AvatarPropertiesUpdate: + AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scale.AgentData.SessionID != SessionId || - scale.AgentData.AgentID != AgentId) + if (avatarProps.AgentData.SessionID != SessionId || + avatarProps.AgentData.AgentID != AgentId) break; } #endregion - for (int i = 0; i < scale.ObjectData.Length; i++) + UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties; + if (handlerUpdateAvatarProperties != null) { - handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; - if (handlerUpdatePrimGroupScale != null) - handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); - } + AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; + UserProfileData UserProfile = new UserProfileData(); + UserProfile.ID = AgentId; + UserProfile.AboutText = Utils.BytesToString(Properties.AboutText); + UserProfile.FirstLifeAboutText = Utils.BytesToString(Properties.FLAboutText); + UserProfile.FirstLifeImage = Properties.FLImageID; + UserProfile.Image = Properties.ImageID; + UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); + handlerUpdateAvatarProperties(this, UserProfile); + } break; - case PacketType.ObjectRotation: - // DEPRECATED: but till libsecondlife removes it, people will use it - ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; + + case PacketType.ScriptDialogReply: + ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rotation.AgentData.SessionID != SessionId || - rotation.AgentData.AgentID != AgentId) + if (rdialog.AgentData.SessionID != SessionId || + rdialog.AgentData.AgentID != AgentId) break; } #endregion - for (int i = 0; i < rotation.ObjectData.Length; i++) + int ch = rdialog.Data.ChatChannel; + byte[] msg = rdialog.Data.ButtonLabel; + if (OnChatFromClient != null) { - handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; - if (handlerUpdatePrimRotation != null) - handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); + OSChatMessage args = new OSChatMessage(); + args.Channel = ch; + args.From = String.Empty; + args.Message = Utils.BytesToString(msg); + args.Type = ChatTypeEnum.Shout; + args.Position = new Vector3(); + args.Scene = Scene; + args.Sender = this; + ChatMessage handlerChatFromClient2 = OnChatFromClient; + if (handlerChatFromClient2 != null) + handlerChatFromClient2(this, args); } break; - case PacketType.ObjectFlagUpdate: - ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + + case PacketType.ImprovedInstantMessage: + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (flags.AgentData.SessionID != SessionId || - flags.AgentData.AgentID != AgentId) + if (msgpack.AgentData.SessionID != SessionId || + msgpack.AgentData.AgentID != AgentId) break; } #endregion - handlerUpdatePrimFlags = OnUpdatePrimFlags; + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); + ImprovedInstantMessage handlerInstantMessage = OnInstantMessage; - if (handlerUpdatePrimFlags != null) + if (handlerInstantMessage != null) { - byte[] data = Pack.ToBytes(); - // 46,47,48 are special positions within the packet - // This may change so perhaps we need a better way - // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) - bool UsePhysics = (data[46] != 0) ? true : false; - bool IsTemporary = (data[47] != 0) ? true : false; - bool IsPhantom = (data[48] != 0) ? true : false; - handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); - } - break; - case PacketType.ObjectImage: - ObjectImagePacket imagePack = (ObjectImagePacket)Pack; + GridInstantMessage im = new GridInstantMessage(Scene, + msgpack.AgentData.AgentID, + IMfromName, + msgpack.MessageBlock.ToAgentID, + msgpack.MessageBlock.Dialog, + msgpack.MessageBlock.FromGroup, + IMmessage, + msgpack.MessageBlock.ID, + msgpack.MessageBlock.Offline != 0 ? true : false, + msgpack.MessageBlock.Position, + msgpack.MessageBlock.BinaryBucket); - handlerUpdatePrimTexture = null; - for (int i = 0; i < imagePack.ObjectData.Length; i++) - { - handlerUpdatePrimTexture = OnUpdatePrimTexture; - if (handlerUpdatePrimTexture != null) - { - handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, - imagePack.ObjectData[i].TextureEntry, this); - } + handlerInstantMessage(this, im); } break; - case PacketType.ObjectGrab: - ObjectGrabPacket grab = (ObjectGrabPacket)Pack; + + case PacketType.AcceptFriendship: + AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (grab.AgentData.SessionID != SessionId || - grab.AgentData.AgentID != AgentId) + if (afriendpack.AgentData.SessionID != SessionId || + afriendpack.AgentData.AgentID != AgentId) break; } #endregion - handlerGrabObject = OnGrabObject; + // My guess is this is the folder to stick the calling card into + List callingCardFolders = new List(); + + UUID agentID = afriendpack.AgentData.AgentID; + UUID transactionID = afriendpack.TransactionBlock.TransactionID; - if (handlerGrabObject != null) + for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) { - List touchArgs = new List(); - if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) - { - foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); + callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); + } + + FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; + if (handlerApproveFriendRequest != null) + { + handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); } break; - case PacketType.ObjectGrabUpdate: - ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; + + case PacketType.DeclineFriendship: + DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (grabUpdate.AgentData.SessionID != SessionId || - grabUpdate.AgentData.AgentID != AgentId) + if (dfriendpack.AgentData.SessionID != SessionId || + dfriendpack.AgentData.AgentID != AgentId) break; } #endregion - handlerGrabUpdate = OnGrabUpdate; - - if (handlerGrabUpdate != null) + if (OnDenyFriendRequest != null) { - List touchArgs = new List(); - if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) - { - foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, - grabUpdate.ObjectData.GrabPosition, this, touchArgs); + OnDenyFriendRequest(this, + dfriendpack.AgentData.AgentID, + dfriendpack.TransactionBlock.TransactionID, + null); } break; - case PacketType.ObjectDeGrab: - ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + + case PacketType.TerminateFriendship: + TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deGrab.AgentData.SessionID != SessionId || - deGrab.AgentData.AgentID != AgentId) + if (tfriendpack.AgentData.SessionID != SessionId || + tfriendpack.AgentData.AgentID != AgentId) break; } #endregion - handlerDeGrabObject = OnDeGrabObject; - if (handlerDeGrabObject != null) + UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; + UUID exFriendID = tfriendpack.ExBlock.OtherID; + + FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship; + if (handlerTerminateFriendship != null) { - List touchArgs = new List(); - if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) - { - foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) - { - SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); - arg.Binormal = surfaceInfo.Binormal; - arg.FaceIndex = surfaceInfo.FaceIndex; - arg.Normal = surfaceInfo.Normal; - arg.Position = surfaceInfo.Position; - arg.STCoord = surfaceInfo.STCoord; - arg.UVCoord = surfaceInfo.UVCoord; - touchArgs.Add(arg); - } - } - handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); + handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); } break; - case PacketType.ObjectSpinStart: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); - ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; + + case PacketType.RezObject: + RezObjectPacket rezPacket = (RezObjectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStart.AgentData.SessionID != SessionId || - spinStart.AgentData.AgentID != AgentId) + if (rezPacket.AgentData.SessionID != SessionId || + rezPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerSpinStart = OnSpinStart; - if (handlerSpinStart != null) + RezObject handlerRezObject = OnRezObject; + if (handlerRezObject != null) { - handlerSpinStart(spinStart.ObjectData.ObjectID, this); + handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, + rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, + rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, + rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, + rezPacket.RezData.FromTaskID); } break; - case PacketType.ObjectSpinUpdate: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); - ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; + + case PacketType.DeRezObject: + DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinUpdate.AgentData.SessionID != SessionId || - spinUpdate.AgentData.AgentID != AgentId) + if (DeRezPacket.AgentData.SessionID != SessionId || + DeRezPacket.AgentData.AgentID != AgentId) break; } #endregion - Vector3 axis; - float angle; - spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); - //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); - - handlerSpinUpdate = OnSpinUpdate; - if (handlerSpinUpdate != null) + DeRezObject handlerDeRezObject = OnDeRezObject; + if (handlerDeRezObject != null) { - handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); + List deRezIDs = new List(); + + foreach (DeRezObjectPacket.ObjectDataBlock data in + DeRezPacket.ObjectData) + { + deRezIDs.Add(data.ObjectLocalID); + } + // It just so happens that the values on the DeRezAction enumerator match the Destination + // values given by a Second Life client + handlerDeRezObject(this, deRezIDs, + DeRezPacket.AgentBlock.GroupID, + (DeRezAction)DeRezPacket.AgentBlock.Destination, + DeRezPacket.AgentBlock.DestinationID); + } break; - case PacketType.ObjectSpinStop: - //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); - ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; + + case PacketType.ModifyLand: + ModifyLandPacket modify = (ModifyLandPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (spinStop.AgentData.SessionID != SessionId || - spinStop.AgentData.AgentID != AgentId) + if (modify.AgentData.SessionID != SessionId || + modify.AgentData.AgentID != AgentId) break; } + #endregion + //m_log.Info("[LAND]: LAND:" + modify.ToString()); + if (modify.ParcelData.Length > 0) + { + if (OnModifyTerrain != null) + { + for (int i = 0; i < modify.ParcelData.Length; i++) + { + ModifyTerrain handlerModifyTerrain = OnModifyTerrain; + if (handlerModifyTerrain != null) + { + handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, + modify.ModifyBlock.BrushSize, + modify.ModifyBlock.Action, modify.ParcelData[i].North, + modify.ParcelData[i].West, modify.ParcelData[i].South, + modify.ParcelData[i].East, AgentId); + } + } + } + } - handlerSpinStop = OnSpinStop; - if (handlerSpinStop != null) + break; + + case PacketType.RegionHandshakeReply: + + Action handlerRegionHandShakeReply = OnRegionHandShakeReply; + if (handlerRegionHandShakeReply != null) { - handlerSpinStop(spinStop.ObjectData.ObjectID, this); + handlerRegionHandShakeReply(this); } + break; - case PacketType.ObjectDescription: - ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; + case PacketType.AgentWearablesRequest: + GenericCall2 handlerRequestWearables = OnRequestWearables; - #region Packet Session and User Check - if (m_checkPackets) + if (handlerRequestWearables != null) { - if (objDes.AgentData.SessionID != SessionId || - objDes.AgentData.AgentID != AgentId) - break; + handlerRequestWearables(); } - #endregion - handlerObjectDescription = null; + Action handlerRequestAvatarsData = OnRequestAvatarsData; - for (int i = 0; i < objDes.ObjectData.Length; i++) + if (handlerRequestAvatarsData != null) { - handlerObjectDescription = OnObjectDescription; - if (handlerObjectDescription != null) - { - handlerObjectDescription(this, objDes.ObjectData[i].LocalID, - Util.FieldToString(objDes.ObjectData[i].Description)); - } + handlerRequestAvatarsData(this); } + break; - case PacketType.ObjectName: - ObjectNamePacket objName = (ObjectNamePacket)Pack; - + + case PacketType.AgentSetAppearance: + AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (objName.AgentData.SessionID != SessionId || - objName.AgentData.AgentID != AgentId) + if (appear.AgentData.SessionID != SessionId || + appear.AgentData.AgentID != AgentId) break; } #endregion - - handlerObjectName = null; - for (int i = 0; i < objName.ObjectData.Length; i++) + + SetAppearance handlerSetAppearance = OnSetAppearance; + if (handlerSetAppearance != null) { - handlerObjectName = OnObjectName; - if (handlerObjectName != null) + // Temporarily protect ourselves from the mantis #951 failure. + // However, we could do this for several other handlers where a failure isn't terminal + // for the client session anyway, in order to protect ourselves against bad code in plugins + try { - handlerObjectName(this, objName.ObjectData[i].LocalID, - Util.FieldToString(objName.ObjectData[i].Name)); + byte[] visualparams = new byte[appear.VisualParam.Length]; + for (int i = 0; i < appear.VisualParam.Length; i++) + visualparams[i] = appear.VisualParam[i].ParamValue; + + Primitive.TextureEntry te = null; + if (appear.ObjectData.TextureEntry.Length > 1) + te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); + + handlerSetAppearance(te, visualparams); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", + e); } } + break; - case PacketType.ObjectPermissions: - if (OnObjectPermissions != null) + + case PacketType.AgentIsNowWearing: + if (OnAvatarNowWearing != null) { - ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; + AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (newobjPerms.AgentData.SessionID != SessionId || - newobjPerms.AgentData.AgentID != AgentId) + if (nowWearing.AgentData.SessionID != SessionId || + nowWearing.AgentData.AgentID != AgentId) break; } #endregion - UUID AgentID = newobjPerms.AgentData.AgentID; - UUID SessionID = newobjPerms.AgentData.SessionID; - - handlerObjectPermissions = null; - - for (int i = 0; i < newobjPerms.ObjectData.Length; i++) + AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); + for (int i = 0; i < nowWearing.WearableData.Length; i++) { - ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; + AvatarWearingArgs.Wearable wearable = + new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, + nowWearing.WearableData[i].WearableType); + wearingArgs.NowWearing.Add(wearable); + } - byte field = permChanges.Field; - uint localID = permChanges.ObjectLocalID; - uint mask = permChanges.Mask; - byte set = permChanges.Set; + AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing; + if (handlerAvatarNowWearing != null) + { + handlerAvatarNowWearing(this, wearingArgs); + } + } + break; - handlerObjectPermissions = OnObjectPermissions; + case PacketType.RezSingleAttachmentFromInv: + RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; + if (handlerRezSingleAttachment != null) + { + RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; - if (handlerObjectPermissions != null) - handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); + #region Packet Session and User Check + if (m_checkPackets) + { + if (rez.AgentData.SessionID != SessionId || + rez.AgentData.AgentID != AgentId) + break; } + #endregion + + handlerRezSingleAttachment(this, rez.ObjectData.ItemID, + rez.ObjectData.AttachmentPt); } - // Here's our data, - // PermField contains the field the info goes into - // PermField determines which mask we're changing - // - // chmask is the mask of the change - // setTF is whether we're adding it or taking it away - // - // objLocalID is the localID of the object. + break; - // Unfortunately, we have to pass the event the packet because objData is an array - // That means multiple object perms may be updated in a single packet. + case PacketType.RezMultipleAttachmentsFromInv: + RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; + if (handlerRezMultipleAttachments != null) + { + RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; + handlerRezMultipleAttachments(this, rez.HeaderData, + rez.ObjectData); + } break; - case PacketType.Undo: - UndoPacket undoitem = (UndoPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + case PacketType.DetachAttachmentIntoInv: + UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; + if (handlerDetachAttachmentIntoInv != null) { - if (undoitem.AgentData.SessionID != SessionId || - undoitem.AgentData.AgentID != AgentId) - break; + DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; + + #region Packet Session and User Check + // UNSUPPORTED ON THIS PACKET + #endregion + + UUID itemID = detachtoInv.ObjectData.ItemID; + // UUID ATTACH_agentID = detachtoInv.ObjectData.AgentID; + + handlerDetachAttachmentIntoInv(itemID, this); } - #endregion + break; - if (undoitem.ObjectData.Length > 0) + case PacketType.ObjectAttach: + if (OnObjectAttach != null) { - for (int i = 0; i < undoitem.ObjectData.Length; i++) + ObjectAttachPacket att = (ObjectAttachPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - UUID objiD = undoitem.ObjectData[i].ObjectID; - handlerOnUndo = OnUndo; - if (handlerOnUndo != null) + if (att.AgentData.SessionID != SessionId || + att.AgentData.AgentID != AgentId) + break; + } + #endregion + + ObjectAttach handlerObjectAttach = OnObjectAttach; + + if (handlerObjectAttach != null) + { + if (att.ObjectData.Length > 0) { - handlerOnUndo(this, objiD); + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); } - } } break; - case PacketType.ObjectDuplicateOnRay: - ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; + + case PacketType.ObjectDetach: + ObjectDetachPacket dett = (ObjectDetachPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dupeOnRay.AgentData.SessionID != SessionId || - dupeOnRay.AgentData.AgentID != AgentId) + if (dett.AgentData.SessionID != SessionId || + dett.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectDuplicateOnRay = null; - - - for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) + for (int j = 0; j < dett.ObjectData.Length; j++) { - handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; - if (handlerObjectDuplicateOnRay != null) + uint obj = dett.ObjectData[j].ObjectLocalID; + ObjectDeselect handlerObjectDetach = OnObjectDetach; + if (handlerObjectDetach != null) { - handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, - dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, - dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); + handlerObjectDetach(obj, this); } - } + } break; - case PacketType.RequestObjectPropertiesFamily: - //This powers the little tooltip that appears when you move your mouse over an object - RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; + + case PacketType.ObjectDrop: + ObjectDropPacket dropp = (ObjectDropPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (packToolTip.AgentData.SessionID != SessionId || - packToolTip.AgentData.AgentID != AgentId) + if (dropp.AgentData.SessionID != SessionId || + dropp.AgentData.AgentID != AgentId) break; } #endregion - RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; - - handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; - - if (handlerRequestObjectPropertiesFamily != null) + for (int j = 0; j < dropp.ObjectData.Length; j++) { - handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, - packObjBlock.ObjectID); + uint obj = dropp.ObjectData[j].ObjectLocalID; + ObjectDrop handlerObjectDrop = OnObjectDrop; + if (handlerObjectDrop != null) + { + handlerObjectDrop(obj, this); + } } - break; - case PacketType.ObjectIncludeInSearch: - //This lets us set objects to appear in search (stuff like DataSnapshot, etc) - ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; - handlerObjectIncludeInSearch = null; + + case PacketType.SetAlwaysRun: + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (packInSearch.AgentData.SessionID != SessionId || - packInSearch.AgentData.AgentID != AgentId) + if (run.AgentData.SessionID != SessionId || + run.AgentData.AgentID != AgentId) break; } #endregion - foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) + SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun; + if (handlerSetAlwaysRun != null) + handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); + + break; + + case PacketType.CompleteAgentMovement: + GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; + if (handlerCompleteMovementToRegion != null) { - bool inSearch = objData.IncludeInSearch; - uint localID = objData.ObjectLocalID; + handlerCompleteMovementToRegion(); + } + handlerCompleteMovementToRegion = null; - handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + break; - if (handlerObjectIncludeInSearch != null) + case PacketType.AgentUpdate: + if (OnAgentUpdate != null) + { + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerObjectIncludeInSearch(this, inSearch, localID); + if (agenUpdate.AgentData.SessionID != SessionId || + agenUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion + + AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; + + // We can only check when we have something to check + // against. + + if (lastarg != null) + { + update = + ( + (x.BodyRotation != lastarg.BodyRotation) || + (x.CameraAtAxis != lastarg.CameraAtAxis) || + (x.CameraCenter != lastarg.CameraCenter) || + (x.CameraLeftAxis != lastarg.CameraLeftAxis) || + (x.CameraUpAxis != lastarg.CameraUpAxis) || + (x.ControlFlags != lastarg.ControlFlags) || + (x.Far != lastarg.Far) || + (x.Flags != lastarg.Flags) || + (x.State != lastarg.State) || + (x.HeadRotation != lastarg.HeadRotation) || + (x.SessionID != lastarg.SessionID) || + (x.AgentID != lastarg.AgentID) + ); + } + else + update = true; + + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + + if (update) + { + AgentUpdateArgs arg = new AgentUpdateArgs(); + arg.AgentID = x.AgentID; + arg.BodyRotation = x.BodyRotation; + arg.CameraAtAxis = x.CameraAtAxis; + arg.CameraCenter = x.CameraCenter; + arg.CameraLeftAxis = x.CameraLeftAxis; + arg.CameraUpAxis = x.CameraUpAxis; + arg.ControlFlags = x.ControlFlags; + arg.Far = x.Far; + arg.Flags = x.Flags; + arg.HeadRotation = x.HeadRotation; + arg.SessionID = x.SessionID; + arg.State = x.State; + UpdateAgent handlerAgentUpdate = OnAgentUpdate; + lastarg = arg; // save this set of arguments for nexttime + if (handlerAgentUpdate != null) + OnAgentUpdate(this, arg); + + handlerAgentUpdate = null; } + } break; - case PacketType.ScriptAnswerYes: - ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; + case PacketType.AgentAnimation: + AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scriptAnswer.AgentData.SessionID != SessionId || - scriptAnswer.AgentData.AgentID != AgentId) + if (AgentAni.AgentData.SessionID != SessionId || + AgentAni.AgentData.AgentID != AgentId) break; } #endregion - handlerScriptAnswer = OnScriptAnswer; - if (handlerScriptAnswer != null) + StartAnim handlerStartAnim = null; + StopAnim handlerStopAnim = null; + + for (int i = 0; i < AgentAni.AnimationList.Length; i++) { - handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); + if (AgentAni.AnimationList[i].StartAnim) + { + handlerStartAnim = OnStartAnim; + if (handlerStartAnim != null) + { + handlerStartAnim(this, AgentAni.AnimationList[i].AnimID); + } + } + else + { + handlerStopAnim = OnStopAnim; + if (handlerStopAnim != null) + { + handlerStopAnim(this, AgentAni.AnimationList[i].AnimID); + } + } } break; - case PacketType.ObjectClickAction: - ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) + case PacketType.AgentRequestSit: + if (OnAgentRequestSit != null) { - if (ocpacket.AgentData.SessionID != SessionId || - ocpacket.AgentData.AgentID != AgentId) - break; + AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (agentRequestSit.AgentData.SessionID != SessionId || + agentRequestSit.AgentData.AgentID != AgentId) + break; + } + #endregion + + AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; + if (handlerAgentRequestSit != null) + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); } - #endregion + break; - handlerObjectClickAction = OnObjectClickAction; - if (handlerObjectClickAction != null) + case PacketType.AgentSit: + if (OnAgentSit != null) { - foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) + AgentSitPacket agentSit = (AgentSitPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - byte action = odata.ClickAction; - uint localID = odata.ObjectLocalID; - handlerObjectClickAction(this, localID, action.ToString()); + if (agentSit.AgentData.SessionID != SessionId || + agentSit.AgentData.AgentID != AgentId) + break; + } + #endregion + + AgentSit handlerAgentSit = OnAgentSit; + if (handlerAgentSit != null) + { + OnAgentSit(this, agentSit.AgentData.AgentID); } } break; - case PacketType.ObjectMaterial: - ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; + case PacketType.SoundTrigger: + SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ompacket.AgentData.SessionID != SessionId || - ompacket.AgentData.AgentID != AgentId) - break; + // UNSUPPORTED ON THIS PACKET } #endregion - handlerObjectMaterial = OnObjectMaterial; - if (handlerObjectMaterial != null) + SoundTrigger handlerSoundTrigger = OnSoundTrigger; + if (handlerSoundTrigger != null) { - foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) - { - byte material = odata.Material; - uint localID = odata.ObjectLocalID; - handlerObjectMaterial(this, localID, material.ToString()); - } + handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, + soundTriggerPacket.SoundData.ObjectID, soundTriggerPacket.SoundData.ParentID, + soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, + soundTriggerPacket.SoundData.Handle); + } break; - #endregion - - #region Inventory/Asset/Other related packets + case PacketType.AvatarPickerRequest: + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; - case PacketType.RequestImage: - RequestImagePacket imageRequest = (RequestImagePacket)Pack; - //m_log.Debug("image request: " + Pack.ToString()); - #region Packet Session and User Check if (m_checkPackets) { - if (imageRequest.AgentData.SessionID != SessionId || - imageRequest.AgentData.AgentID != AgentId) + if (avRequestQuery.AgentData.SessionID != SessionId || + avRequestQuery.AgentData.AgentID != AgentId) break; } #endregion - //handlerTextureRequest = null; + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); - for (int i = 0; i < imageRequest.RequestImage.Length; i++) + AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest; + if (handlerAvatarPickerRequest != null) { - if (OnRequestTexture != null) - { - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = imageRequest.RequestImage[i].Image; - args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; - args.PacketNumber = imageRequest.RequestImage[i].Packet; - args.Priority = imageRequest.RequestImage[i].DownloadPriority; - args.requestSequence = imageRequest.Header.Sequence; - - //handlerTextureRequest = OnRequestTexture; - - //if (handlerTextureRequest != null) - //OnRequestTexture(this, args); - - // in the end, we null this, so we have to check if it's null - if (m_imageManager != null) - { - m_imageManager.EnqueueReq(args); - } - } + handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, + Utils.BytesToString(querydata.Name)); } break; - case PacketType.TransferRequest: - //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); + case PacketType.AgentDataUpdateRequest: + AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; - TransferRequestPacket transfer = (TransferRequestPacket)Pack; - //m_log.Debug("Transfer Request: " + transfer.ToString()); - // Validate inventory transfers - // Has to be done here, because AssetCache can't do it - // - - if (transfer.TransferInfo.SourceType == 3) + #region Packet Session and User Check + if (m_checkPackets) { - UUID taskID = new UUID(transfer.TransferInfo.Params, 48); - UUID itemID = new UUID(transfer.TransferInfo.Params, 64); - UUID requestID = new UUID(transfer.TransferInfo.Params, 80); - if (!(((Scene)m_scene).Permissions.BypassPermissions())) - { - if (taskID != UUID.Zero) // Prim - { - SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); - if (part == null) - break; + if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || + avRequestDataUpdatePacket.AgentData.AgentID != AgentId) + break; + } + #endregion - if (part.OwnerID != AgentId) - break; + FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - break; + if (handlerAgentDataUpdateRequest != null) + { + handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); + } - TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); - if (ti == null) - break; + break; + + case PacketType.UserInfoRequest: + UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest; + if (handlerUserInfoRequest != null) + { + handlerUserInfoRequest(this); + } + else + { + SendUserInfoReply(false, true, ""); + } + break; + + case PacketType.UpdateUserInfo: + UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; - if (ti.OwnerID != AgentId) - break; + #region Packet Session and User Check + if (m_checkPackets) + { + if (updateUserInfo.AgentData.SessionID != SessionId || + updateUserInfo.AgentData.AgentID != AgentId) + break; + } + #endregion - if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - break; + UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo; + if (handlerUpdateUserInfo != null) + { + bool visible = true; + string DirectoryVisibility = + Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); + if (DirectoryVisibility == "hidden") + visible = false; - if (ti.AssetID != requestID) - break; - } - else // Agent - { - IInventoryService invService = m_scene.RequestModuleInterface(); - InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); - assetRequestItem = invService.GetItem(assetRequestItem); - if (assetRequestItem == null) - { - assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); - if (assetRequestItem == null) - return; - } + handlerUpdateUserInfo( + updateUserInfo.UserData.IMViaEMail, + visible, this); + } + break; + + case PacketType.SetStartLocationRequest: + SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; - // At this point, we need to apply perms - // only to notecards and scripts. All - // other asset types are always available - // - if (assetRequestItem.AssetType == 10) - { - if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view script", false); - break; - } - } - else if (assetRequestItem.AssetType == 7) - { - if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view notecard", false); - break; - } - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || + avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - if (assetRequestItem.AssetID != requestID) - break; - } + if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) + { + TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest; + if (handlerSetStartLocationRequest != null) + { + handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, + avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, + avSetStartLocationRequestPacket.StartLocationData.LocationID); } } + break; - //m_assetCache.AddAssetRequest(this, transfer); + case PacketType.AgentThrottle: + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; - MakeAssetRequest(transfer); + #region Packet Session and User Check + if (m_checkPackets) + { + if (atpack.AgentData.SessionID != SessionId || + atpack.AgentData.AgentID != AgentId) + break; + } + #endregion - /* RequestAsset = OnRequestAsset; - if (RequestAsset != null) - { - RequestAsset(this, transfer); - }*/ + m_udpClient.SetThrottles(atpack.Throttle.Throttles); break; - case PacketType.AssetUploadRequest: - AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - - // m_log.Debug("upload request " + request.ToString()); - // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); - UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); + case PacketType.AgentPause: + m_udpClient.IsPaused = true; + break; - handlerAssetUploadRequest = OnAssetUploadRequest; + case PacketType.AgentResume: + m_udpClient.IsPaused = false; + SendStartPingCheck(m_udpClient.CurrentPingSequence++); - if (handlerAssetUploadRequest != null) - { - handlerAssetUploadRequest(this, temp, - request.AssetBlock.TransactionID, request.AssetBlock.Type, - request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, - request.AssetBlock.Tempfile); - } break; - case PacketType.RequestXfer: - RequestXferPacket xferReq = (RequestXferPacket)Pack; - - handlerRequestXfer = OnRequestXfer; - if (handlerRequestXfer != null) + case PacketType.ForceScriptControlRelease: + ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls; + if (handlerForceReleaseControls != null) { - handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + handlerForceReleaseControls(this, AgentId); } break; - case PacketType.SendXferPacket: - SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; - handlerXferReceive = OnXferReceive; - if (handlerXferReceive != null) + #endregion + + #region Objects/m_sceneObjects + + case PacketType.ObjectLink: + ObjectLinkPacket link = (ObjectLinkPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + if (link.AgentData.SessionID != SessionId || + link.AgentData.AgentID != AgentId) + break; } - break; - case PacketType.ConfirmXferPacket: - ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; - - handlerConfirmXfer = OnConfirmXfer; - if (handlerConfirmXfer != null) + #endregion + + uint parentprimid = 0; + List childrenprims = new List(); + if (link.ObjectData.Length > 1) { - handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); + parentprimid = link.ObjectData[0].ObjectLocalID; + + for (int i = 1; i < link.ObjectData.Length; i++) + { + childrenprims.Add(link.ObjectData[i].ObjectLocalID); + } } - break; - case PacketType.AbortXfer: - AbortXferPacket abortXfer = (AbortXferPacket)Pack; - handlerAbortXfer = OnAbortXfer; - if (handlerAbortXfer != null) + LinkObjects handlerLinkObjects = OnLinkObjects; + if (handlerLinkObjects != null) { - handlerAbortXfer(this, abortXfer.XferID.ID); + handlerLinkObjects(this, parentprimid, childrenprims); } - break; - case PacketType.CreateInventoryFolder: - CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; + + case PacketType.ObjectDelink: + ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFolder.AgentData.SessionID != SessionId || - invFolder.AgentData.AgentID != AgentId) + if (delink.AgentData.SessionID != SessionId || + delink.AgentData.AgentID != AgentId) break; } #endregion - handlerCreateInventoryFolder = OnCreateNewInventoryFolder; - if (handlerCreateInventoryFolder != null) + // It appears the prim at index 0 is not always the root prim (for + // instance, when one prim of a link set has been edited independently + // of the others). Therefore, we'll pass all the ids onto the delink + // method for it to decide which is the root. + List prims = new List(); + for (int i = 0; i < delink.ObjectData.Length; i++) { - handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, - (ushort)invFolder.FolderData.Type, - Util.FieldToString(invFolder.FolderData.Name), - invFolder.FolderData.ParentID); + prims.Add(delink.ObjectData[i].ObjectLocalID); + } + DelinkObjects handlerDelinkObjects = OnDelinkObjects; + if (handlerDelinkObjects != null) + { + handlerDelinkObjects(prims); } + break; - case PacketType.UpdateInventoryFolder: - if (OnUpdateInventoryFolder != null) + + case PacketType.ObjectAdd: + if (OnAddPrim != null) { - UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; + ObjectAddPacket addPacket = (ObjectAddPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (invFolderx.AgentData.SessionID != SessionId || - invFolderx.AgentData.AgentID != AgentId) + if (addPacket.AgentData.SessionID != SessionId || + addPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerUpdateInventoryFolder = null; + PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); + // m_log.Info("[REZData]: " + addPacket.ToString()); + //BypassRaycast: 1 + //RayStart: <69.79469, 158.2652, 98.40343> + //RayEnd: <61.97724, 141.995, 92.58341> + //RayTargetID: 00000000-0000-0000-0000-000000000000 - for (int i = 0; i < invFolderx.FolderData.Length; i++) - { - handlerUpdateInventoryFolder = OnUpdateInventoryFolder; - if (handlerUpdateInventoryFolder != null) - { - OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, - (ushort)invFolderx.FolderData[i].Type, - Util.FieldToString(invFolderx.FolderData[i].Name), - invFolderx.FolderData[i].ParentID); - } - } + //Check to see if adding the prim is allowed; useful for any module wanting to restrict the + //object from rezing initially + + AddNewPrim handlerAddPrim = OnAddPrim; + if (handlerAddPrim != null) + handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); } break; - case PacketType.MoveInventoryFolder: - if (OnMoveInventoryFolder != null) + + case PacketType.ObjectShape: + ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; + if (shapePacket.AgentData.SessionID != SessionId || + shapePacket.AgentData.AgentID != AgentId) + break; + } + #endregion - #region Packet Session and User Check - if (m_checkPackets) + UpdateShape handlerUpdatePrimShape = null; + for (int i = 0; i < shapePacket.ObjectData.Length; i++) + { + handlerUpdatePrimShape = OnUpdatePrimShape; + if (handlerUpdatePrimShape != null) { - if (invFoldery.AgentData.SessionID != SessionId || - invFoldery.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerMoveInventoryFolder = null; + UpdateShapeArgs shapeData = new UpdateShapeArgs(); + shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID; + shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin; + shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve; + shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd; + shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset; + shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions; + shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX; + shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY; + shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX; + shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY; + shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew; + shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX; + shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY; + shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist; + shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin; + shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin; + shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve; + shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd; + shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow; - for (int i = 0; i < invFoldery.InventoryData.Length; i++) - { - handlerMoveInventoryFolder = OnMoveInventoryFolder; - if (handlerMoveInventoryFolder != null) - { - OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, - invFoldery.InventoryData[i].ParentID); - } + handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, + shapeData); } } break; - case PacketType.CreateInventoryItem: - CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; - + + case PacketType.ObjectExtraParams: + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (createItem.AgentData.SessionID != SessionId || - createItem.AgentData.AgentID != AgentId) + if (extraPar.AgentData.SessionID != SessionId || + extraPar.AgentData.AgentID != AgentId) break; } #endregion - handlerCreateNewInventoryItem = OnCreateNewInventoryItem; - if (handlerCreateNewInventoryItem != null) - { - handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, - createItem.InventoryBlock.FolderID, - createItem.InventoryBlock.CallbackID, - Util.FieldToString(createItem.InventoryBlock.Description), - Util.FieldToString(createItem.InventoryBlock.Name), - createItem.InventoryBlock.InvType, - createItem.InventoryBlock.Type, - createItem.InventoryBlock.WearableType, - createItem.InventoryBlock.NextOwnerMask, - Util.UnixTimeSinceEpoch()); - } - break; - case PacketType.FetchInventory: - if (OnFetchInventory != null) + ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams; + if (handlerUpdateExtraParams != null) { - FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (FetchInventoryx.AgentData.SessionID != SessionId || - FetchInventoryx.AgentData.AgentID != AgentId) - break; - } - #endregion - - handlerFetchInventory = null; - - for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) + for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) { - handlerFetchInventory = OnFetchInventory; - - if (handlerFetchInventory != null) - { - OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, - FetchInventoryx.InventoryData[i].OwnerID); - } + handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, + extraPar.ObjectData[i].ParamType, + extraPar.ObjectData[i].ParamInUse, extraPar.ObjectData[i].ParamData); } } break; - case PacketType.FetchInventoryDescendents: - FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Fetch.AgentData.SessionID != SessionId || - Fetch.AgentData.AgentID != AgentId) + if (dupe.AgentData.SessionID != SessionId || + dupe.AgentData.AgentID != AgentId) break; } #endregion - handlerFetchInventoryDescendents = OnFetchInventoryDescendents; - if (handlerFetchInventoryDescendents != null) + ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + + ObjectDuplicate handlerObjectDuplicate = null; + + for (int i = 0; i < dupe.ObjectData.Length; i++) { - handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, - Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, - Fetch.InventoryData.SortOrder); + handlerObjectDuplicate = OnObjectDuplicate; + if (handlerObjectDuplicate != null) + { + handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, + dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, + AgentandGroupData.GroupID); + } } + break; - case PacketType.PurgeInventoryDescendents: - PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + + case PacketType.RequestMultipleObjects: + RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (Purge.AgentData.SessionID != SessionId || - Purge.AgentData.AgentID != AgentId) + if (incomingRequest.AgentData.SessionID != SessionId || + incomingRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; - if (handlerPurgeInventoryDescendents != null) + ObjectRequest handlerObjectRequest = null; + + for (int i = 0; i < incomingRequest.ObjectData.Length; i++) { - handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + handlerObjectRequest = OnObjectRequest; + if (handlerObjectRequest != null) + { + handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); + } } break; - case PacketType.UpdateInventoryItem: - UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; - + case PacketType.ObjectSelect: + ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (inventoryItemUpdate.AgentData.SessionID != SessionId || - inventoryItemUpdate.AgentData.AgentID != AgentId) + if (incomingselect.AgentData.SessionID != SessionId || + incomingselect.AgentData.AgentID != AgentId) break; } #endregion - if (OnUpdateInventoryItem != null) + ObjectSelect handlerObjectSelect = null; + + for (int i = 0; i < incomingselect.ObjectData.Length; i++) { - handlerUpdateInventoryItem = null; - for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + handlerObjectSelect = OnObjectSelect; + if (handlerObjectSelect != null) { - handlerUpdateInventoryItem = OnUpdateInventoryItem; - - if (handlerUpdateInventoryItem != null) - { - InventoryItemBase itemUpd = new InventoryItemBase(); - itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; - itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); - itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); - itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; - itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; - itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; - itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; - itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; - itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; - itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; - itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; - itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; - itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; - itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; - /* - OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, - inventoryItemUpdate.InventoryData[i].ItemID, - Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name), - Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description), - inventoryItemUpdate.InventoryData[i].NextOwnerMask); - */ - OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, - inventoryItemUpdate.InventoryData[i].ItemID, - itemUpd); - } + handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); } } - //m_log.Debug(Pack.ToString()); - /*for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) - { - if (inventoryItemUpdate.InventoryData[i].TransactionID != UUID.Zero) - { - AssetBase asset = m_assetCache.GetAsset(inventoryItemUpdate.InventoryData[i].TransactionID.Combine(this.SecureSessionId)); - if (asset != null) - { - // m_log.Debug("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache"); - m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); - } - else - { - asset = this.UploadAssets.AddUploadToAssetCache(inventoryItemUpdate.InventoryData[i].TransactionID); - if (asset != null) - { - //m_log.Debug("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache"); - m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset); - } - else - { - //m_log.Debug("trying to update inventory item, but asset is null"); - } - } - } - else - { - m_inventoryCache.UpdateInventoryItemDetails(this, inventoryItemUpdate.InventoryData[i].ItemID, inventoryItemUpdate.InventoryData[i]); ; - } - }*/ break; - case PacketType.CopyInventoryItem: - CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; + case PacketType.ObjectDeselect: + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (copyitem.AgentData.SessionID != SessionId || - copyitem.AgentData.AgentID != AgentId) + if (incomingdeselect.AgentData.SessionID != SessionId || + incomingdeselect.AgentData.AgentID != AgentId) break; } #endregion - handlerCopyInventoryItem = null; - if (OnCopyInventoryItem != null) + ObjectDeselect handlerObjectDeselect = null; + + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) { - foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + handlerObjectDeselect = OnObjectDeselect; + if (handlerObjectDeselect != null) { - handlerCopyInventoryItem = OnCopyInventoryItem; - if (handlerCopyInventoryItem != null) - { - handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, - datablock.OldItemID, datablock.NewFolderID, - Util.FieldToString(datablock.NewName)); - } + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); } } break; - case PacketType.MoveInventoryItem: - MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; + case PacketType.ObjectPosition: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectPositionPacket position = (ObjectPositionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moveitem.AgentData.SessionID != SessionId || - moveitem.AgentData.AgentID != AgentId) + if (position.AgentData.SessionID != SessionId || + position.AgentData.AgentID != AgentId) break; } #endregion - if (OnMoveInventoryItem != null) + + for (int i = 0; i < position.ObjectData.Length; i++) { - handlerMoveInventoryItem = null; - InventoryItemBase itm = null; - List items = new List(); - foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) - { - itm = new InventoryItemBase(datablock.ItemID, AgentId); - itm.Folder = datablock.FolderID; - itm.Name = Util.FieldToString(datablock.NewName); - // weird, comes out as empty string - //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); - items.Add(itm); - } - handlerMoveInventoryItem = OnMoveInventoryItem; - if (handlerMoveInventoryItem != null) - { - handlerMoveInventoryItem(this, items); - } + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; + if (handlerUpdateVector != null) + handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); } + break; - case PacketType.RemoveInventoryItem: - RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; + case PacketType.ObjectScale: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectScalePacket scale = (ObjectScalePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeItem.AgentData.SessionID != SessionId || - removeItem.AgentData.AgentID != AgentId) + if (scale.AgentData.SessionID != SessionId || + scale.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryItem != null) + for (int i = 0; i < scale.ObjectData.Length; i++) { - handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) - { - handlerRemoveInventoryItem(this, uuids); - } - + UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); } + break; - case PacketType.RemoveInventoryFolder: - RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; + case PacketType.ObjectRotation: + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeFolder.AgentData.SessionID != SessionId || - removeFolder.AgentData.AgentID != AgentId) + if (rotation.AgentData.SessionID != SessionId || + rotation.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryFolder != null) + for (int i = 0; i < rotation.ObjectData.Length; i++) { - handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder(this, uuids); - } + UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); } + break; - case PacketType.RemoveInventoryObjects: - RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; + case PacketType.ObjectFlagUpdate: + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (removeObject.AgentData.SessionID != SessionId || - removeObject.AgentData.AgentID != AgentId) + if (flags.AgentData.SessionID != SessionId || + flags.AgentData.AgentID != AgentId) break; } #endregion - if (OnRemoveInventoryFolder != null) + + UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags; + + if (handlerUpdatePrimFlags != null) { - handlerRemoveInventoryFolder = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) - { - uuids.Add(datablock.FolderID); - } - handlerRemoveInventoryFolder = OnRemoveInventoryFolder; - if (handlerRemoveInventoryFolder != null) - { - handlerRemoveInventoryFolder(this, uuids); - } + byte[] data = Pack.ToBytes(); + // 46,47,48 are special positions within the packet + // This may change so perhaps we need a better way + // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) + bool UsePhysics = (data[46] != 0) ? true : false; + bool IsTemporary = (data[47] != 0) ? true : false; + bool IsPhantom = (data[48] != 0) ? true : false; + handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); } + break; + case PacketType.ObjectImage: + ObjectImagePacket imagePack = (ObjectImagePacket)Pack; - if (OnRemoveInventoryItem != null) + UpdatePrimTexture handlerUpdatePrimTexture = null; + for (int i = 0; i < imagePack.ObjectData.Length; i++) { - handlerRemoveInventoryItem = null; - List uuids = new List(); - foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) - { - uuids.Add(datablock.ItemID); - } - handlerRemoveInventoryItem = OnRemoveInventoryItem; - if (handlerRemoveInventoryItem != null) + handlerUpdatePrimTexture = OnUpdatePrimTexture; + if (handlerUpdatePrimTexture != null) { - handlerRemoveInventoryItem(this, uuids); + handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, + imagePack.ObjectData[i].TextureEntry, this); } } break; - case PacketType.RequestTaskInventory: - RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; + case PacketType.ObjectGrab: + ObjectGrabPacket grab = (ObjectGrabPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (requesttask.AgentData.SessionID != SessionId || - requesttask.AgentData.AgentID != AgentId) + if (grab.AgentData.SessionID != SessionId || + grab.AgentData.AgentID != AgentId) break; } #endregion - handlerRequestTaskInventory = OnRequestTaskInventory; - if (handlerRequestTaskInventory != null) + GrabObject handlerGrabObject = OnGrabObject; + + if (handlerGrabObject != null) { - handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); + List touchArgs = new List(); + if ((grab.SurfaceInfo != null) && (grab.SurfaceInfo.Length > 0)) + { + foreach (ObjectGrabPacket.SurfaceInfoBlock surfaceInfo in grab.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } + } + handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this, touchArgs); } break; - case PacketType.UpdateTaskInventory: - UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; + case PacketType.ObjectGrabUpdate: + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (updatetask.AgentData.SessionID != SessionId || - updatetask.AgentData.AgentID != AgentId) + if (grabUpdate.AgentData.SessionID != SessionId || + grabUpdate.AgentData.AgentID != AgentId) break; } #endregion - if (OnUpdateTaskInventory != null) + MoveObject handlerGrabUpdate = OnGrabUpdate; + + if (handlerGrabUpdate != null) { - if (updatetask.UpdateData.Key == 0) + List touchArgs = new List(); + if ((grabUpdate.SurfaceInfo != null) && (grabUpdate.SurfaceInfo.Length > 0)) { - handlerUpdateTaskInventory = OnUpdateTaskInventory; - if (handlerUpdateTaskInventory != null) + foreach (ObjectGrabUpdatePacket.SurfaceInfoBlock surfaceInfo in grabUpdate.SurfaceInfo) { - TaskInventoryItem newTaskItem = new TaskInventoryItem(); - newTaskItem.ItemID = updatetask.InventoryData.ItemID; - newTaskItem.ParentID = updatetask.InventoryData.FolderID; - newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; - newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; - newTaskItem.GroupID = updatetask.InventoryData.GroupID; - newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; - newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; - newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; - newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; - newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; - //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; - newTaskItem.Type = updatetask.InventoryData.Type; - newTaskItem.InvType = updatetask.InventoryData.InvType; - newTaskItem.Flags = updatetask.InventoryData.Flags; - //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; - newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); - newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); - newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; - handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, - newTaskItem, updatetask.UpdateData.LocalID); + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); } } + handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, + grabUpdate.ObjectData.GrabPosition, this, touchArgs); } - break; - - case PacketType.RemoveTaskInventory: - - RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; + case PacketType.ObjectDeGrab: + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (removeTask.AgentData.SessionID != SessionId || - removeTask.AgentData.AgentID != AgentId) + if (deGrab.AgentData.SessionID != SessionId || + deGrab.AgentData.AgentID != AgentId) break; } #endregion - handlerRemoveTaskItem = OnRemoveTaskItem; - - if (handlerRemoveTaskItem != null) + DeGrabObject handlerDeGrabObject = OnDeGrabObject; + if (handlerDeGrabObject != null) { - handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); + List touchArgs = new List(); + if ((deGrab.SurfaceInfo != null) && (deGrab.SurfaceInfo.Length > 0)) + { + foreach (ObjectDeGrabPacket.SurfaceInfoBlock surfaceInfo in deGrab.SurfaceInfo) + { + SurfaceTouchEventArgs arg = new SurfaceTouchEventArgs(); + arg.Binormal = surfaceInfo.Binormal; + arg.FaceIndex = surfaceInfo.FaceIndex; + arg.Normal = surfaceInfo.Normal; + arg.Position = surfaceInfo.Position; + arg.STCoord = surfaceInfo.STCoord; + arg.UVCoord = surfaceInfo.UVCoord; + touchArgs.Add(arg); + } + } + handlerDeGrabObject(deGrab.ObjectData.LocalID, this, touchArgs); } - break; - - case PacketType.MoveTaskInventory: - - MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; + case PacketType.ObjectSpinStart: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); + ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || - moveTaskInventoryPacket.AgentData.AgentID != AgentId) + if (spinStart.AgentData.SessionID != SessionId || + spinStart.AgentData.AgentID != AgentId) break; } #endregion - handlerMoveTaskItem = OnMoveTaskItem; - - if (handlerMoveTaskItem != null) + SpinStart handlerSpinStart = OnSpinStart; + if (handlerSpinStart != null) { - handlerMoveTaskItem( - this, moveTaskInventoryPacket.AgentData.FolderID, - moveTaskInventoryPacket.InventoryData.LocalID, - moveTaskInventoryPacket.InventoryData.ItemID); + handlerSpinStart(spinStart.ObjectData.ObjectID, this); } - break; - - case PacketType.RezScript: - //m_log.Debug(Pack.ToString()); - RezScriptPacket rezScriptx = (RezScriptPacket)Pack; + case PacketType.ObjectSpinUpdate: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); + ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rezScriptx.AgentData.SessionID != SessionId || - rezScriptx.AgentData.AgentID != AgentId) + if (spinUpdate.AgentData.SessionID != SessionId || + spinUpdate.AgentData.AgentID != AgentId) break; } #endregion - handlerRezScript = OnRezScript; - InventoryItemBase item = new InventoryItemBase(); - item.ID = rezScriptx.InventoryBlock.ItemID; - item.Folder = rezScriptx.InventoryBlock.FolderID; - item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); - item.Owner = rezScriptx.InventoryBlock.OwnerID; - item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; - item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; - item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; - item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; - item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; - item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; - item.GroupID = rezScriptx.InventoryBlock.GroupID; - item.AssetType = rezScriptx.InventoryBlock.Type; - item.InvType = rezScriptx.InventoryBlock.InvType; - item.Flags = rezScriptx.InventoryBlock.Flags; - item.SaleType = rezScriptx.InventoryBlock.SaleType; - item.SalePrice = rezScriptx.InventoryBlock.SalePrice; - item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); - item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); - item.CreationDate = rezScriptx.InventoryBlock.CreationDate; + Vector3 axis; + float angle; + spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); + //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); - if (handlerRezScript != null) + SpinObject handlerSpinUpdate = OnSpinUpdate; + if (handlerSpinUpdate != null) { - handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); + handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); } break; - - case PacketType.MapLayerRequest: - RequestMapLayer(); - break; - case PacketType.MapBlockRequest: - MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; + case PacketType.ObjectSpinStop: + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); + ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (MapRequest.AgentData.SessionID != SessionId || - MapRequest.AgentData.AgentID != AgentId) + if (spinStop.AgentData.SessionID != SessionId || + spinStop.AgentData.AgentID != AgentId) break; } #endregion - handlerRequestMapBlocks = OnRequestMapBlocks; - if (handlerRequestMapBlocks != null) + SpinStop handlerSpinStop = OnSpinStop; + if (handlerSpinStop != null) { - handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, - MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); + handlerSpinStop(spinStop.ObjectData.ObjectID, this); } break; - case PacketType.MapNameRequest: - MapNameRequestPacket map = (MapNameRequestPacket)Pack; + + case PacketType.ObjectDescription: + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (map.AgentData.SessionID != SessionId || - map.AgentData.AgentID != AgentId) + if (objDes.AgentData.SessionID != SessionId || + objDes.AgentData.AgentID != AgentId) break; } #endregion - string mapName = Util.UTF8.GetString(map.NameData.Name, 0, - map.NameData.Name.Length - 1); - handlerMapNameRequest = OnMapNameRequest; - if (handlerMapNameRequest != null) + GenericCall7 handlerObjectDescription = null; + + for (int i = 0; i < objDes.ObjectData.Length; i++) { - handlerMapNameRequest(this, mapName); + handlerObjectDescription = OnObjectDescription; + if (handlerObjectDescription != null) + { + handlerObjectDescription(this, objDes.ObjectData[i].LocalID, + Util.FieldToString(objDes.ObjectData[i].Description)); + } } break; - case PacketType.TeleportLandmarkRequest: - TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; - + case PacketType.ObjectName: + ObjectNamePacket objName = (ObjectNamePacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (tpReq.Info.SessionID != SessionId || - tpReq.Info.AgentID != AgentId) + if (objName.AgentData.SessionID != SessionId || + objName.AgentData.AgentID != AgentId) break; } #endregion - - UUID lmid = tpReq.Info.LandmarkID; - AssetLandmark lm; - if (lmid != UUID.Zero) + + GenericCall7 handlerObjectName = null; + for (int i = 0; i < objName.ObjectData.Length; i++) { - //AssetBase lma = m_assetCache.GetAsset(lmid, false); - AssetBase lma = m_assetService.Get(lmid.ToString()); - - if (lma == null) - { - // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - } - - try - { - lm = new AssetLandmark(lma); - } - catch (NullReferenceException) + handlerObjectName = OnObjectName; + if (handlerObjectName != null) { - // asset not found generates null ref inside the assetlandmark constructor. - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); - break; + handlerObjectName(this, objName.ObjectData[i].LocalID, + Util.FieldToString(objName.ObjectData[i].Name)); } } - else + break; + case PacketType.ObjectPermissions: + if (OnObjectPermissions != null) { - // Teleport home request - handlerTeleportHomeRequest = OnTeleportHomeRequest; - if (handlerTeleportHomeRequest != null) + ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - handlerTeleportHomeRequest(AgentId, this); + if (newobjPerms.AgentData.SessionID != SessionId || + newobjPerms.AgentData.AgentID != AgentId) + break; } - break; - } + #endregion - handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; - if (handlerTeleportLandmarkRequest != null) - { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); - } - else - { - //no event handler so cancel request + UUID AgentID = newobjPerms.AgentData.AgentID; + UUID SessionID = newobjPerms.AgentData.SessionID; + ObjectPermissions handlerObjectPermissions = null; - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.AgentID = tpReq.Info.AgentID; - tpCancel.Info.SessionID = tpReq.Info.SessionID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + for (int i = 0; i < newobjPerms.ObjectData.Length; i++) + { + ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; + + byte field = permChanges.Field; + uint localID = permChanges.ObjectLocalID; + uint mask = permChanges.Mask; + byte set = permChanges.Set; + + handlerObjectPermissions = OnObjectPermissions; + if (handlerObjectPermissions != null) + handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); + } } + + // Here's our data, + // PermField contains the field the info goes into + // PermField determines which mask we're changing + // + // chmask is the mask of the change + // setTF is whether we're adding it or taking it away + // + // objLocalID is the localID of the object. + + // Unfortunately, we have to pass the event the packet because objData is an array + // That means multiple object perms may be updated in a single packet. + break; - case PacketType.TeleportLocationRequest: - TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; - // m_log.Debug(tpLocReq.ToString()); + case PacketType.Undo: + UndoPacket undoitem = (UndoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (tpLocReq.AgentData.SessionID != SessionId || - tpLocReq.AgentData.AgentID != AgentId) + if (undoitem.AgentData.SessionID != SessionId || + undoitem.AgentData.AgentID != AgentId) break; } #endregion - handlerTeleportLocationRequest = OnTeleportLocationRequest; - if (handlerTeleportLocationRequest != null) - { - handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, - tpLocReq.Info.LookAt, 16); - } - else + if (undoitem.ObjectData.Length > 0) { - //no event handler so cancel request - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; - tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + for (int i = 0; i < undoitem.ObjectData.Length; i++) + { + UUID objiD = undoitem.ObjectData[i].ObjectID; + AgentSit handlerOnUndo = OnUndo; + if (handlerOnUndo != null) + { + handlerOnUndo(this, objiD); + } + + } } break; + case PacketType.ObjectDuplicateOnRay: + ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (dupeOnRay.AgentData.SessionID != SessionId || + dupeOnRay.AgentData.AgentID != AgentId) + break; + } #endregion - case PacketType.UUIDNameRequest: - UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null; - foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) { - handlerNameRequest = OnNameFromUUIDRequest; - if (handlerNameRequest != null) + handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; + if (handlerObjectDuplicateOnRay != null) { - handlerNameRequest(UUIDBlock.ID, this); + handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, + dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, + dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); } } - break; - - #region Parcel related packets - - case PacketType.RegionHandleRequest: - RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; - handlerRegionHandleRequest = OnRegionHandleRequest; - if (handlerRegionHandleRequest != null) - { - handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); - } break; - - case PacketType.ParcelInfoRequest: - ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; + case PacketType.RequestObjectPropertiesFamily: + //This powers the little tooltip that appears when you move your mouse over an object + RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pirPack.AgentData.SessionID != SessionId || - pirPack.AgentData.AgentID != AgentId) + if (packToolTip.AgentData.SessionID != SessionId || + packToolTip.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelInfoRequest = OnParcelInfoRequest; - if (handlerParcelInfoRequest != null) + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + + RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; + + if (handlerRequestObjectPropertiesFamily != null) { - handlerParcelInfoRequest(this, pirPack.Data.ParcelID); + handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, + packObjBlock.ObjectID); } - break; - case PacketType.ParcelAccessListRequest: - ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; + break; + case PacketType.ObjectIncludeInSearch: + //This lets us set objects to appear in search (stuff like DataSnapshot, etc) + ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; + ObjectIncludeInSearch handlerObjectIncludeInSearch = null; #region Packet Session and User Check if (m_checkPackets) { - if (requestPacket.AgentData.SessionID != SessionId || - requestPacket.AgentData.AgentID != AgentId) + if (packInSearch.AgentData.SessionID != SessionId || + packInSearch.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelAccessListRequest = OnParcelAccessListRequest; - - if (handlerParcelAccessListRequest != null) + foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) { - handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, - requestPacket.Data.Flags, requestPacket.Data.SequenceID, - requestPacket.Data.LocalID, this); - } - break; - - case PacketType.ParcelAccessListUpdate: - ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (updatePacket.AgentData.SessionID != SessionId || - updatePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + bool inSearch = objData.IncludeInSearch; + uint localID = objData.ObjectLocalID; - List entries = new List(); - foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = block.ID; - entry.Flags = (AccessList)block.Flags; - entry.Time = new DateTime(); - entries.Add(entry); - } + handlerObjectIncludeInSearch = OnObjectIncludeInSearch; - handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; - if (handlerParcelAccessListUpdateRequest != null) - { - handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, - updatePacket.AgentData.SessionID, updatePacket.Data.Flags, - updatePacket.Data.LocalID, entries, this); + if (handlerObjectIncludeInSearch != null) + { + handlerObjectIncludeInSearch(this, inSearch, localID); + } } break; - case PacketType.ParcelPropertiesRequest: - ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; + case PacketType.ScriptAnswerYes: + ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (propertiesRequest.AgentData.SessionID != SessionId || - propertiesRequest.AgentData.AgentID != AgentId) + if (scriptAnswer.AgentData.SessionID != SessionId || + scriptAnswer.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelPropertiesRequest = OnParcelPropertiesRequest; - if (handlerParcelPropertiesRequest != null) + ScriptAnswer handlerScriptAnswer = OnScriptAnswer; + if (handlerScriptAnswer != null) { - handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), - (int)Math.Round(propertiesRequest.ParcelData.South), - (int)Math.Round(propertiesRequest.ParcelData.East), - (int)Math.Round(propertiesRequest.ParcelData.North), - propertiesRequest.ParcelData.SequenceID, - propertiesRequest.ParcelData.SnapSelection, this); + handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); } break; - case PacketType.ParcelDivide: - ParcelDividePacket landDivide = (ParcelDividePacket)Pack; + + case PacketType.ObjectClickAction: + ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (landDivide.AgentData.SessionID != SessionId || - landDivide.AgentData.AgentID != AgentId) + if (ocpacket.AgentData.SessionID != SessionId || + ocpacket.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelDivideRequest = OnParcelDivideRequest; - if (handlerParcelDivideRequest != null) + GenericCall7 handlerObjectClickAction = OnObjectClickAction; + if (handlerObjectClickAction != null) { - handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), - (int)Math.Round(landDivide.ParcelData.South), - (int)Math.Round(landDivide.ParcelData.East), - (int)Math.Round(landDivide.ParcelData.North), this); + foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) + { + byte action = odata.ClickAction; + uint localID = odata.ObjectLocalID; + handlerObjectClickAction(this, localID, action.ToString()); + } } break; - case PacketType.ParcelJoin: - ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; + + case PacketType.ObjectMaterial: + ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (landJoin.AgentData.SessionID != SessionId || - landJoin.AgentData.AgentID != AgentId) + if (ompacket.AgentData.SessionID != SessionId || + ompacket.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelJoinRequest = OnParcelJoinRequest; - - if (handlerParcelJoinRequest != null) + GenericCall7 handlerObjectMaterial = OnObjectMaterial; + if (handlerObjectMaterial != null) { - handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), - (int)Math.Round(landJoin.ParcelData.South), - (int)Math.Round(landJoin.ParcelData.East), - (int)Math.Round(landJoin.ParcelData.North), this); + foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) + { + byte material = odata.Material; + uint localID = odata.ObjectLocalID; + handlerObjectMaterial(this, localID, material.ToString()); + } } break; - case PacketType.ParcelPropertiesUpdate: - ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) - { - if (parcelPropertiesPacket.AgentData.SessionID != SessionId || - parcelPropertiesPacket.AgentData.AgentID != AgentId) - break; - } #endregion - handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; - - if (handlerParcelPropertiesUpdateRequest != null) - { - LandUpdateArgs args = new LandUpdateArgs(); - - args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; - args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; - args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); - args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; - args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; - args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; - args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; - args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); - args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); - args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); - args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; - args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; - args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; - args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; - args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; - args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; - args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; - handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); - } - break; - case PacketType.ParcelSelectObjects: - ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; + #region Inventory/Asset/Other related packets + case PacketType.RequestImage: + RequestImagePacket imageRequest = (RequestImagePacket)Pack; + //m_log.Debug("image request: " + Pack.ToString()); + #region Packet Session and User Check if (m_checkPackets) { - if (selectPacket.AgentData.SessionID != SessionId || - selectPacket.AgentData.AgentID != AgentId) + if (imageRequest.AgentData.SessionID != SessionId || + imageRequest.AgentData.AgentID != AgentId) break; } #endregion - List returnIDs = new List(); + //handlerTextureRequest = null; - foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in - selectPacket.ReturnIDs) + for (int i = 0; i < imageRequest.RequestImage.Length; i++) { - returnIDs.Add(rb.ReturnID); - } + if (OnRequestTexture != null) + { + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = imageRequest.RequestImage[i].Image; + args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + args.PacketNumber = imageRequest.RequestImage[i].Packet; + args.Priority = imageRequest.RequestImage[i].DownloadPriority; + args.requestSequence = imageRequest.Header.Sequence; - handlerParcelSelectObjects = OnParcelSelectObjects; + //handlerTextureRequest = OnRequestTexture; - if (handlerParcelSelectObjects != null) - { - handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, - Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); - } - break; - case PacketType.ParcelObjectOwnersRequest: - //m_log.Debug(Pack.ToString()); - ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + //if (handlerTextureRequest != null) + //OnRequestTexture(this, args); - #region Packet Session and User Check - if (m_checkPackets) - { - if (reqPacket.AgentData.SessionID != SessionId || - reqPacket.AgentData.AgentID != AgentId) - break; + // in the end, we null this, so we have to check if it's null + if (m_imageManager != null) + { + m_imageManager.EnqueueReq(args); + } + } } - #endregion + break; - handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; + case PacketType.TransferRequest: + //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); - if (handlerParcelObjectOwnerRequest != null) + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + //m_log.Debug("Transfer Request: " + transfer.ToString()); + // Validate inventory transfers + // Has to be done here, because AssetCache can't do it + // + + if (transfer.TransferInfo.SourceType == 3) { - handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); - } - break; - case PacketType.ParcelGodForceOwner: - ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; + UUID taskID = new UUID(transfer.TransferInfo.Params, 48); + UUID itemID = new UUID(transfer.TransferInfo.Params, 64); + UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + if (!(((Scene)m_scene).Permissions.BypassPermissions())) + { + if (taskID != UUID.Zero) // Prim + { + SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + if (part == null) + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (godForceOwnerPacket.AgentData.SessionID != SessionId || - godForceOwnerPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + if (part.OwnerID != AgentId) + break; - handlerParcelGodForceOwner = OnParcelGodForceOwner; - if (handlerParcelGodForceOwner != null) - { - handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); - } - break; - case PacketType.ParcelRelease: - ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (releasePacket.AgentData.SessionID != SessionId || - releasePacket.AgentData.AgentID != AgentId) - break; - } - #endregion + TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); + if (ti == null) + break; - handlerParcelAbandonRequest = OnParcelAbandonRequest; - if (handlerParcelAbandonRequest != null) - { - handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); - } - break; - case PacketType.ParcelReclaim: - ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; + if (ti.OwnerID != AgentId) + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (reclaimPacket.AgentData.SessionID != SessionId || - reclaimPacket.AgentData.AgentID != AgentId) - break; - } - #endregion + if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + break; - handlerParcelReclaim = OnParcelReclaim; - if (handlerParcelReclaim != null) - { - handlerParcelReclaim(reclaimPacket.Data.LocalID, this); + if (ti.AssetID != requestID) + break; + } + else // Agent + { + IInventoryService invService = m_scene.RequestModuleInterface(); + InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); + assetRequestItem = invService.GetItem(assetRequestItem); + if (assetRequestItem == null) + { + assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); + if (assetRequestItem == null) + return; + } + + // At this point, we need to apply perms + // only to notecards and scripts. All + // other asset types are always available + // + if (assetRequestItem.AssetType == 10) + { + if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view script", false); + break; + } + } + else if (assetRequestItem.AssetType == 7) + { + if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) + { + SendAgentAlertMessage("Insufficient permissions to view notecard", false); + break; + } + } + + if (assetRequestItem.AssetID != requestID) + break; + } + } } - break; - case PacketType.ParcelReturnObjects: + //m_assetCache.AddAssetRequest(this, transfer); - ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; + MakeAssetRequest(transfer); - #region Packet Session and User Check - if (m_checkPackets) - { - if (parcelReturnObjects.AgentData.SessionID != SessionId || - parcelReturnObjects.AgentData.AgentID != AgentId) - break; - } - #endregion + /* RequestAsset = OnRequestAsset; + if (RequestAsset != null) + { + RequestAsset(this, transfer); + }*/ + break; + case PacketType.AssetUploadRequest: + AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; - UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; - for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) - puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; + + // m_log.Debug("upload request " + request.ToString()); + // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); + UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); - UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; + UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest; - for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) - puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; + if (handlerAssetUploadRequest != null) + { + handlerAssetUploadRequest(this, temp, + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, + request.AssetBlock.Tempfile); + } + break; + case PacketType.RequestXfer: + RequestXferPacket xferReq = (RequestXferPacket)Pack; + + RequestXfer handlerRequestXfer = OnRequestXfer; - handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; - if (handlerParcelReturnObjectsRequest != null) + if (handlerRequestXfer != null) { - handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); + handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + } + break; + case PacketType.SendXferPacket: + SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; + XferReceive handlerXferReceive = OnXferReceive; + if (handlerXferReceive != null) + { + handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + } + break; + case PacketType.ConfirmXferPacket: + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; + + ConfirmXfer handlerConfirmXfer = OnConfirmXfer; + if (handlerConfirmXfer != null) + { + handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); } break; + case PacketType.AbortXfer: + AbortXferPacket abortXfer = (AbortXferPacket)Pack; + AbortXfer handlerAbortXfer = OnAbortXfer; + if (handlerAbortXfer != null) + { + handlerAbortXfer(this, abortXfer.XferID.ID); + } - case PacketType.ParcelSetOtherCleanTime: - ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; + break; + case PacketType.CreateInventoryFolder: + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || - parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) + if (invFolder.AgentData.SessionID != SessionId || + invFolder.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; - if (handlerParcelSetOtherCleanTime != null) + CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder; + if (handlerCreateInventoryFolder != null) { - handlerParcelSetOtherCleanTime(this, - parcelSetOtherCleanTimePacket.ParcelData.LocalID, - parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); + handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort)invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + break; + case PacketType.UpdateInventoryFolder: + if (OnUpdateInventoryFolder != null) + { + UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFolderx.AgentData.SessionID != SessionId || + invFolderx.AgentData.AgentID != AgentId) + break; + } + #endregion + + UpdateInventoryFolder handlerUpdateInventoryFolder = null; + + for (int i = 0; i < invFolderx.FolderData.Length; i++) + { + handlerUpdateInventoryFolder = OnUpdateInventoryFolder; + if (handlerUpdateInventoryFolder != null) + { + OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID, + (ushort)invFolderx.FolderData[i].Type, + Util.FieldToString(invFolderx.FolderData[i].Name), + invFolderx.FolderData[i].ParentID); + } + } } break; + case PacketType.MoveInventoryFolder: + if (OnMoveInventoryFolder != null) + { + MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack; - case PacketType.LandStatRequest: - LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFoldery.AgentData.SessionID != SessionId || + invFoldery.AgentData.AgentID != AgentId) + break; + } + #endregion + + MoveInventoryFolder handlerMoveInventoryFolder = null; + for (int i = 0; i < invFoldery.InventoryData.Length; i++) + { + handlerMoveInventoryFolder = OnMoveInventoryFolder; + if (handlerMoveInventoryFolder != null) + { + OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID, + invFoldery.InventoryData[i].ParentID); + } + } + } + break; + case PacketType.CreateInventoryItem: + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; + #region Packet Session and User Check if (m_checkPackets) { - if (lsrp.AgentData.SessionID != SessionId || - lsrp.AgentData.AgentID != AgentId) + if (createItem.AgentData.SessionID != SessionId || + createItem.AgentData.AgentID != AgentId) break; } #endregion - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) + CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem; + if (handlerCreateNewInventoryItem != null) { - handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); + handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, + createItem.InventoryBlock.FolderID, + createItem.InventoryBlock.CallbackID, + Util.FieldToString(createItem.InventoryBlock.Description), + Util.FieldToString(createItem.InventoryBlock.Name), + createItem.InventoryBlock.InvType, + createItem.InventoryBlock.Type, + createItem.InventoryBlock.WearableType, + createItem.InventoryBlock.NextOwnerMask, + Util.UnixTimeSinceEpoch()); } break; + case PacketType.FetchInventory: + if (OnFetchInventory != null) + { + FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack; - case PacketType.ParcelDwellRequest: - ParcelDwellRequestPacket dwellrq = - (ParcelDwellRequestPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (FetchInventoryx.AgentData.SessionID != SessionId || + FetchInventoryx.AgentData.AgentID != AgentId) + break; + } + #endregion + + FetchInventory handlerFetchInventory = null; + + for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) + { + handlerFetchInventory = OnFetchInventory; + + if (handlerFetchInventory != null) + { + OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID, + FetchInventoryx.InventoryData[i].OwnerID); + } + } + } + break; + case PacketType.FetchInventoryDescendents: + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dwellrq.AgentData.SessionID != SessionId || - dwellrq.AgentData.AgentID != AgentId) + if (Fetch.AgentData.SessionID != SessionId || + Fetch.AgentData.AgentID != AgentId) break; } #endregion - handlerParcelDwellRequest = OnParcelDwellRequest; - if (handlerParcelDwellRequest != null) + FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents; + if (handlerFetchInventoryDescendents != null) { - handlerParcelDwellRequest(dwellrq.Data.LocalID, this); + handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); } break; - - #endregion - - #region Estate Packets - - case PacketType.EstateOwnerMessage: - EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; - //m_log.Debug(messagePacket.ToString()); + case PacketType.PurgeInventoryDescendents: + PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (messagePacket.AgentData.SessionID != SessionId || - messagePacket.AgentData.AgentID != AgentId) + if (Purge.AgentData.SessionID != SessionId || + Purge.AgentData.AgentID != AgentId) break; } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; + if (handlerPurgeInventoryDescendents != null) { - case "getinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); - } - break; - case "setregioninfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), - convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), - Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), - (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), - Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), - convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); - } - break; -// case "texturebase": -// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) -// { -// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) -// { -// string s = Utils.BytesToString(block.Parameter); -// string[] splitField = s.Split(' '); -// if (splitField.Length == 2) -// { -// UUID tempUUID = new UUID(splitField[1]); -// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); -// } -// } -// } -// break; - case "texturedetail": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 2) - { - Int16 corner = Convert.ToInt16(splitField[0]); - UUID textureUUID = new UUID(splitField[1]); - - OnSetEstateTerrainDetailTexture(this, corner, textureUUID); - } - } - } - - break; - case "textureheights": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - string s = Utils.BytesToString(block.Parameter); - string[] splitField = s.Split(' '); - if (splitField.Length == 3) - { - Int16 corner = Convert.ToInt16(splitField[0]); - float lowValue = (float)Convert.ToDecimal(splitField[1]); - float highValue = (float)Convert.ToDecimal(splitField[2]); - - OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); - } - } - } - break; - case "texturecommit": - OnCommitEstateTerrainTextureRequest(this); - break; - case "setregionterrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length != 9) - { - m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); - } - else - { - try - { - string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float WaterHeight = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); - tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); - if (!tmp.Contains(".")) tmp += ".00"; - float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); - bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); - bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); - float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); - bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); - bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); - float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); - - OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); - - } - catch (Exception ex) - { - m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); - } - } - } - - break; - case "restart": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - float timeSeconds; - Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); - timeSeconds = (int)timeSeconds; - OnEstateRestartSimRequest(this, (int)timeSeconds); - - } - } - break; - case "estatechangecovenantid": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) - { - UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); - OnEstateChangeCovenantRequest(this, newCovenantID); - } - } + handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + } + break; + case PacketType.UpdateInventoryItem: + UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (inventoryItemUpdate.AgentData.SessionID != SessionId || + inventoryItemUpdate.AgentData.AgentID != AgentId) break; - case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); + } + #endregion - } - break; - case "simulatormessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "instantmessage": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length < 5) - break; - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); - string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); - UUID sessionID = messagePacket.AgentData.SessionID; - OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); - } - break; - case "setregiondebug": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); - bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); - bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); + if (OnUpdateInventoryItem != null) + { + UpdateInventoryItem handlerUpdateInventoryItem = null; + for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) + { + handlerUpdateInventoryItem = OnUpdateInventoryItem; - OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); - } - break; - case "teleporthomeuser": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + if (handlerUpdateInventoryItem != null) { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UUID Prey; - - UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); + InventoryItemBase itemUpd = new InventoryItemBase(); + itemUpd.ID = inventoryItemUpdate.InventoryData[i].ItemID; + itemUpd.Name = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name); + itemUpd.Description = Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description); + itemUpd.GroupID = inventoryItemUpdate.InventoryData[i].GroupID; + itemUpd.GroupOwned = inventoryItemUpdate.InventoryData[i].GroupOwned; + itemUpd.GroupPermissions = inventoryItemUpdate.InventoryData[i].GroupMask; + itemUpd.NextPermissions = inventoryItemUpdate.InventoryData[i].NextOwnerMask; + itemUpd.EveryOnePermissions = inventoryItemUpdate.InventoryData[i].EveryoneMask; + itemUpd.CreationDate = inventoryItemUpdate.InventoryData[i].CreationDate; + itemUpd.Folder = inventoryItemUpdate.InventoryData[i].FolderID; + itemUpd.InvType = inventoryItemUpdate.InventoryData[i].InvType; + itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; + itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; + itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; - OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); - } - break; - case "teleporthomeallusers": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); - } - break; - case "colliders": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) - { - handlerLandStatRequest(0, 1, 0, "", this); - } - break; - case "scripts": - handlerLandStatRequest = OnLandStatRequest; - if (handlerLandStatRequest != null) - { - handlerLandStatRequest(0, 0, 0, "", this); + OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, + inventoryItemUpdate.InventoryData[i].ItemID, + itemUpd); } - break; - case "terrain": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) - { - if (messagePacket.ParamList.Length > 0) - { - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") - { - handlerBakeTerrain = OnBakeTerrain; - if (handlerBakeTerrain != null) - { - handlerBakeTerrain(this); - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") - { - if (messagePacket.ParamList.Length > 1) - { - handlerRequestTerrain = OnRequestTerrain; - if (handlerRequestTerrain != null) - { - handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } - if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") - { - if (messagePacket.ParamList.Length > 1) - { - handlerUploadTerrain = OnUploadTerrain; - if (handlerUploadTerrain != null) - { - handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - } - } - } - - } - + } + } + break; + case PacketType.CopyInventoryItem: + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (copyitem.AgentData.SessionID != SessionId || + copyitem.AgentData.AgentID != AgentId) break; + } + #endregion - case "estatechangeinfo": - if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + CopyInventoryItem handlerCopyInventoryItem = null; + if (OnCopyInventoryItem != null) + { + foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + { + handlerCopyInventoryItem = OnCopyInventoryItem; + if (handlerCopyInventoryItem != null) { - UUID invoice = messagePacket.MethodData.Invoice; - UUID SenderID = messagePacket.AgentData.AgentID; - UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); - UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - - handlerEstateChangeInfo = OnEstateChangeInfo; - if (handlerEstateChangeInfo != null) - { - handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); - } + handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, + datablock.OldItemID, datablock.NewFolderID, + Util.FieldToString(datablock.NewName)); } - break; - - default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); - break; + } } - - //int parcelID, uint reportType, uint requestflags, string filter - - //lsrp.RequestData.ParcelLocalID; - //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts - //lsrp.RequestData.RequestFlags; - //lsrp.RequestData.Filter; - - break; - - case PacketType.RequestRegionInfo: - RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; + break; + case PacketType.MoveInventoryItem: + MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (mPacket.SessionID != SessionId || - mPacket.AgentID != AgentId) + if (moveitem.AgentData.SessionID != SessionId || + moveitem.AgentData.AgentID != AgentId) break; } #endregion - handlerRegionInfoRequest = OnRegionInfoRequest; - if (handlerRegionInfoRequest != null) + if (OnMoveInventoryItem != null) { - handlerRegionInfoRequest(this); + MoveInventoryItem handlerMoveInventoryItem = null; + InventoryItemBase itm = null; + List items = new List(); + foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) + { + itm = new InventoryItemBase(datablock.ItemID, AgentId); + itm.Folder = datablock.FolderID; + itm.Name = Util.FieldToString(datablock.NewName); + // weird, comes out as empty string + //m_log.DebugFormat("[XXX] new name: {0}", itm.Name); + items.Add(itm); + } + handlerMoveInventoryItem = OnMoveInventoryItem; + if (handlerMoveInventoryItem != null) + { + handlerMoveInventoryItem(this, items); + } } break; - case PacketType.EstateCovenantRequest: - - //EstateCovenantRequestPacket.AgentDataBlock epack = - // ((EstateCovenantRequestPacket)Pack).AgentData; + case PacketType.RemoveInventoryItem: + RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; - handlerEstateCovenantRequest = OnEstateCovenantRequest; - if (handlerEstateCovenantRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerEstateCovenantRequest(this); + if (removeItem.AgentData.SessionID != SessionId || + removeItem.AgentData.AgentID != AgentId) + break; } - break; - #endregion - #region GodPackets - - case PacketType.RequestGodlikePowers: - RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; - RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; - UUID token = rblock.Token; - - RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + if (OnRemoveInventoryItem != null) + { + RemoveInventoryItem handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) + { + uuids.Add(datablock.ItemID); + } + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } - handlerReqGodlikePowers = OnRequestGodlikePowers; + } + break; + case PacketType.RemoveInventoryFolder: + RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; - if (handlerReqGodlikePowers != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); + if (removeFolder.AgentData.SessionID != SessionId || + removeFolder.AgentData.AgentID != AgentId) + break; } + #endregion - break; - case PacketType.GodKickUser: - GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - - if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) + if (OnRemoveInventoryFolder != null) { - handlerGodKickUser = OnGodKickUser; - if (handlerGodKickUser != null) + RemoveInventoryFolder handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) { - handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, - gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); } } - else - { - SendAgentAlertMessage("Kick request denied", false); - } - //KickUserPacket kupack = new KickUserPacket(); - //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; - - //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; - //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; - - //kupack.TargetBlock.TargetIP = (uint)0; - //kupack.TargetBlock.TargetPort = (ushort)0; - //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; - - //OutPacket(kupack, ThrottleOutPacketType.Task); break; - - #endregion - - #region Economy/Transaction Packets - - case PacketType.MoneyBalanceRequest: - MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; - + case PacketType.RemoveInventoryObjects: + RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (moneybalancerequestpacket.AgentData.SessionID != SessionId || - moneybalancerequestpacket.AgentData.AgentID != AgentId) + if (removeObject.AgentData.SessionID != SessionId || + removeObject.AgentData.AgentID != AgentId) break; } #endregion - - handlerMoneyBalanceRequest = OnMoneyBalanceRequest; - - if (handlerMoneyBalanceRequest != null) + if (OnRemoveInventoryFolder != null) { - handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + RemoveInventoryFolder handlerRemoveInventoryFolder = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) + { + uuids.Add(datablock.FolderID); + } + handlerRemoveInventoryFolder = OnRemoveInventoryFolder; + if (handlerRemoveInventoryFolder != null) + { + handlerRemoveInventoryFolder(this, uuids); + } } + if (OnRemoveInventoryItem != null) + { + RemoveInventoryItem handlerRemoveInventoryItem = null; + List uuids = new List(); + foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) + { + uuids.Add(datablock.ItemID); + } + handlerRemoveInventoryItem = OnRemoveInventoryItem; + if (handlerRemoveInventoryItem != null) + { + handlerRemoveInventoryItem(this, uuids); + } + } break; - case PacketType.EconomyDataRequest: + case PacketType.RequestTaskInventory: + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; - - handlerEconomoyDataRequest = OnEconomyDataRequest; - if (handlerEconomoyDataRequest != null) + #region Packet Session and User Check + if (m_checkPackets) { - handlerEconomoyDataRequest(AgentId); + if (requesttask.AgentData.SessionID != SessionId || + requesttask.AgentData.AgentID != AgentId) + break; } - break; - case PacketType.RequestPayPrice: - RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + #endregion - handlerRequestPayPrice = OnRequestPayPrice; - if (handlerRequestPayPrice != null) + RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory; + if (handlerRequestTaskInventory != null) { - handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); + handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); } break; - - case PacketType.ObjectSaleInfo: - ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; + case PacketType.UpdateTaskInventory: + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectSaleInfoPacket.AgentData.SessionID != SessionId || - objectSaleInfoPacket.AgentData.AgentID != AgentId) + if (updatetask.AgentData.SessionID != SessionId || + updatetask.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectSaleInfo = OnObjectSaleInfo; - if (handlerObjectSaleInfo != null) + if (OnUpdateTaskInventory != null) { - foreach (ObjectSaleInfoPacket.ObjectDataBlock d - in objectSaleInfoPacket.ObjectData) + if (updatetask.UpdateData.Key == 0) { - handlerObjectSaleInfo(this, - objectSaleInfoPacket.AgentData.AgentID, - objectSaleInfoPacket.AgentData.SessionID, - d.LocalID, - d.SaleType, - d.SalePrice); + UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory; + if (handlerUpdateTaskInventory != null) + { + TaskInventoryItem newTaskItem = new TaskInventoryItem(); + newTaskItem.ItemID = updatetask.InventoryData.ItemID; + newTaskItem.ParentID = updatetask.InventoryData.FolderID; + newTaskItem.CreatorID = updatetask.InventoryData.CreatorID; + newTaskItem.OwnerID = updatetask.InventoryData.OwnerID; + newTaskItem.GroupID = updatetask.InventoryData.GroupID; + newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask; + newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask; + newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; + newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; + newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; + newTaskItem.Type = updatetask.InventoryData.Type; + newTaskItem.InvType = updatetask.InventoryData.InvType; + newTaskItem.Flags = updatetask.InventoryData.Flags; + //newTaskItem.SaleType=updatetask.InventoryData.SaleType; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); + newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); + newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; + handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID, + newTaskItem, updatetask.UpdateData.LocalID); + } } } + break; - case PacketType.ObjectBuy: - ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; + case PacketType.RemoveTaskInventory: + + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectBuyPacket.AgentData.SessionID != SessionId || - objectBuyPacket.AgentData.AgentID != AgentId) + if (removeTask.AgentData.SessionID != SessionId || + removeTask.AgentData.AgentID != AgentId) break; } #endregion - handlerObjectBuy = OnObjectBuy; + RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem; - if (handlerObjectBuy != null) + if (handlerRemoveTaskItem != null) { - foreach (ObjectBuyPacket.ObjectDataBlock d - in objectBuyPacket.ObjectData) - { - handlerObjectBuy(this, - objectBuyPacket.AgentData.AgentID, - objectBuyPacket.AgentData.SessionID, - objectBuyPacket.AgentData.GroupID, - objectBuyPacket.AgentData.CategoryID, - d.ObjectLocalID, - d.SaleType, - d.SalePrice); - } + handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); } - break; - - #endregion - - #region Script Packets - - case PacketType.GetScriptRunning: - GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; - handlerGetScriptRunning = OnGetScriptRunning; - if (handlerGetScriptRunning != null) - { - handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); - } break; - case PacketType.SetScriptRunning: - SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; + case PacketType.MoveTaskInventory: + + MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (setScriptRunning.AgentData.SessionID != SessionId || - setScriptRunning.AgentData.AgentID != AgentId) + if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || + moveTaskInventoryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerSetScriptRunning = OnSetScriptRunning; - if (handlerSetScriptRunning != null) + MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem; + + if (handlerMoveTaskItem != null) { - handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); + handlerMoveTaskItem( + this, moveTaskInventoryPacket.AgentData.FolderID, + moveTaskInventoryPacket.InventoryData.LocalID, + moveTaskInventoryPacket.InventoryData.ItemID); } + break; - case PacketType.ScriptReset: - ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; + case PacketType.RezScript: + //m_log.Debug(Pack.ToString()); + RezScriptPacket rezScriptx = (RezScriptPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (scriptResetPacket.AgentData.SessionID != SessionId || - scriptResetPacket.AgentData.AgentID != AgentId) + if (rezScriptx.AgentData.SessionID != SessionId || + rezScriptx.AgentData.AgentID != AgentId) break; } #endregion - handlerScriptReset = OnScriptReset; - if (handlerScriptReset != null) + RezScript handlerRezScript = OnRezScript; + InventoryItemBase item = new InventoryItemBase(); + item.ID = rezScriptx.InventoryBlock.ItemID; + item.Folder = rezScriptx.InventoryBlock.FolderID; + item.CreatorId = rezScriptx.InventoryBlock.CreatorID.ToString(); + item.Owner = rezScriptx.InventoryBlock.OwnerID; + item.BasePermissions = rezScriptx.InventoryBlock.BaseMask; + item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask; + item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask; + item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask; + item.GroupPermissions = rezScriptx.InventoryBlock.GroupMask; + item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned; + item.GroupID = rezScriptx.InventoryBlock.GroupID; + item.AssetType = rezScriptx.InventoryBlock.Type; + item.InvType = rezScriptx.InventoryBlock.InvType; + item.Flags = rezScriptx.InventoryBlock.Flags; + item.SaleType = rezScriptx.InventoryBlock.SaleType; + item.SalePrice = rezScriptx.InventoryBlock.SalePrice; + item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name); + item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description); + item.CreationDate = rezScriptx.InventoryBlock.CreationDate; + + if (handlerRezScript != null) { - handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); + handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); } break; - #endregion - - #region Gesture Managment - - case PacketType.ActivateGestures: - ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; + case PacketType.MapLayerRequest: + RequestMapLayer(); + break; + case PacketType.MapBlockRequest: + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGesturePacket.AgentData.SessionID != SessionId || - activateGesturePacket.AgentData.AgentID != AgentId) + if (MapRequest.AgentData.SessionID != SessionId || + MapRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerActivateGesture = OnActivateGesture; - if (handlerActivateGesture != null) + RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks; + if (handlerRequestMapBlocks != null) { - handlerActivateGesture(this, - activateGesturePacket.Data[0].AssetID, - activateGesturePacket.Data[0].ItemID); + handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); } - else m_log.Error("Null pointer for activateGesture"); - break; - - case PacketType.DeactivateGestures: - DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; + case PacketType.MapNameRequest: + MapNameRequestPacket map = (MapNameRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (deactivateGesturePacket.AgentData.SessionID != SessionId || - deactivateGesturePacket.AgentData.AgentID != AgentId) + if (map.AgentData.SessionID != SessionId || + map.AgentData.AgentID != AgentId) break; } #endregion - handlerDeactivateGesture = OnDeactivateGesture; - if (handlerDeactivateGesture != null) + string mapName = Util.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + RequestMapName handlerMapNameRequest = OnMapNameRequest; + if (handlerMapNameRequest != null) { - handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); + handlerMapNameRequest(this, mapName); } break; - case PacketType.ObjectOwner: - ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; + case PacketType.TeleportLandmarkRequest: + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (objectOwnerPacket.AgentData.SessionID != SessionId || - objectOwnerPacket.AgentData.AgentID != AgentId) + if (tpReq.Info.SessionID != SessionId || + tpReq.Info.AgentID != AgentId) break; } #endregion - List localIDs = new List(); + UUID lmid = tpReq.Info.LandmarkID; + AssetLandmark lm; + if (lmid != UUID.Zero) + { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); + AssetBase lma = m_assetService.Get(lmid.ToString()); - foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) - localIDs.Add(d.ObjectLocalID); + if (lma == null) + { + // Failed to find landmark + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } - handlerObjectOwner = OnObjectOwner; - if (handlerObjectOwner != null) + try + { + lm = new AssetLandmark(lma); + } + catch (NullReferenceException) + { + // asset not found generates null ref inside the assetlandmark constructor. + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + break; + } + } + else { - handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); + // Teleport home request + UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest; + if (handlerTeleportHomeRequest != null) + { + handlerTeleportHomeRequest(AgentId, this); + } + break; } - break; - - #endregion + TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; + if (handlerTeleportLandmarkRequest != null) + { + handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + } + else + { + //no event handler so cancel request - #region unimplemented handlers - case PacketType.StartPingCheck: - // Send the client the ping response back - // Pass the same PingID in the matching packet - // Handled In the packet processing - //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); - break; - case PacketType.CompletePingCheck: - // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client - //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); - break; + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); - case PacketType.ViewerStats: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); + } break; - case PacketType.MapItemRequest: - MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; + case PacketType.TeleportLocationRequest: + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; + // m_log.Debug(tpLocReq.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (mirpk.AgentData.SessionID != SessionId || - mirpk.AgentData.AgentID != AgentId) + if (tpLocReq.AgentData.SessionID != SessionId || + tpLocReq.AgentData.AgentID != AgentId) break; } #endregion - //m_log.Debug(mirpk.ToString()); - handlerMapItemRequest = OnMapItemRequest; - if (handlerMapItemRequest != null) + TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; + if (handlerTeleportLocationRequest != null) { - handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, - mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, - mirpk.RequestData.RegionHandle); + handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, + tpLocReq.Info.LookAt, 16); + } + else + { + //no event handler so cancel request + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; + tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; + + #endregion + + case PacketType.UUIDNameRequest: + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest; + if (handlerNameRequest != null) + { + handlerNameRequest(UUIDBlock.ID, this); + } } break; - case PacketType.TransferAbort: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); + #region Parcel related packets + + case PacketType.RegionHandleRequest: + RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; + + RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; + if (handlerRegionHandleRequest != null) + { + handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); + } break; - case PacketType.MuteListRequest: - MuteListRequestPacket muteListRequest = - (MuteListRequestPacket)Pack; + + case PacketType.ParcelInfoRequest: + ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (muteListRequest.AgentData.SessionID != SessionId || - muteListRequest.AgentData.AgentID != AgentId) + if (pirPack.AgentData.SessionID != SessionId || + pirPack.AgentData.AgentID != AgentId) break; } #endregion - handlerMuteListRequest = OnMuteListRequest; - if (handlerMuteListRequest != null) - { - handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); - } - else + ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest; + if (handlerParcelInfoRequest != null) { - SendUseCachedMuteList(); + handlerParcelInfoRequest(this, pirPack.Data.ParcelID); } break; - case PacketType.UseCircuitCode: - // Don't display this one, we handle it at a lower level - break; - - case PacketType.AgentHeightWidth: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); - break; - - case PacketType.InventoryDescendents: - // TODO: handle this packet - //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); - break; - case PacketType.DirPlacesQuery: - DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; - //m_log.Debug(dirPlacesQueryPacket.ToString()); + case PacketType.ParcelAccessListRequest: + ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || - dirPlacesQueryPacket.AgentData.AgentID != AgentId) + if (requestPacket.AgentData.SessionID != SessionId || + requestPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerDirPlacesQuery = OnDirPlacesQuery; - if (handlerDirPlacesQuery != null) + ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest; + + if (handlerParcelAccessListRequest != null) { - handlerDirPlacesQuery(this, - dirPlacesQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.QueryText), - (int)dirPlacesQueryPacket.QueryData.QueryFlags, - (int)dirPlacesQueryPacket.QueryData.Category, - Utils.BytesToString( - dirPlacesQueryPacket.QueryData.SimName), - dirPlacesQueryPacket.QueryData.QueryStart); + handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, + requestPacket.Data.Flags, requestPacket.Data.SequenceID, + requestPacket.Data.LocalID, this); } break; - case PacketType.DirFindQuery: - DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; + + case PacketType.ParcelAccessListUpdate: + ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirFindQueryPacket.AgentData.SessionID != SessionId || - dirFindQueryPacket.AgentData.AgentID != AgentId) + if (updatePacket.AgentData.SessionID != SessionId || + updatePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerDirFindQuery = OnDirFindQuery; - if (handlerDirFindQuery != null) + List entries = new List(); + foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) { - handlerDirFindQuery(this, - dirFindQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirFindQueryPacket.QueryData.QueryText), - dirFindQueryPacket.QueryData.QueryFlags, - dirFindQueryPacket.QueryData.QueryStart); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = block.ID; + entry.Flags = (AccessList)block.Flags; + entry.Time = new DateTime(); + entries.Add(entry); + } + + ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; + if (handlerParcelAccessListUpdateRequest != null) + { + handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, + updatePacket.AgentData.SessionID, updatePacket.Data.Flags, + updatePacket.Data.LocalID, entries, this); } break; - case PacketType.DirLandQuery: - DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; + case PacketType.ParcelPropertiesRequest: + + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirLandQueryPacket.AgentData.SessionID != SessionId || - dirLandQueryPacket.AgentData.AgentID != AgentId) + if (propertiesRequest.AgentData.SessionID != SessionId || + propertiesRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerDirLandQuery = OnDirLandQuery; - if (handlerDirLandQuery != null) + ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest; + if (handlerParcelPropertiesRequest != null) { - handlerDirLandQuery(this, - dirLandQueryPacket.QueryData.QueryID, - dirLandQueryPacket.QueryData.QueryFlags, - dirLandQueryPacket.QueryData.SearchType, - dirLandQueryPacket.QueryData.Price, - dirLandQueryPacket.QueryData.Area, - dirLandQueryPacket.QueryData.QueryStart); + handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), + (int)Math.Round(propertiesRequest.ParcelData.South), + (int)Math.Round(propertiesRequest.ParcelData.East), + (int)Math.Round(propertiesRequest.ParcelData.North), + propertiesRequest.ParcelData.SequenceID, + propertiesRequest.ParcelData.SnapSelection, this); } break; - case PacketType.DirPopularQuery: - DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; + case PacketType.ParcelDivide: + ParcelDividePacket landDivide = (ParcelDividePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirPopularQueryPacket.AgentData.SessionID != SessionId || - dirPopularQueryPacket.AgentData.AgentID != AgentId) + if (landDivide.AgentData.SessionID != SessionId || + landDivide.AgentData.AgentID != AgentId) break; } #endregion - handlerDirPopularQuery = OnDirPopularQuery; - if (handlerDirPopularQuery != null) + ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest; + if (handlerParcelDivideRequest != null) { - handlerDirPopularQuery(this, - dirPopularQueryPacket.QueryData.QueryID, - dirPopularQueryPacket.QueryData.QueryFlags); + handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), + (int)Math.Round(landDivide.ParcelData.South), + (int)Math.Round(landDivide.ParcelData.East), + (int)Math.Round(landDivide.ParcelData.North), this); } break; - case PacketType.DirClassifiedQuery: - DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; + case PacketType.ParcelJoin: + ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || - dirClassifiedQueryPacket.AgentData.AgentID != AgentId) + if (landJoin.AgentData.SessionID != SessionId || + landJoin.AgentData.AgentID != AgentId) break; } #endregion - handlerDirClassifiedQuery = OnDirClassifiedQuery; - if (handlerDirClassifiedQuery != null) + ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest; + + if (handlerParcelJoinRequest != null) { - handlerDirClassifiedQuery(this, - dirClassifiedQueryPacket.QueryData.QueryID, - Utils.BytesToString( - dirClassifiedQueryPacket.QueryData.QueryText), - dirClassifiedQueryPacket.QueryData.QueryFlags, - dirClassifiedQueryPacket.QueryData.Category, - dirClassifiedQueryPacket.QueryData.QueryStart); + handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), + (int)Math.Round(landJoin.ParcelData.South), + (int)Math.Round(landJoin.ParcelData.East), + (int)Math.Round(landJoin.ParcelData.North), this); } break; - case PacketType.EventInfoRequest: - EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; + case PacketType.ParcelPropertiesUpdate: + ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventInfoRequestPacket.AgentData.SessionID != SessionId || - eventInfoRequestPacket.AgentData.AgentID != AgentId) + if (parcelPropertiesPacket.AgentData.SessionID != SessionId || + parcelPropertiesPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnEventInfoRequest != null) + ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; + + if (handlerParcelPropertiesUpdateRequest != null) { - OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); + LandUpdateArgs args = new LandUpdateArgs(); + + args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID; + args.Category = (ParcelCategory)parcelPropertiesPacket.ParcelData.Category; + args.Desc = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc); + args.GroupID = parcelPropertiesPacket.ParcelData.GroupID; + args.LandingType = parcelPropertiesPacket.ParcelData.LandingType; + args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale; + args.MediaID = parcelPropertiesPacket.ParcelData.MediaID; + args.MediaURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL); + args.MusicURL = Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL); + args.Name = Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name); + args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags; + args.PassHours = parcelPropertiesPacket.ParcelData.PassHours; + args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice; + args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice; + args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID; + args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation; + args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt; + handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this); } break; - - #region Calling Card - - case PacketType.OfferCallingCard: - OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; + case PacketType.ParcelSelectObjects: + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (offerCallingCardPacket.AgentData.SessionID != SessionId || - offerCallingCardPacket.AgentData.AgentID != AgentId) + if (selectPacket.AgentData.SessionID != SessionId || + selectPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnOfferCallingCard != null) + List returnIDs = new List(); + + foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in + selectPacket.ReturnIDs) { - OnOfferCallingCard(this, - offerCallingCardPacket.AgentBlock.DestID, - offerCallingCardPacket.AgentBlock.TransactionID); + returnIDs.Add(rb.ReturnID); } - break; - case PacketType.AcceptCallingCard: - AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; + ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects; + + if (handlerParcelSelectObjects != null) + { + handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); + } + break; + case PacketType.ParcelObjectOwnersRequest: + //m_log.Debug(Pack.ToString()); + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (acceptCallingCardPacket.AgentData.SessionID != SessionId || - acceptCallingCardPacket.AgentData.AgentID != AgentId) + if (reqPacket.AgentData.SessionID != SessionId || + reqPacket.AgentData.AgentID != AgentId) break; } #endregion - // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should - // contain exactly one entry - if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) + ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; + + if (handlerParcelObjectOwnerRequest != null) { - OnAcceptCallingCard(this, - acceptCallingCardPacket.TransactionBlock.TransactionID, - acceptCallingCardPacket.FolderData[0].FolderID); + handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); } break; - - case PacketType.DeclineCallingCard: - DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; + case PacketType.ParcelGodForceOwner: + ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (declineCallingCardPacket.AgentData.SessionID != SessionId || - declineCallingCardPacket.AgentData.AgentID != AgentId) + if (godForceOwnerPacket.AgentData.SessionID != SessionId || + godForceOwnerPacket.AgentData.AgentID != AgentId) break; } #endregion - if (OnDeclineCallingCard != null) + ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner; + if (handlerParcelGodForceOwner != null) { - OnDeclineCallingCard(this, - declineCallingCardPacket.TransactionBlock.TransactionID); + handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); } break; - #endregion - - #region Groups - case PacketType.ActivateGroup: - ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; + case PacketType.ParcelRelease: + ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (activateGroupPacket.AgentData.SessionID != SessionId || - activateGroupPacket.AgentData.AgentID != AgentId) + if (releasePacket.AgentData.SessionID != SessionId || + releasePacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest; + if (handlerParcelAbandonRequest != null) { - m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); - m_GroupsModule.SendAgentGroupDataUpdate(this); + handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); } break; - - case PacketType.GroupTitlesRequest: - GroupTitlesRequestPacket groupTitlesRequest = - (GroupTitlesRequestPacket)Pack; + case PacketType.ParcelReclaim: + ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupTitlesRequest.AgentData.SessionID != SessionId || - groupTitlesRequest.AgentData.AgentID != AgentId) + if (reclaimPacket.AgentData.SessionID != SessionId || + reclaimPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelReclaim handlerParcelReclaim = OnParcelReclaim; + if (handlerParcelReclaim != null) { - GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - - groupTitlesReply.AgentData = - new GroupTitlesReplyPacket.AgentDataBlock(); - - groupTitlesReply.AgentData.AgentID = AgentId; - groupTitlesReply.AgentData.GroupID = - groupTitlesRequest.AgentData.GroupID; - - groupTitlesReply.AgentData.RequestID = - groupTitlesRequest.AgentData.RequestID; - - List titles = - m_GroupsModule.GroupTitlesRequest(this, - groupTitlesRequest.AgentData.GroupID); - - groupTitlesReply.GroupData = - new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - - int i = 0; - foreach (GroupTitlesData d in titles) - { - groupTitlesReply.GroupData[i] = - new GroupTitlesReplyPacket.GroupDataBlock(); - - groupTitlesReply.GroupData[i].Title = - Utils.StringToBytes(d.Name); - groupTitlesReply.GroupData[i].RoleID = - d.UUID; - groupTitlesReply.GroupData[i].Selected = - d.Selected; - i++; - } - - OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + handlerParcelReclaim(reclaimPacket.Data.LocalID, this); } break; + case PacketType.ParcelReturnObjects: - case PacketType.GroupProfileRequest: - GroupProfileRequestPacket groupProfileRequest = - (GroupProfileRequestPacket)Pack; + + ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupProfileRequest.AgentData.SessionID != SessionId || - groupProfileRequest.AgentData.AgentID != AgentId) + if (parcelReturnObjects.AgentData.SessionID != SessionId || + parcelReturnObjects.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) - { - GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + UUID[] puserselectedOwnerIDs = new UUID[parcelReturnObjects.OwnerIDs.Length]; + for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++) + puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID; - groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); - groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); - groupProfileReply.AgentData.AgentID = AgentId; + UUID[] puserselectedTaskIDs = new UUID[parcelReturnObjects.TaskIDs.Length]; - GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, - groupProfileRequest.GroupData.GroupID); + for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) + puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; - groupProfileReply.GroupData.GroupID = d.GroupID; - groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); - groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); - groupProfileReply.GroupData.ShowInList = d.ShowInList; - groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); - groupProfileReply.GroupData.PowersMask = d.PowersMask; - groupProfileReply.GroupData.InsigniaID = d.InsigniaID; - groupProfileReply.GroupData.FounderID = d.FounderID; - groupProfileReply.GroupData.MembershipFee = d.MembershipFee; - groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; - groupProfileReply.GroupData.Money = d.Money; - groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; - groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; - groupProfileReply.GroupData.AllowPublish = d.AllowPublish; - groupProfileReply.GroupData.MaturePublish = d.MaturePublish; - groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; + if (handlerParcelReturnObjectsRequest != null) + { + handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); - OutPacket(groupProfileReply, ThrottleOutPacketType.Task); } break; - case PacketType.GroupMembersRequest: - GroupMembersRequestPacket groupMembersRequestPacket = - (GroupMembersRequestPacket)Pack; + case PacketType.ParcelSetOtherCleanTime: + ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupMembersRequestPacket.AgentData.SessionID != SessionId || - groupMembersRequestPacket.AgentData.AgentID != AgentId) + if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || + parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; + if (handlerParcelSetOtherCleanTime != null) { - List members = - m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); - - int memberCount = members.Count; - - while (true) - { - int blockCount = members.Count; - if (blockCount > 40) - blockCount = 40; - - GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); - - groupMembersReply.AgentData = - new GroupMembersReplyPacket.AgentDataBlock(); - groupMembersReply.GroupData = - new GroupMembersReplyPacket.GroupDataBlock(); - groupMembersReply.MemberData = - new GroupMembersReplyPacket.MemberDataBlock[ - blockCount]; - - groupMembersReply.AgentData.AgentID = AgentId; - groupMembersReply.GroupData.GroupID = - groupMembersRequestPacket.GroupData.GroupID; - groupMembersReply.GroupData.RequestID = - groupMembersRequestPacket.GroupData.RequestID; - groupMembersReply.GroupData.MemberCount = memberCount; - - for (int i = 0 ; i < blockCount ; i++) - { - GroupMembersData m = members[0]; - members.RemoveAt(0); - - groupMembersReply.MemberData[i] = - new GroupMembersReplyPacket.MemberDataBlock(); - groupMembersReply.MemberData[i].AgentID = - m.AgentID; - groupMembersReply.MemberData[i].Contribution = - m.Contribution; - groupMembersReply.MemberData[i].OnlineStatus = - Utils.StringToBytes(m.OnlineStatus); - groupMembersReply.MemberData[i].AgentPowers = - m.AgentPowers; - groupMembersReply.MemberData[i].Title = - Utils.StringToBytes(m.Title); - groupMembersReply.MemberData[i].IsOwner = - m.IsOwner; - } - OutPacket(groupMembersReply, ThrottleOutPacketType.Task); - if (members.Count == 0) - break; - } + handlerParcelSetOtherCleanTime(this, + parcelSetOtherCleanTimePacket.ParcelData.LocalID, + parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); } break; - case PacketType.GroupRoleDataRequest: - GroupRoleDataRequestPacket groupRolesRequest = - (GroupRoleDataRequestPacket)Pack; + case PacketType.LandStatRequest: + LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRolesRequest.AgentData.SessionID != SessionId || - groupRolesRequest.AgentData.AgentID != AgentId) + if (lsrp.AgentData.SessionID != SessionId || + lsrp.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + GodLandStatRequest handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) { - GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); - - groupRolesReply.AgentData = - new GroupRoleDataReplyPacket.AgentDataBlock(); - - groupRolesReply.AgentData.AgentID = AgentId; - - groupRolesReply.GroupData = - new GroupRoleDataReplyPacket.GroupDataBlock(); - - groupRolesReply.GroupData.GroupID = - groupRolesRequest.GroupData.GroupID; - - groupRolesReply.GroupData.RequestID = - groupRolesRequest.GroupData.RequestID; - - List titles = - m_GroupsModule.GroupRoleDataRequest(this, - groupRolesRequest.GroupData.GroupID); - - groupRolesReply.GroupData.RoleCount = - titles.Count; - - groupRolesReply.RoleData = - new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; - - int i = 0; - foreach (GroupRolesData d in titles) - { - groupRolesReply.RoleData[i] = - new GroupRoleDataReplyPacket.RoleDataBlock(); - - groupRolesReply.RoleData[i].RoleID = - d.RoleID; - groupRolesReply.RoleData[i].Name = - Utils.StringToBytes(d.Name); - groupRolesReply.RoleData[i].Title = - Utils.StringToBytes(d.Title); - groupRolesReply.RoleData[i].Description = - Utils.StringToBytes(d.Description); - groupRolesReply.RoleData[i].Powers = - d.Powers; - groupRolesReply.RoleData[i].Members = - (uint)d.Members; - - i++; - } - - OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); } break; - case PacketType.GroupRoleMembersRequest: - GroupRoleMembersRequestPacket groupRoleMembersRequest = - (GroupRoleMembersRequestPacket)Pack; + case PacketType.ParcelDwellRequest: + ParcelDwellRequestPacket dwellrq = + (ParcelDwellRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRoleMembersRequest.AgentData.SessionID != SessionId || - groupRoleMembersRequest.AgentData.AgentID != AgentId) + if (dwellrq.AgentData.SessionID != SessionId || + dwellrq.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest; + if (handlerParcelDwellRequest != null) { - List mappings = - m_GroupsModule.GroupRoleMembersRequest(this, - groupRoleMembersRequest.GroupData.GroupID); + handlerParcelDwellRequest(dwellrq.Data.LocalID, this); + } + break; - int mappingsCount = mappings.Count; + #endregion - while (mappings.Count > 0) - { - int pairs = mappings.Count; - if (pairs > 32) - pairs = 32; + #region Estate Packets - GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); - groupRoleMembersReply.AgentData = - new GroupRoleMembersReplyPacket.AgentDataBlock(); - groupRoleMembersReply.AgentData.AgentID = - AgentId; - groupRoleMembersReply.AgentData.GroupID = - groupRoleMembersRequest.GroupData.GroupID; - groupRoleMembersReply.AgentData.RequestID = - groupRoleMembersRequest.GroupData.RequestID; + case PacketType.EstateOwnerMessage: + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; + //m_log.Debug(messagePacket.ToString()); + + #region Packet Session and User Check + if (m_checkPackets) + { + if (messagePacket.AgentData.SessionID != SessionId || + messagePacket.AgentData.AgentID != AgentId) + break; + } + #endregion + + switch (Utils.BytesToString(messagePacket.MethodData.Method)) + { + case "getinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); + } + break; + case "setregioninfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter), + convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter), + Convert.ToInt16(Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[4].Parameter))), + (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)), + Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), + convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); + } + break; +// case "texturebase": +// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) +// { +// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) +// { +// string s = Utils.BytesToString(block.Parameter); +// string[] splitField = s.Split(' '); +// if (splitField.Length == 2) +// { +// UUID tempUUID = new UUID(splitField[1]); +// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); +// } +// } +// } +// break; + case "texturedetail": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 2) + { + Int16 corner = Convert.ToInt16(splitField[0]); + UUID textureUUID = new UUID(splitField[1]); - groupRoleMembersReply.AgentData.TotalPairs = - (uint)mappingsCount; + OnSetEstateTerrainDetailTexture(this, corner, textureUUID); + } + } + } - groupRoleMembersReply.MemberData = - new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; + break; + case "textureheights": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + string s = Utils.BytesToString(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 3) + { + Int16 corner = Convert.ToInt16(splitField[0]); + float lowValue = (float)Convert.ToDecimal(splitField[1]); + float highValue = (float)Convert.ToDecimal(splitField[2]); - for (int i = 0 ; i < pairs ; i++) + OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); + } + } + } + break; + case "texturecommit": + OnCommitEstateTerrainTextureRequest(this); + break; + case "setregionterrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) { - GroupRoleMembersData d = mappings[0]; - mappings.RemoveAt(0); + if (messagePacket.ParamList.Length != 9) + { + m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); + } + else + { + try + { + string tmp = Utils.BytesToString(messagePacket.ParamList[0].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float WaterHeight = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); + tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); + bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter); + bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter); + float SunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter)); + bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter); + bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter); + float EstateSunHour = (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[8].Parameter)); - groupRoleMembersReply.MemberData[i] = - new GroupRoleMembersReplyPacket.MemberDataBlock(); + OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour); - groupRoleMembersReply.MemberData[i].RoleID = - d.RoleID; - groupRoleMembersReply.MemberData[i].MemberID = - d.MemberID; + } + catch (Exception ex) + { + m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket + "\n" + ex); + } + } } - OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); - } - } - break; + break; + case "restart": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + float timeSeconds; + Utils.TryParseSingle(Utils.BytesToString(block.Parameter), out timeSeconds); + timeSeconds = (int)timeSeconds; + OnEstateRestartSimRequest(this, (int)timeSeconds); - case PacketType.CreateGroupRequest: - CreateGroupRequestPacket createGroupRequest = - (CreateGroupRequestPacket)Pack; + } + } + break; + case "estatechangecovenantid": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) + { + UUID newCovenantID = new UUID(Utils.BytesToString(block.Parameter)); + OnEstateChangeCovenantRequest(this, newCovenantID); + } + } + break; + case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter))); - #region Packet Session and User Check - if (m_checkPackets) - { - if (createGroupRequest.AgentData.SessionID != SessionId || - createGroupRequest.AgentData.AgentID != AgentId) + } break; - } - #endregion + case "simulatormessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "instantmessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length < 5) + break; + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + UUID sessionID = messagePacket.AgentData.SessionID; + OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + break; + case "setregiondebug": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter); + bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter); + bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter); - if (m_GroupsModule != null) - { - m_GroupsModule.CreateGroup(this, - Utils.BytesToString(createGroupRequest.GroupData.Name), - Utils.BytesToString(createGroupRequest.GroupData.Charter), - createGroupRequest.GroupData.ShowInList, - createGroupRequest.GroupData.InsigniaID, - createGroupRequest.GroupData.MembershipFee, - createGroupRequest.GroupData.OpenEnrollment, - createGroupRequest.GroupData.AllowPublish, - createGroupRequest.GroupData.MaturePublish); - } - break; + OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); + } + break; + case "teleporthomeuser": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UUID Prey; - case PacketType.UpdateGroupInfo: - UpdateGroupInfoPacket updateGroupInfo = - (UpdateGroupInfoPacket)Pack; + UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); - #region Packet Session and User Check - if (m_checkPackets) - { - if (updateGroupInfo.AgentData.SessionID != SessionId || - updateGroupInfo.AgentData.AgentID != AgentId) + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + } break; - } - #endregion + case "teleporthomeallusers": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); + } + break; + case "colliders": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 1, 0, "", this); + } + break; + case "scripts": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 0, 0, "", this); + } + break; + case "terrain": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length > 0) + { + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") + { + BakeTerrain handlerBakeTerrain = OnBakeTerrain; + if (handlerBakeTerrain != null) + { + handlerBakeTerrain(this); + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "download filename") + { + if (messagePacket.ParamList.Length > 1) + { + RequestTerrain handlerRequestTerrain = OnRequestTerrain; + if (handlerRequestTerrain != null) + { + handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } + if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "upload filename") + { + if (messagePacket.ParamList.Length > 1) + { + RequestTerrain handlerUploadTerrain = OnUploadTerrain; + if (handlerUploadTerrain != null) + { + handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + } + } - if (m_GroupsModule != null) - { - m_GroupsModule.UpdateGroupInfo(this, - updateGroupInfo.GroupData.GroupID, - Utils.BytesToString(updateGroupInfo.GroupData.Charter), - updateGroupInfo.GroupData.ShowInList, - updateGroupInfo.GroupData.InsigniaID, - updateGroupInfo.GroupData.MembershipFee, - updateGroupInfo.GroupData.OpenEnrollment, - updateGroupInfo.GroupData.AllowPublish, - updateGroupInfo.GroupData.MaturePublish); - } + } + + + } + break; - break; + case "estatechangeinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); - case PacketType.SetGroupAcceptNotices: - SetGroupAcceptNoticesPacket setGroupAcceptNotices = - (SetGroupAcceptNoticesPacket)Pack; + EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo; + if (handlerEstateChangeInfo != null) + { + handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); + } + } + break; - #region Packet Session and User Check - if (m_checkPackets) - { - if (setGroupAcceptNotices.AgentData.SessionID != SessionId || - setGroupAcceptNotices.AgentData.AgentID != AgentId) + default: + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); break; } - #endregion + + //int parcelID, uint reportType, uint requestflags, string filter - if (m_GroupsModule != null) - { - m_GroupsModule.SetGroupAcceptNotices(this, - setGroupAcceptNotices.Data.GroupID, - setGroupAcceptNotices.Data.AcceptNotices, - setGroupAcceptNotices.NewData.ListInProfile); - } + //lsrp.RequestData.ParcelLocalID; + //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts + //lsrp.RequestData.RequestFlags; + //lsrp.RequestData.Filter; break; - case PacketType.GroupTitleUpdate: - GroupTitleUpdatePacket groupTitleUpdate = - (GroupTitleUpdatePacket)Pack; + case PacketType.RequestRegionInfo: + RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; #region Packet Session and User Check if (m_checkPackets) { - if (groupTitleUpdate.AgentData.SessionID != SessionId || - groupTitleUpdate.AgentData.AgentID != AgentId) + if (mPacket.SessionID != SessionId || + mPacket.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest; + if (handlerRegionInfoRequest != null) { - m_GroupsModule.GroupTitleUpdate(this, - groupTitleUpdate.AgentData.GroupID, - groupTitleUpdate.AgentData.TitleRoleID); + handlerRegionInfoRequest(this); } - break; + case PacketType.EstateCovenantRequest: + //EstateCovenantRequestPacket.AgentDataBlock epack = + // ((EstateCovenantRequestPacket)Pack).AgentData; - case PacketType.ParcelDeedToGroup: - ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; - if (m_GroupsModule != null) + EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest; + if (handlerEstateCovenantRequest != null) { - handlerParcelDeedToGroup = OnParcelDeedToGroup; - if (handlerParcelDeedToGroup != null) - { - handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); - - } + handlerEstateCovenantRequest(this); } - break; - - case PacketType.GroupNoticesListRequest: - GroupNoticesListRequestPacket groupNoticesListRequest = - (GroupNoticesListRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupNoticesListRequest.AgentData.SessionID != SessionId || - groupNoticesListRequest.AgentData.AgentID != AgentId) - break; - } #endregion - if (m_GroupsModule != null) - { - GroupNoticeData[] gn = - m_GroupsModule.GroupNoticesListRequest(this, - groupNoticesListRequest.Data.GroupID); + #region GodPackets - GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); - groupNoticesListReply.AgentData = - new GroupNoticesListReplyPacket.AgentDataBlock(); - groupNoticesListReply.AgentData.AgentID = AgentId; - groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; + case PacketType.RequestGodlikePowers: + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + UUID token = rblock.Token; - groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; - int i = 0; - foreach (GroupNoticeData g in gn) - { - groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); - groupNoticesListReply.Data[i].NoticeID = - g.NoticeID; - groupNoticesListReply.Data[i].Timestamp = - g.Timestamp; - groupNoticesListReply.Data[i].FromName = - Utils.StringToBytes(g.FromName); - groupNoticesListReply.Data[i].Subject = - Utils.StringToBytes(g.Subject); - groupNoticesListReply.Data[i].HasAttachment = - g.HasAttachment; - groupNoticesListReply.Data[i].AssetType = - g.AssetType; - i++; - } + RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers; - OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); + if (handlerReqGodlikePowers != null) + { + handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); } break; - case PacketType.GroupNoticeRequest: - GroupNoticeRequestPacket groupNoticeRequest = - (GroupNoticeRequestPacket)Pack; + case PacketType.GodKickUser: + GodKickUserPacket gkupack = (GodKickUserPacket)Pack; - #region Packet Session and User Check - if (m_checkPackets) + if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) { - if (groupNoticeRequest.AgentData.SessionID != SessionId || - groupNoticeRequest.AgentData.AgentID != AgentId) - break; + GodKickUser handlerGodKickUser = OnGodKickUser; + if (handlerGodKickUser != null) + { + handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, + gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); + } } - #endregion - - if (m_GroupsModule != null) + else { - m_GroupsModule.GroupNoticeRequest(this, - groupNoticeRequest.Data.GroupNoticeID); + SendAgentAlertMessage("Kick request denied", false); } - break; + //KickUserPacket kupack = new KickUserPacket(); + //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; - case PacketType.GroupRoleUpdate: - GroupRoleUpdatePacket groupRoleUpdate = - (GroupRoleUpdatePacket)Pack; + //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; + //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; - #region Packet Session and User Check - if (m_checkPackets) - { - if (groupRoleUpdate.AgentData.SessionID != SessionId || - groupRoleUpdate.AgentData.AgentID != AgentId) - break; - } - #endregion + //kupack.TargetBlock.TargetIP = (uint)0; + //kupack.TargetBlock.TargetPort = (ushort)0; + //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; - if (m_GroupsModule != null) - { - foreach (GroupRoleUpdatePacket.RoleDataBlock d in - groupRoleUpdate.RoleData) - { - m_GroupsModule.GroupRoleUpdate(this, - groupRoleUpdate.AgentData.GroupID, - d.RoleID, - Utils.BytesToString(d.Name), - Utils.BytesToString(d.Description), - Utils.BytesToString(d.Title), - d.Powers, - d.UpdateType); - } - m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); - } + //OutPacket(kupack, ThrottleOutPacketType.Task); break; - case PacketType.GroupRoleChanges: - GroupRoleChangesPacket groupRoleChanges = - (GroupRoleChangesPacket)Pack; + #endregion + + #region Economy/Transaction Packets + + case PacketType.MoneyBalanceRequest: + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (groupRoleChanges.AgentData.SessionID != SessionId || - groupRoleChanges.AgentData.AgentID != AgentId) + if (moneybalancerequestpacket.AgentData.SessionID != SessionId || + moneybalancerequestpacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest; + + if (handlerMoneyBalanceRequest != null) { - foreach (GroupRoleChangesPacket.RoleChangeBlock d in - groupRoleChanges.RoleChange) - { - m_GroupsModule.GroupRoleChanges(this, - groupRoleChanges.AgentData.GroupID, - d.RoleID, - d.MemberID, - d.Change); - } - m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); + handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); } - break; - case PacketType.JoinGroupRequest: - JoinGroupRequestPacket joinGroupRequest = - (JoinGroupRequestPacket)Pack; + break; + case PacketType.EconomyDataRequest: - #region Packet Session and User Check - if (m_checkPackets) + + EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; + if (handlerEconomoyDataRequest != null) { - if (joinGroupRequest.AgentData.SessionID != SessionId || - joinGroupRequest.AgentData.AgentID != AgentId) - break; + handlerEconomoyDataRequest(AgentId); } - #endregion + break; + case PacketType.RequestPayPrice: + RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; - if (m_GroupsModule != null) + RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice; + if (handlerRequestPayPrice != null) { - m_GroupsModule.JoinGroupRequest(this, - joinGroupRequest.GroupData.GroupID); + handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); } break; - case PacketType.LeaveGroupRequest: - LeaveGroupRequestPacket leaveGroupRequest = - (LeaveGroupRequestPacket)Pack; + case PacketType.ObjectSaleInfo: + ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (leaveGroupRequest.AgentData.SessionID != SessionId || - leaveGroupRequest.AgentData.AgentID != AgentId) + if (objectSaleInfoPacket.AgentData.SessionID != SessionId || + objectSaleInfoPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo; + if (handlerObjectSaleInfo != null) { - m_GroupsModule.LeaveGroupRequest(this, - leaveGroupRequest.GroupData.GroupID); + foreach (ObjectSaleInfoPacket.ObjectDataBlock d + in objectSaleInfoPacket.ObjectData) + { + handlerObjectSaleInfo(this, + objectSaleInfoPacket.AgentData.AgentID, + objectSaleInfoPacket.AgentData.SessionID, + d.LocalID, + d.SaleType, + d.SalePrice); + } } - break; - - case PacketType.EjectGroupMemberRequest: - EjectGroupMemberRequestPacket ejectGroupMemberRequest = - (EjectGroupMemberRequestPacket)Pack; + break; + + case PacketType.ObjectBuy: + ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || - ejectGroupMemberRequest.AgentData.AgentID != AgentId) + if (objectBuyPacket.AgentData.SessionID != SessionId || + objectBuyPacket.AgentData.AgentID != AgentId) break; } #endregion - if (m_GroupsModule != null) + ObjectBuy handlerObjectBuy = OnObjectBuy; + + if (handlerObjectBuy != null) { - foreach (EjectGroupMemberRequestPacket.EjectDataBlock e - in ejectGroupMemberRequest.EjectData) + foreach (ObjectBuyPacket.ObjectDataBlock d + in objectBuyPacket.ObjectData) { - m_GroupsModule.EjectGroupMemberRequest(this, - ejectGroupMemberRequest.GroupData.GroupID, - e.EjecteeID); + handlerObjectBuy(this, + objectBuyPacket.AgentData.AgentID, + objectBuyPacket.AgentData.SessionID, + objectBuyPacket.AgentData.GroupID, + objectBuyPacket.AgentData.CategoryID, + d.ObjectLocalID, + d.SaleType, + d.SalePrice); } } break; - case PacketType.InviteGroupRequest: - InviteGroupRequestPacket inviteGroupRequest = - (InviteGroupRequestPacket)Pack; - - #region Packet Session and User Check - if (m_checkPackets) - { - if (inviteGroupRequest.AgentData.SessionID != SessionId || - inviteGroupRequest.AgentData.AgentID != AgentId) - break; - } #endregion - if (m_GroupsModule != null) + #region Script Packets + + case PacketType.GetScriptRunning: + GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; + + GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning; + if (handlerGetScriptRunning != null) { - foreach (InviteGroupRequestPacket.InviteDataBlock b in - inviteGroupRequest.InviteData) - { - m_GroupsModule.InviteGroupRequest(this, - inviteGroupRequest.GroupData.GroupID, - b.InviteeID, - b.RoleID); - } + handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); } break; - #endregion - case PacketType.StartLure: - StartLurePacket startLureRequest = (StartLurePacket)Pack; + case PacketType.SetScriptRunning: + SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (startLureRequest.AgentData.SessionID != SessionId || - startLureRequest.AgentData.AgentID != AgentId) + if (setScriptRunning.AgentData.SessionID != SessionId || + setScriptRunning.AgentData.AgentID != AgentId) break; } #endregion - handlerStartLure = OnStartLure; - if (handlerStartLure != null) - handlerStartLure(startLureRequest.Info.LureType, - Utils.BytesToString( - startLureRequest.Info.Message), - startLureRequest.TargetData[0].TargetID, - this); + SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning; + if (handlerSetScriptRunning != null) + { + handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); + } break; - case PacketType.TeleportLureRequest: - TeleportLureRequestPacket teleportLureRequest = - (TeleportLureRequestPacket)Pack; + case PacketType.ScriptReset: + ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (teleportLureRequest.Info.SessionID != SessionId || - teleportLureRequest.Info.AgentID != AgentId) + if (scriptResetPacket.AgentData.SessionID != SessionId || + scriptResetPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerTeleportLureRequest = OnTeleportLureRequest; - if (handlerTeleportLureRequest != null) - handlerTeleportLureRequest( - teleportLureRequest.Info.LureID, - teleportLureRequest.Info.TeleportFlags, - this); + ScriptReset handlerScriptReset = OnScriptReset; + if (handlerScriptReset != null) + { + handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); + } break; - case PacketType.ClassifiedInfoRequest: - ClassifiedInfoRequestPacket classifiedInfoRequest = - (ClassifiedInfoRequestPacket)Pack; + #endregion + + #region Gesture Managment + + case PacketType.ActivateGestures: + ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (classifiedInfoRequest.AgentData.SessionID != SessionId || - classifiedInfoRequest.AgentData.AgentID != AgentId) + if (activateGesturePacket.AgentData.SessionID != SessionId || + activateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerClassifiedInfoRequest = OnClassifiedInfoRequest; - if (handlerClassifiedInfoRequest != null) - handlerClassifiedInfoRequest( - classifiedInfoRequest.Data.ClassifiedID, - this); + ActivateGesture handlerActivateGesture = OnActivateGesture; + if (handlerActivateGesture != null) + { + handlerActivateGesture(this, + activateGesturePacket.Data[0].AssetID, + activateGesturePacket.Data[0].ItemID); + } + else m_log.Error("Null pointer for activateGesture"); + break; - case PacketType.ClassifiedInfoUpdate: - ClassifiedInfoUpdatePacket classifiedInfoUpdate = - (ClassifiedInfoUpdatePacket)Pack; + case PacketType.DeactivateGestures: + DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (classifiedInfoUpdate.AgentData.SessionID != SessionId || - classifiedInfoUpdate.AgentData.AgentID != AgentId) + if (deactivateGesturePacket.AgentData.SessionID != SessionId || + deactivateGesturePacket.AgentData.AgentID != AgentId) break; } #endregion - handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; - if (handlerClassifiedInfoUpdate != null) - handlerClassifiedInfoUpdate( - classifiedInfoUpdate.Data.ClassifiedID, - classifiedInfoUpdate.Data.Category, - Utils.BytesToString( - classifiedInfoUpdate.Data.Name), - Utils.BytesToString( - classifiedInfoUpdate.Data.Desc), - classifiedInfoUpdate.Data.ParcelID, - classifiedInfoUpdate.Data.ParentEstate, - classifiedInfoUpdate.Data.SnapshotID, - new Vector3( - classifiedInfoUpdate.Data.PosGlobal), - classifiedInfoUpdate.Data.ClassifiedFlags, - classifiedInfoUpdate.Data.PriceForListing, - this); + DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture; + if (handlerDeactivateGesture != null) + { + handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); + } break; - - case PacketType.ClassifiedDelete: - ClassifiedDeletePacket classifiedDelete = - (ClassifiedDeletePacket)Pack; + case PacketType.ObjectOwner: + ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (classifiedDelete.AgentData.SessionID != SessionId || - classifiedDelete.AgentData.AgentID != AgentId) + if (objectOwnerPacket.AgentData.SessionID != SessionId || + objectOwnerPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerClassifiedDelete = OnClassifiedDelete; - if (handlerClassifiedDelete != null) - handlerClassifiedDelete( - classifiedDelete.Data.ClassifiedID, - this); - break; + List localIDs = new List(); - case PacketType.ClassifiedGodDelete: - ClassifiedGodDeletePacket classifiedGodDelete = - (ClassifiedGodDeletePacket)Pack; + foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) + localIDs.Add(d.ObjectLocalID); - #region Packet Session and User Check - if (m_checkPackets) + ObjectOwner handlerObjectOwner = OnObjectOwner; + if (handlerObjectOwner != null) { - if (classifiedGodDelete.AgentData.SessionID != SessionId || - classifiedGodDelete.AgentData.AgentID != AgentId) - break; + handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); } + break; + #endregion - handlerClassifiedGodDelete = OnClassifiedGodDelete; - if (handlerClassifiedGodDelete != null) - handlerClassifiedGodDelete( - classifiedGodDelete.Data.ClassifiedID, - this); + + #region unimplemented handlers + + case PacketType.StartPingCheck: + StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; + CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); + pingComplete.PingID.PingID = pingStart.PingID.PingID; + m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); break; - case PacketType.EventGodDelete: - EventGodDeletePacket eventGodDelete = - (EventGodDeletePacket)Pack; + case PacketType.CompletePingCheck: + // TODO: Do stats tracking or something with these? + break; + + case PacketType.ViewerStats: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); + break; + + case PacketType.MapItemRequest: + MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventGodDelete.AgentData.SessionID != SessionId || - eventGodDelete.AgentData.AgentID != AgentId) + if (mirpk.AgentData.SessionID != SessionId || + mirpk.AgentData.AgentID != AgentId) break; } #endregion - handlerEventGodDelete = OnEventGodDelete; - if (handlerEventGodDelete != null) - handlerEventGodDelete( - eventGodDelete.EventData.EventID, - eventGodDelete.QueryData.QueryID, - Utils.BytesToString( - eventGodDelete.QueryData.QueryText), - eventGodDelete.QueryData.QueryFlags, - eventGodDelete.QueryData.QueryStart, - this); + //m_log.Debug(mirpk.ToString()); + MapItemRequest handlerMapItemRequest = OnMapItemRequest; + if (handlerMapItemRequest != null) + { + handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, + mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, + mirpk.RequestData.RegionHandle); + + } break; - case PacketType.EventNotificationAddRequest: - EventNotificationAddRequestPacket eventNotificationAdd = - (EventNotificationAddRequestPacket)Pack; + case PacketType.TransferAbort: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); + break; + case PacketType.MuteListRequest: + MuteListRequestPacket muteListRequest = + (MuteListRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (eventNotificationAdd.AgentData.SessionID != SessionId || - eventNotificationAdd.AgentData.AgentID != AgentId) + if (muteListRequest.AgentData.SessionID != SessionId || + muteListRequest.AgentData.AgentID != AgentId) break; } #endregion - handlerEventNotificationAddRequest = OnEventNotificationAddRequest; - if (handlerEventNotificationAddRequest != null) - handlerEventNotificationAddRequest( - eventNotificationAdd.EventData.EventID, this); + MuteListRequest handlerMuteListRequest = OnMuteListRequest; + if (handlerMuteListRequest != null) + { + handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); + } + else + { + SendUseCachedMuteList(); + } + break; + case PacketType.UseCircuitCode: + // Don't display this one, we handle it at a lower level break; - case PacketType.EventNotificationRemoveRequest: - EventNotificationRemoveRequestPacket eventNotificationRemove = - (EventNotificationRemoveRequestPacket)Pack; + case PacketType.AgentHeightWidth: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); + break; + + case PacketType.InventoryDescendents: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); + + break; + case PacketType.DirPlacesQuery: + DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; + //m_log.Debug(dirPlacesQueryPacket.ToString()); #region Packet Session and User Check if (m_checkPackets) { - if (eventNotificationRemove.AgentData.SessionID != SessionId || - eventNotificationRemove.AgentData.AgentID != AgentId) + if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || + dirPlacesQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; - if (handlerEventNotificationRemoveRequest != null) - handlerEventNotificationRemoveRequest( - eventNotificationRemove.EventData.EventID, this); + DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery; + if (handlerDirPlacesQuery != null) + { + handlerDirPlacesQuery(this, + dirPlacesQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.QueryText), + (int)dirPlacesQueryPacket.QueryData.QueryFlags, + (int)dirPlacesQueryPacket.QueryData.Category, + Utils.BytesToString( + dirPlacesQueryPacket.QueryData.SimName), + dirPlacesQueryPacket.QueryData.QueryStart); + } break; - - case PacketType.RetrieveInstantMessages: - RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; + case PacketType.DirFindQuery: + DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (rimpInstantMessagePack.AgentData.SessionID != SessionId || - rimpInstantMessagePack.AgentData.AgentID != AgentId) + if (dirFindQueryPacket.AgentData.SessionID != SessionId || + dirFindQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerRetrieveInstantMessages = OnRetrieveInstantMessages; - if (handlerRetrieveInstantMessages != null) - handlerRetrieveInstantMessages(this); + DirFindQuery handlerDirFindQuery = OnDirFindQuery; + if (handlerDirFindQuery != null) + { + handlerDirFindQuery(this, + dirFindQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirFindQueryPacket.QueryData.QueryText), + dirFindQueryPacket.QueryData.QueryFlags, + dirFindQueryPacket.QueryData.QueryStart); + } break; - - case PacketType.PickDelete: - PickDeletePacket pickDelete = - (PickDeletePacket)Pack; + case PacketType.DirLandQuery: + DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickDelete.AgentData.SessionID != SessionId || - pickDelete.AgentData.AgentID != AgentId) + if (dirLandQueryPacket.AgentData.SessionID != SessionId || + dirLandQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickDelete = OnPickDelete; - if (handlerPickDelete != null) - handlerPickDelete(this, pickDelete.Data.PickID); + DirLandQuery handlerDirLandQuery = OnDirLandQuery; + if (handlerDirLandQuery != null) + { + handlerDirLandQuery(this, + dirLandQueryPacket.QueryData.QueryID, + dirLandQueryPacket.QueryData.QueryFlags, + dirLandQueryPacket.QueryData.SearchType, + dirLandQueryPacket.QueryData.Price, + dirLandQueryPacket.QueryData.Area, + dirLandQueryPacket.QueryData.QueryStart); + } break; - case PacketType.PickGodDelete: - PickGodDeletePacket pickGodDelete = - (PickGodDeletePacket)Pack; + case PacketType.DirPopularQuery: + DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickGodDelete.AgentData.SessionID != SessionId || - pickGodDelete.AgentData.AgentID != AgentId) + if (dirPopularQueryPacket.AgentData.SessionID != SessionId || + dirPopularQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickGodDelete = OnPickGodDelete; - if (handlerPickGodDelete != null) - handlerPickGodDelete(this, - pickGodDelete.AgentData.AgentID, - pickGodDelete.Data.PickID, - pickGodDelete.Data.QueryID); + DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery; + if (handlerDirPopularQuery != null) + { + handlerDirPopularQuery(this, + dirPopularQueryPacket.QueryData.QueryID, + dirPopularQueryPacket.QueryData.QueryFlags); + } break; - case PacketType.PickInfoUpdate: - PickInfoUpdatePacket pickInfoUpdate = - (PickInfoUpdatePacket)Pack; + case PacketType.DirClassifiedQuery: + DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (pickInfoUpdate.AgentData.SessionID != SessionId || - pickInfoUpdate.AgentData.AgentID != AgentId) + if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || + dirClassifiedQueryPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerPickInfoUpdate = OnPickInfoUpdate; - if (handlerPickInfoUpdate != null) - handlerPickInfoUpdate(this, - pickInfoUpdate.Data.PickID, - pickInfoUpdate.Data.CreatorID, - pickInfoUpdate.Data.TopPick, - Utils.BytesToString(pickInfoUpdate.Data.Name), - Utils.BytesToString(pickInfoUpdate.Data.Desc), - pickInfoUpdate.Data.SnapshotID, - pickInfoUpdate.Data.SortOrder, - pickInfoUpdate.Data.Enabled); + DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery; + if (handlerDirClassifiedQuery != null) + { + handlerDirClassifiedQuery(this, + dirClassifiedQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirClassifiedQueryPacket.QueryData.QueryText), + dirClassifiedQueryPacket.QueryData.QueryFlags, + dirClassifiedQueryPacket.QueryData.Category, + dirClassifiedQueryPacket.QueryData.QueryStart); + } break; - case PacketType.AvatarNotesUpdate: - AvatarNotesUpdatePacket avatarNotesUpdate = - (AvatarNotesUpdatePacket)Pack; + case PacketType.EventInfoRequest: + EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; #region Packet Session and User Check if (m_checkPackets) { - if (avatarNotesUpdate.AgentData.SessionID != SessionId || - avatarNotesUpdate.AgentData.AgentID != AgentId) + if (eventInfoRequestPacket.AgentData.SessionID != SessionId || + eventInfoRequestPacket.AgentData.AgentID != AgentId) break; } #endregion - handlerAvatarNotesUpdate = OnAvatarNotesUpdate; - if (handlerAvatarNotesUpdate != null) - handlerAvatarNotesUpdate(this, - avatarNotesUpdate.Data.TargetID, - Utils.BytesToString(avatarNotesUpdate.Data.Notes)); - break; - -// case PacketType.AvatarInterestsUpdate: -// AvatarInterestsUpdatePacket avatarInterestUpdate = -// (AvatarInterestsUpdatePacket)Pack; -// -// break; - - case PacketType.PlacesQuery: - PlacesQueryPacket placesQueryPacket = - (PlacesQueryPacket)Pack; - - handlerPlacesQuery = OnPlacesQuery; - - if (handlerPlacesQuery != null) - handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, - placesQueryPacket.TransactionData.TransactionID, - Utils.BytesToString( - placesQueryPacket.QueryData.QueryText), - placesQueryPacket.QueryData.QueryFlags, - (byte)placesQueryPacket.QueryData.Category, - Utils.BytesToString( - placesQueryPacket.QueryData.SimName), - this); - break; - default: - m_log.Warn("[CLIENT]: unhandled packet " + Pack); + if (OnEventInfoRequest != null) + { + OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); + } break; - #endregion - } - - PacketPool.Instance.ReturnPacket(Pack); - - } - - private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) - { - PrimitiveBaseShape shape = new PrimitiveBaseShape(); - - shape.PCode = addPacket.ObjectData.PCode; - shape.State = addPacket.ObjectData.State; - shape.PathBegin = addPacket.ObjectData.PathBegin; - shape.PathEnd = addPacket.ObjectData.PathEnd; - shape.PathScaleX = addPacket.ObjectData.PathScaleX; - shape.PathScaleY = addPacket.ObjectData.PathScaleY; - shape.PathShearX = addPacket.ObjectData.PathShearX; - shape.PathShearY = addPacket.ObjectData.PathShearY; - shape.PathSkew = addPacket.ObjectData.PathSkew; - shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; - shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; - shape.Scale = addPacket.ObjectData.Scale; - shape.PathCurve = addPacket.ObjectData.PathCurve; - shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; - shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; - shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; - shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; - shape.PathTaperX = addPacket.ObjectData.PathTaperX; - shape.PathTaperY = addPacket.ObjectData.PathTaperY; - shape.PathTwist = addPacket.ObjectData.PathTwist; - shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; - Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); - shape.TextureEntry = ntex.GetBytes(); - //shape.Textures = ntex; - return shape; - } - - /// - /// Send the client an Estate message blue box pop-down with a single OK button - /// - /// - /// - /// - /// - public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) - { - if (!ChildAgentStatus()) - SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); - - //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); - } - - public void SendLogoutPacket() - { - // I know this is a bit of a hack, however there are times when you don't - // want to send this, but still need to do the rest of the shutdown process - // this method gets called from the packet server.. which makes it practically - // impossible to do any other way. - - if (m_SendLogoutPacketWhenClosing) - { - LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); - // TODO: don't create new blocks if recycling an old packet - logReply.AgentData.AgentID = AgentId; - logReply.AgentData.SessionID = SessionId; - logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; - logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); - logReply.InventoryData[0].ItemID = UUID.Zero; - - OutPacket(logReply, ThrottleOutPacketType.Task); - } - } + #region Calling Card - public void SendHealth(float health) - { - HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage); - healthpacket.HealthData.Health = health; - OutPacket(healthpacket, ThrottleOutPacketType.Task); - } + case PacketType.OfferCallingCard: + OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; - public void SendAgentOnline(UUID[] agentIDs) - { - OnlineNotificationPacket onp = new OnlineNotificationPacket(); - OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) - { - OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - onpb[i] = onpbl; - } - onp.AgentBlock = onpb; - onp.Header.Reliable = true; - OutPacket(onp, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (offerCallingCardPacket.AgentData.SessionID != SessionId || + offerCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAgentOffline(UUID[] agentIDs) - { - OfflineNotificationPacket offp = new OfflineNotificationPacket(); - OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length]; - for (int i = 0; i < agentIDs.Length; i++) - { - OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = agentIDs[i]; - offpb[i] = onpbl; - } - offp.AgentBlock = offpb; - offp.Header.Reliable = true; - OutPacket(offp, ThrottleOutPacketType.Task); - } + if (OnOfferCallingCard != null) + { + OnOfferCallingCard(this, + offerCallingCardPacket.AgentBlock.DestID, + offerCallingCardPacket.AgentBlock.TransactionID); + } + break; - public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, - Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) - { - AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); - avatarSitResponse.SitObject.ID = TargetID; - if (CameraAtOffset != Vector3.Zero) - { - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; - } - avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; - avatarSitResponse.SitTransform.AutoPilot = autopilot; - avatarSitResponse.SitTransform.SitPosition = OffsetPos; - avatarSitResponse.SitTransform.SitRotation = SitOrientation; + case PacketType.AcceptCallingCard: + AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; - OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (acceptCallingCardPacket.AgentData.SessionID != SessionId || + acceptCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAdminResponse(UUID Token, uint AdminLevel) - { - GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); - GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); - GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); + // according to http://wiki.secondlife.com/wiki/AcceptCallingCard FolderData should + // contain exactly one entry + if (OnAcceptCallingCard != null && acceptCallingCardPacket.FolderData.Length > 0) + { + OnAcceptCallingCard(this, + acceptCallingCardPacket.TransactionBlock.TransactionID, + acceptCallingCardPacket.FolderData[0].FolderID); + } + break; - adb.AgentID = AgentId; - adb.SessionID = SessionId; // More security - gdb.GodLevel = (byte)AdminLevel; - gdb.Token = Token; - //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; - respondPacket.GrantData = gdb; - respondPacket.AgentData = adb; - OutPacket(respondPacket, ThrottleOutPacketType.Task); - } + case PacketType.DeclineCallingCard: + DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; - public void SendGroupMembership(GroupMembershipData[] GroupMembership) - { - m_groupPowers.Clear(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (declineCallingCardPacket.AgentData.SessionID != SessionId || + declineCallingCardPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket(); - AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length]; - for (int i = 0; i < GroupMembership.Length; i++) - { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + if (OnDeclineCallingCard != null) + { + OnDeclineCallingCard(this, + declineCallingCardPacket.TransactionBlock.TransactionID); + } + break; + #endregion - AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock(); - Group.AcceptNotices = GroupMembership[i].AcceptNotices; - Group.Contribution = GroupMembership[i].Contribution; - Group.GroupID = GroupMembership[i].GroupID; - Group.GroupInsigniaID = GroupMembership[i].GroupPicture; - Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); - Group.GroupPowers = GroupMembership[i].GroupPowers; - Groups[i] = Group; - + #region Groups + case PacketType.ActivateGroup: + ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; - } - Groupupdate.GroupData = Groups; - Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); - Groupupdate.AgentData.AgentID = AgentId; - OutPacket(Groupupdate, ThrottleOutPacketType.Task); + #region Packet Session and User Check + if (m_checkPackets) + { + if (activateGroupPacket.AgentData.SessionID != SessionId || + activateGroupPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - try - { - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - eq.GroupMembership(Groupupdate, this.AgentId); - } - } - catch (Exception ex) - { - m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString()); - m_log.Warn("sending group membership data via UDP"); - OutPacket(Groupupdate, ThrottleOutPacketType.Task); - } - } + if (m_GroupsModule != null) + { + m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); + m_GroupsModule.SendAgentGroupDataUpdate(this); + } + break; + case PacketType.GroupTitlesRequest: + GroupTitlesRequestPacket groupTitlesRequest = + (GroupTitlesRequestPacket)Pack; - public void SendGroupNameReply(UUID groupLLUID, string GroupName) - { - UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket(); - UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; - UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); - uidnamebloc.ID = groupLLUID; - uidnamebloc.GroupName = Utils.StringToBytes(GroupName); - uidnameblock[0] = uidnamebloc; - pack.UUIDNameBlock = uidnameblock; - OutPacket(pack, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitlesRequest.AgentData.SessionID != SessionId || + groupTitlesRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) - { - LandStatReplyPacket lsrp = new LandStatReplyPacket(); - // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); - LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; - //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - // lsrepdb. - lsrp.RequestData.ReportType = reportType; - lsrp.RequestData.RequestFlags = requestFlags; - lsrp.RequestData.TotalObjectCount = resultCount; - for (int i = 0; i < lsrpia.Length; i++) - { - LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - lsrepdb.LocationX = lsrpia[i].LocationX; - lsrepdb.LocationY = lsrpia[i].LocationY; - lsrepdb.LocationZ = lsrpia[i].LocationZ; - lsrepdb.Score = lsrpia[i].Score; - lsrepdb.TaskID = lsrpia[i].TaskID; - lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; - lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); - lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); - lsrepdba[i] = lsrepdb; - } - lsrp.ReportData = lsrepdba; - OutPacket(lsrp, ThrottleOutPacketType.Task); - } + if (m_GroupsModule != null) + { + GroupTitlesReplyPacket groupTitlesReply = (GroupTitlesReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupTitlesReply); - public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) - { - ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket(); - scriptRunningReply.Script.ObjectID = objectID; - scriptRunningReply.Script.ItemID = itemID; - scriptRunningReply.Script.Running = running; + groupTitlesReply.AgentData = + new GroupTitlesReplyPacket.AgentDataBlock(); - OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); - } + groupTitlesReply.AgentData.AgentID = AgentId; + groupTitlesReply.AgentData.GroupID = + groupTitlesRequest.AgentData.GroupID; - public void SendAsset(AssetRequestToClient req) - { - //m_log.Debug("sending asset " + req.RequestAssetID); - TransferInfoPacket Transfer = new TransferInfoPacket(); - Transfer.TransferInfo.ChannelType = 2; - Transfer.TransferInfo.Status = 0; - Transfer.TransferInfo.TargetType = 0; - if (req.AssetRequestSource == 2) - { - Transfer.TransferInfo.Params = new byte[20]; - Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - int assType = req.AssetInf.Type; - Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); - } - else if (req.AssetRequestSource == 3) - { - Transfer.TransferInfo.Params = req.Params; - // Transfer.TransferInfo.Params = new byte[100]; - //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); - //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); - } - Transfer.TransferInfo.Size = req.AssetInf.Data.Length; - Transfer.TransferInfo.TransferID = req.TransferRequestID; - Transfer.Header.Zerocoded = true; - OutPacket(Transfer, ThrottleOutPacketType.Asset); + groupTitlesReply.AgentData.RequestID = + groupTitlesRequest.AgentData.RequestID; - if (req.NumPackets == 1) - { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 0; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; - TransferPacket.TransferData.Data = req.AssetInf.Data; - TransferPacket.TransferData.Status = 1; - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - } - else - { - int processedLength = 0; - int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; - int packetNumber = 0; + List titles = + m_GroupsModule.GroupTitlesRequest(this, + groupTitlesRequest.AgentData.GroupID); - while (processedLength < req.AssetInf.Data.Length) - { - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = packetNumber; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = req.TransferRequestID; + groupTitlesReply.GroupData = + new GroupTitlesReplyPacket.GroupDataBlock[titles.Count]; - int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); - byte[] chunk = new byte[chunkSize]; - Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); + int i = 0; + foreach (GroupTitlesData d in titles) + { + groupTitlesReply.GroupData[i] = + new GroupTitlesReplyPacket.GroupDataBlock(); - TransferPacket.TransferData.Data = chunk; + groupTitlesReply.GroupData[i].Title = + Utils.StringToBytes(d.Name); + groupTitlesReply.GroupData[i].RoleID = + d.UUID; + groupTitlesReply.GroupData[i].Selected = + d.Selected; + i++; + } - // 0 indicates more packets to come, 1 indicates last packet - if (req.AssetInf.Data.Length - processedLength > maxChunkSize) + OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + } + break; + + case PacketType.GroupProfileRequest: + GroupProfileRequestPacket groupProfileRequest = + (GroupProfileRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) { - TransferPacket.TransferData.Status = 0; + if (groupProfileRequest.AgentData.SessionID != SessionId || + groupProfileRequest.AgentData.AgentID != AgentId) + break; } - else + #endregion + + if (m_GroupsModule != null) { - TransferPacket.TransferData.Status = 1; + GroupProfileReplyPacket groupProfileReply = (GroupProfileReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupProfileReply); + + groupProfileReply.AgentData = new GroupProfileReplyPacket.AgentDataBlock(); + groupProfileReply.GroupData = new GroupProfileReplyPacket.GroupDataBlock(); + groupProfileReply.AgentData.AgentID = AgentId; + + GroupProfileData d = m_GroupsModule.GroupProfileRequest(this, + groupProfileRequest.GroupData.GroupID); + + groupProfileReply.GroupData.GroupID = d.GroupID; + groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); + groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); + groupProfileReply.GroupData.ShowInList = d.ShowInList; + groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); + groupProfileReply.GroupData.PowersMask = d.PowersMask; + groupProfileReply.GroupData.InsigniaID = d.InsigniaID; + groupProfileReply.GroupData.FounderID = d.FounderID; + groupProfileReply.GroupData.MembershipFee = d.MembershipFee; + groupProfileReply.GroupData.OpenEnrollment = d.OpenEnrollment; + groupProfileReply.GroupData.Money = d.Money; + groupProfileReply.GroupData.GroupMembershipCount = d.GroupMembershipCount; + groupProfileReply.GroupData.GroupRolesCount = d.GroupRolesCount; + groupProfileReply.GroupData.AllowPublish = d.AllowPublish; + groupProfileReply.GroupData.MaturePublish = d.MaturePublish; + groupProfileReply.GroupData.OwnerRole = d.OwnerRole; + + OutPacket(groupProfileReply, ThrottleOutPacketType.Task); } - TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + break; - processedLength += chunkSize; - packetNumber++; - } - } - } + case PacketType.GroupMembersRequest: + GroupMembersRequestPacket groupMembersRequestPacket = + (GroupMembersRequestPacket)Pack; - public void SendTexture(AssetBase TextureAsset) - { + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupMembersRequestPacket.AgentData.SessionID != SessionId || + groupMembersRequestPacket.AgentData.AgentID != AgentId) + break; + } + #endregion - } + if (m_GroupsModule != null) + { + List members = + m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); - public ClientInfo GetClientInfo() - { - ClientInfo info = m_PacketHandler.GetClientInfo(); + int memberCount = members.Count; - info.userEP = m_userEndPoint; - info.proxyEP = m_proxyEndPoint; - info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); + while (true) + { + int blockCount = members.Count; + if (blockCount > 40) + blockCount = 40; - return info; - } + GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); - public EndPoint GetClientEP() - { - return m_userEndPoint; - } + groupMembersReply.AgentData = + new GroupMembersReplyPacket.AgentDataBlock(); + groupMembersReply.GroupData = + new GroupMembersReplyPacket.GroupDataBlock(); + groupMembersReply.MemberData = + new GroupMembersReplyPacket.MemberDataBlock[ + blockCount]; - public void SetClientInfo(ClientInfo info) - { - m_PacketHandler.SetClientInfo(info); - } + groupMembersReply.AgentData.AgentID = AgentId; + groupMembersReply.GroupData.GroupID = + groupMembersRequestPacket.GroupData.GroupID; + groupMembersReply.GroupData.RequestID = + groupMembersRequestPacket.GroupData.RequestID; + groupMembersReply.GroupData.MemberCount = memberCount; - #region Media Parcel Members + for (int i = 0 ; i < blockCount ; i++) + { + GroupMembersData m = members[0]; + members.RemoveAt(0); - public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) - { - ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); - commandMessagePacket.CommandBlock.Flags = flags; - commandMessagePacket.CommandBlock.Command =(uint) command; - commandMessagePacket.CommandBlock.Time = time; + groupMembersReply.MemberData[i] = + new GroupMembersReplyPacket.MemberDataBlock(); + groupMembersReply.MemberData[i].AgentID = + m.AgentID; + groupMembersReply.MemberData[i].Contribution = + m.Contribution; + groupMembersReply.MemberData[i].OnlineStatus = + Utils.StringToBytes(m.OnlineStatus); + groupMembersReply.MemberData[i].AgentPowers = + m.AgentPowers; + groupMembersReply.MemberData[i].Title = + Utils.StringToBytes(m.Title); + groupMembersReply.MemberData[i].IsOwner = + m.IsOwner; + } + OutPacket(groupMembersReply, ThrottleOutPacketType.Task); + if (members.Count == 0) + break; + } + } + break; - OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); - } + case PacketType.GroupRoleDataRequest: + GroupRoleDataRequestPacket groupRolesRequest = + (GroupRoleDataRequestPacket)Pack; - public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, - byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, - byte mediaLoop) - { - ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); - updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); - updatePacket.DataBlock.MediaID = mediaTextureID; - updatePacket.DataBlock.MediaAutoScale = autoScale; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRolesRequest.AgentData.SessionID != SessionId || + groupRolesRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); - updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); - updatePacket.DataBlockExtended.MediaWidth = mediaWidth; - updatePacket.DataBlockExtended.MediaHeight = mediaHeight; - updatePacket.DataBlockExtended.MediaLoop = mediaLoop; + if (m_GroupsModule != null) + { + GroupRoleDataReplyPacket groupRolesReply = (GroupRoleDataReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleDataReply); - OutPacket(updatePacket, ThrottleOutPacketType.Unknown); - } + groupRolesReply.AgentData = + new GroupRoleDataReplyPacket.AgentDataBlock(); - #endregion + groupRolesReply.AgentData.AgentID = AgentId; + groupRolesReply.GroupData = + new GroupRoleDataReplyPacket.GroupDataBlock(); - #region Camera + groupRolesReply.GroupData.GroupID = + groupRolesRequest.GroupData.GroupID; - public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) - { - SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; - uint idx = 0; - foreach (KeyValuePair pair in parameters) - { - SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); - block.Type = pair.Key; - block.Value = pair.Value; + groupRolesReply.GroupData.RequestID = + groupRolesRequest.GroupData.RequestID; - camPropBlock[idx++] = block; - } - packet.CameraProperty = camPropBlock; - OutPacket(packet, ThrottleOutPacketType.Task); - } + List titles = + m_GroupsModule.GroupRoleDataRequest(this, + groupRolesRequest.GroupData.GroupID); + + groupRolesReply.GroupData.RoleCount = + titles.Count; + + groupRolesReply.RoleData = + new GroupRoleDataReplyPacket.RoleDataBlock[titles.Count]; + + int i = 0; + foreach (GroupRolesData d in titles) + { + groupRolesReply.RoleData[i] = + new GroupRoleDataReplyPacket.RoleDataBlock(); + + groupRolesReply.RoleData[i].RoleID = + d.RoleID; + groupRolesReply.RoleData[i].Name = + Utils.StringToBytes(d.Name); + groupRolesReply.RoleData[i].Title = + Utils.StringToBytes(d.Title); + groupRolesReply.RoleData[i].Description = + Utils.StringToBytes(d.Description); + groupRolesReply.RoleData[i].Powers = + d.Powers; + groupRolesReply.RoleData[i].Members = + (uint)d.Members; + + i++; + } + + OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + } + break; - public void SendClearFollowCamProperties (UUID objectID) - { - ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); - packet.ObjectData.ObjectID = objectID; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupRoleMembersRequest: + GroupRoleMembersRequestPacket groupRoleMembersRequest = + (GroupRoleMembersRequestPacket)Pack; - #endregion + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleMembersRequest.AgentData.SessionID != SessionId || + groupRoleMembersRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendRegionHandle(UUID regionID, ulong handle) { - RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply); - reply.ReplyBlock.RegionID = regionID; - reply.ReplyBlock.RegionHandle = handle; - OutPacket(reply, ThrottleOutPacketType.Land); - } + if (m_GroupsModule != null) + { + List mappings = + m_GroupsModule.GroupRoleMembersRequest(this, + groupRoleMembersRequest.GroupData.GroupID); - public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) - { - ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); - reply.AgentData.AgentID = m_agentId; - reply.Data.ParcelID = parcelID; - reply.Data.OwnerID = land.OwnerID; - reply.Data.Name = Utils.StringToBytes(land.Name); - reply.Data.Desc = Utils.StringToBytes(land.Description); - reply.Data.ActualArea = land.Area; - reply.Data.BillableArea = land.Area; // TODO: what is this? + int mappingsCount = mappings.Count; - // Bit 0: Mature, bit 7: on sale, other bits: no idea - reply.Data.Flags = (byte)( - ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + - ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); + while (mappings.Count > 0) + { + int pairs = mappings.Count; + if (pairs > 32) + pairs = 32; - Vector3 pos = land.UserLocation; - if (pos.Equals(Vector3.Zero)) - { - pos = (land.AABBMax + land.AABBMin) * 0.5f; - } - reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; - reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; - reply.Data.GlobalZ = pos.Z; - reply.Data.SimName = Utils.StringToBytes(info.RegionName); - reply.Data.SnapshotID = land.SnapshotID; - reply.Data.Dwell = land.Dwell; - reply.Data.SalePrice = land.SalePrice; - reply.Data.AuctionID = (int)land.AuctionID; + GroupRoleMembersReplyPacket groupRoleMembersReply = (GroupRoleMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupRoleMembersReply); + groupRoleMembersReply.AgentData = + new GroupRoleMembersReplyPacket.AgentDataBlock(); + groupRoleMembersReply.AgentData.AgentID = + AgentId; + groupRoleMembersReply.AgentData.GroupID = + groupRoleMembersRequest.GroupData.GroupID; + groupRoleMembersReply.AgentData.RequestID = + groupRoleMembersRequest.GroupData.RequestID; - OutPacket(reply, ThrottleOutPacketType.Land); - } + groupRoleMembersReply.AgentData.TotalPairs = + (uint)mappingsCount; - public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) - { - ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); + groupRoleMembersReply.MemberData = + new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; - packet.Data.ObjectName = Utils.StringToBytes(objName); - packet.Data.SimName = Utils.StringToBytes(simName); - packet.Data.SimPosition = pos; - packet.Data.LookAt = lookAt; + for (int i = 0 ; i < pairs ; i++) + { + GroupRoleMembersData d = mappings[0]; + mappings.RemoveAt(0); - OutPacket(packet, ThrottleOutPacketType.Task); - } + groupRoleMembersReply.MemberData[i] = + new GroupRoleMembersReplyPacket.MemberDataBlock(); - public void SetClientOption(string option, string value) - { - switch (option) - { - case "ReliableIsImportant": - bool val; + groupRoleMembersReply.MemberData[i].RoleID = + d.RoleID; + groupRoleMembersReply.MemberData[i].MemberID = + d.MemberID; + } - if (bool.TryParse(value, out val)) - m_PacketHandler.ReliableIsImportant = val; - break; - default: - break; - } - } + OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); + } + } + break; - public string GetClientOption(string option) - { - switch (option) - { - case "ReliableIsImportant": - return m_PacketHandler.ReliableIsImportant.ToString(); + case PacketType.CreateGroupRequest: + CreateGroupRequestPacket createGroupRequest = + (CreateGroupRequestPacket)Pack; - default: + #region Packet Session and User Check + if (m_checkPackets) + { + if (createGroupRequest.AgentData.SessionID != SessionId || + createGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.CreateGroup(this, + Utils.BytesToString(createGroupRequest.GroupData.Name), + Utils.BytesToString(createGroupRequest.GroupData.Charter), + createGroupRequest.GroupData.ShowInList, + createGroupRequest.GroupData.InsigniaID, + createGroupRequest.GroupData.MembershipFee, + createGroupRequest.GroupData.OpenEnrollment, + createGroupRequest.GroupData.AllowPublish, + createGroupRequest.GroupData.MaturePublish); + } break; - } - return string.Empty; - } - public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) - { - DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + case PacketType.UpdateGroupInfo: + UpdateGroupInfoPacket updateGroupInfo = + (UpdateGroupInfoPacket)Pack; - packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + #region Packet Session and User Check + if (m_checkPackets) + { + if (updateGroupInfo.AgentData.SessionID != SessionId || + updateGroupInfo.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; - packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + if (m_GroupsModule != null) + { + m_GroupsModule.UpdateGroupInfo(this, + updateGroupInfo.GroupData.GroupID, + Utils.BytesToString(updateGroupInfo.GroupData.Charter), + updateGroupInfo.GroupData.ShowInList, + updateGroupInfo.GroupData.InsigniaID, + updateGroupInfo.GroupData.MembershipFee, + updateGroupInfo.GroupData.OpenEnrollment, + updateGroupInfo.GroupData.AllowPublish, + updateGroupInfo.GroupData.MaturePublish); + } - packet.QueryReplies = - new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; + break; - packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ - data.Length]; + case PacketType.SetGroupAcceptNotices: + SetGroupAcceptNoticesPacket setGroupAcceptNotices = + (SetGroupAcceptNoticesPacket)Pack; - packet.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (setGroupAcceptNotices.AgentData.SessionID != SessionId || + setGroupAcceptNotices.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryData[0].QueryID = queryID; + if (m_GroupsModule != null) + { + m_GroupsModule.SetGroupAcceptNotices(this, + setGroupAcceptNotices.Data.GroupID, + setGroupAcceptNotices.Data.AcceptNotices, + setGroupAcceptNotices.NewData.ListInProfile); + } - int i = 0; - foreach (DirPlacesReplyData d in data) - { - packet.QueryReplies[i] = - new DirPlacesReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].Dwell = d.dwell; - packet.StatusData[i].Status = d.Status; - i++; - } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupTitleUpdate: + GroupTitleUpdatePacket groupTitleUpdate = + (GroupTitleUpdatePacket)Pack; - public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) - { - DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitleUpdate.AgentData.SessionID != SessionId || + groupTitleUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + m_GroupsModule.GroupTitleUpdate(this, + groupTitleUpdate.AgentData.GroupID, + groupTitleUpdate.AgentData.TitleRoleID); + } - packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + break; - packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[ - data.Length]; - int i = 0; - foreach (DirPeopleReplyData d in data) - { - packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].AgentID = d.agentID; - packet.QueryReplies[i].FirstName = - Utils.StringToBytes(d.firstName); - packet.QueryReplies[i].LastName = - Utils.StringToBytes(d.lastName); - packet.QueryReplies[i].Group = - Utils.StringToBytes(d.group); - packet.QueryReplies[i].Online = d.online; - packet.QueryReplies[i].Reputation = d.reputation; - i++; - } + case PacketType.ParcelDeedToGroup: + ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; + if (m_GroupsModule != null) + { + ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; + if (handlerParcelDeedToGroup != null) + { + handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); - OutPacket(packet, ThrottleOutPacketType.Task); - } + } + } - public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) - { - DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply); + break; - packet.AgentData = new DirEventsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; - packet.QueryData = new DirEventsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.GroupNoticesListRequest: + GroupNoticesListRequestPacket groupNoticesListRequest = + (GroupNoticesListRequestPacket)Pack; - packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticesListRequest.AgentData.SessionID != SessionId || + groupNoticesListRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ - data.Length]; + if (m_GroupsModule != null) + { + GroupNoticeData[] gn = + m_GroupsModule.GroupNoticesListRequest(this, + groupNoticesListRequest.Data.GroupID); - int i = 0; - foreach (DirEventsReplyData d in data) - { - packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].OwnerID = d.ownerID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].EventID = d.eventID; - packet.QueryReplies[i].Date = - Utils.StringToBytes(d.date); - packet.QueryReplies[i].UnixTime = d.unixTime; - packet.QueryReplies[i].EventFlags = d.eventFlags; - packet.StatusData[i].Status = d.Status; - i++; - } + GroupNoticesListReplyPacket groupNoticesListReply = (GroupNoticesListReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupNoticesListReply); + groupNoticesListReply.AgentData = + new GroupNoticesListReplyPacket.AgentDataBlock(); + groupNoticesListReply.AgentData.AgentID = AgentId; + groupNoticesListReply.AgentData.GroupID = groupNoticesListRequest.Data.GroupID; - OutPacket(packet, ThrottleOutPacketType.Task); - } + groupNoticesListReply.Data = new GroupNoticesListReplyPacket.DataBlock[gn.Length]; - public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) - { - DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply); + int i = 0; + foreach (GroupNoticeData g in gn) + { + groupNoticesListReply.Data[i] = new GroupNoticesListReplyPacket.DataBlock(); + groupNoticesListReply.Data[i].NoticeID = + g.NoticeID; + groupNoticesListReply.Data[i].Timestamp = + g.Timestamp; + groupNoticesListReply.Data[i].FromName = + Utils.StringToBytes(g.FromName); + groupNoticesListReply.Data[i].Subject = + Utils.StringToBytes(g.Subject); + groupNoticesListReply.Data[i].HasAttachment = + g.HasAttachment; + groupNoticesListReply.Data[i].AssetType = + g.AssetType; + i++; + } - packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); + } - packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + break; + case PacketType.GroupNoticeRequest: + GroupNoticeRequestPacket groupNoticeRequest = + (GroupNoticeRequestPacket)Pack; - packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticeRequest.AgentData.SessionID != SessionId || + groupNoticeRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - int i = 0; - foreach (DirGroupsReplyData d in data) - { - packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].GroupID = d.groupID; - packet.QueryReplies[i].GroupName = - Utils.StringToBytes(d.groupName); - packet.QueryReplies[i].Members = d.members; - packet.QueryReplies[i].SearchOrder = d.searchOrder; - i++; - } + if (m_GroupsModule != null) + { + m_GroupsModule.GroupNoticeRequest(this, + groupNoticeRequest.Data.GroupNoticeID); + } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.GroupRoleUpdate: + GroupRoleUpdatePacket groupRoleUpdate = + (GroupRoleUpdatePacket)Pack; - public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) - { - DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleUpdate.AgentData.SessionID != SessionId || + groupRoleUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + foreach (GroupRoleUpdatePacket.RoleDataBlock d in + groupRoleUpdate.RoleData) + { + m_GroupsModule.GroupRoleUpdate(this, + groupRoleUpdate.AgentData.GroupID, + d.RoleID, + Utils.BytesToString(d.Name), + Utils.BytesToString(d.Description), + Utils.BytesToString(d.Title), + d.Powers, + d.UpdateType); + } + m_GroupsModule.NotifyChange(groupRoleUpdate.AgentData.GroupID); + } + break; - packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.GroupRoleChanges: + GroupRoleChangesPacket groupRoleChanges = + (GroupRoleChangesPacket)Pack; - packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[ - data.Length]; - packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[ - data.Length]; + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleChanges.AgentData.SessionID != SessionId || + groupRoleChanges.AgentData.AgentID != AgentId) + break; + } + #endregion - int i = 0; - foreach (DirClassifiedReplyData d in data) - { - packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ClassifiedID = d.classifiedID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags; - packet.QueryReplies[i].CreationDate = d.creationDate; - packet.QueryReplies[i].ExpirationDate = d.expirationDate; - packet.QueryReplies[i].PriceForListing = d.price; - packet.StatusData[i].Status = d.Status; - i++; - } + if (m_GroupsModule != null) + { + foreach (GroupRoleChangesPacket.RoleChangeBlock d in + groupRoleChanges.RoleChange) + { + m_GroupsModule.GroupRoleChanges(this, + groupRoleChanges.AgentData.GroupID, + d.RoleID, + d.MemberID, + d.Change); + } + m_GroupsModule.NotifyChange(groupRoleChanges.AgentData.GroupID); + } + break; - OutPacket(packet, ThrottleOutPacketType.Task); - } + case PacketType.JoinGroupRequest: + JoinGroupRequestPacket joinGroupRequest = + (JoinGroupRequestPacket)Pack; - public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) - { - DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (joinGroupRequest.AgentData.SessionID != SessionId || + joinGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + if (m_GroupsModule != null) + { + m_GroupsModule.JoinGroupRequest(this, + joinGroupRequest.GroupData.GroupID); + } + break; - packet.QueryData = new DirLandReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + case PacketType.LeaveGroupRequest: + LeaveGroupRequestPacket leaveGroupRequest = + (LeaveGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (leaveGroupRequest.AgentData.SessionID != SessionId || + leaveGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.LeaveGroupRequest(this, + leaveGroupRequest.GroupData.GroupID); + } + break; + + case PacketType.EjectGroupMemberRequest: + EjectGroupMemberRequestPacket ejectGroupMemberRequest = + (EjectGroupMemberRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || + ejectGroupMemberRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[ - data.Length]; + if (m_GroupsModule != null) + { + foreach (EjectGroupMemberRequestPacket.EjectDataBlock e + in ejectGroupMemberRequest.EjectData) + { + m_GroupsModule.EjectGroupMemberRequest(this, + ejectGroupMemberRequest.GroupData.GroupID, + e.EjecteeID); + } + } + break; - int i = 0; - foreach (DirLandReplyData d in data) - { - packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].SalePrice = d.salePrice; - packet.QueryReplies[i].ActualArea = d.actualArea; - i++; - } + case PacketType.InviteGroupRequest: + InviteGroupRequestPacket inviteGroupRequest = + (InviteGroupRequestPacket)Pack; - OutPacket(packet, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (inviteGroupRequest.AgentData.SessionID != SessionId || + inviteGroupRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) - { - DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply); + if (m_GroupsModule != null) + { + foreach (InviteGroupRequestPacket.InviteDataBlock b in + inviteGroupRequest.InviteData) + { + m_GroupsModule.InviteGroupRequest(this, + inviteGroupRequest.GroupData.GroupID, + b.InviteeID, + b.RoleID); + } + } + break; - packet.AgentData = new DirPopularReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + #endregion + case PacketType.StartLure: + StartLurePacket startLureRequest = (StartLurePacket)Pack; - packet.QueryData = new DirPopularReplyPacket.QueryDataBlock(); - packet.QueryData.QueryID = queryID; + #region Packet Session and User Check + if (m_checkPackets) + { + if (startLureRequest.AgentData.SessionID != SessionId || + startLureRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[ - data.Length]; + StartLure handlerStartLure = OnStartLure; + if (handlerStartLure != null) + handlerStartLure(startLureRequest.Info.LureType, + Utils.BytesToString( + startLureRequest.Info.Message), + startLureRequest.TargetData[0].TargetID, + this); + break; - int i = 0; - foreach (DirPopularReplyData d in data) - { - packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = - Utils.StringToBytes(d.name); - packet.QueryReplies[i].Dwell = d.dwell; - i++; - } + case PacketType.TeleportLureRequest: + TeleportLureRequestPacket teleportLureRequest = + (TeleportLureRequestPacket)Pack; - OutPacket(packet, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (teleportLureRequest.Info.SessionID != SessionId || + teleportLureRequest.Info.AgentID != AgentId) + break; + } + #endregion - public void SendEventInfoReply(EventData data) - { - EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); + TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest; + if (handlerTeleportLureRequest != null) + handlerTeleportLureRequest( + teleportLureRequest.Info.LureID, + teleportLureRequest.Info.TeleportFlags, + this); + break; - packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); - packet.AgentData.AgentID = AgentId; + case PacketType.ClassifiedInfoRequest: + ClassifiedInfoRequestPacket classifiedInfoRequest = + (ClassifiedInfoRequestPacket)Pack; - packet.EventData = new EventInfoReplyPacket.EventDataBlock(); - packet.EventData.EventID = data.eventID; - packet.EventData.Creator = Utils.StringToBytes(data.creator); - packet.EventData.Name = Utils.StringToBytes(data.name); - packet.EventData.Category = Utils.StringToBytes(data.category); - packet.EventData.Desc = Utils.StringToBytes(data.description); - packet.EventData.Date = Utils.StringToBytes(data.date); - packet.EventData.DateUTC = data.dateUTC; - packet.EventData.Duration = data.duration; - packet.EventData.Cover = data.cover; - packet.EventData.Amount = data.amount; - packet.EventData.SimName = Utils.StringToBytes(data.simName); - packet.EventData.GlobalPos = new Vector3d(data.globalPos); - packet.EventData.EventFlags = data.eventFlags; + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoRequest.AgentData.SessionID != SessionId || + classifiedInfoRequest.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(packet, ThrottleOutPacketType.Task); - } + ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest; + if (handlerClassifiedInfoRequest != null) + handlerClassifiedInfoRequest( + classifiedInfoRequest.Data.ClassifiedID, + this); + break; - public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) - { - MapItemReplyPacket mirplk = new MapItemReplyPacket(); - mirplk.AgentData.AgentID = AgentId; - mirplk.RequestData.ItemType = mapitemtype; - mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; - for (int i = 0; i < replies.Length; i++) - { - MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); - mrdata.X = replies[i].x; - mrdata.Y = replies[i].y; - mrdata.ID = replies[i].id; - mrdata.Extra = replies[i].Extra; - mrdata.Extra2 = replies[i].Extra2; - mrdata.Name = Utils.StringToBytes(replies[i].name); - mirplk.Data[i] = mrdata; - } - //m_log.Debug(mirplk.ToString()); - OutPacket(mirplk, ThrottleOutPacketType.Task); + case PacketType.ClassifiedInfoUpdate: + ClassifiedInfoUpdatePacket classifiedInfoUpdate = + (ClassifiedInfoUpdatePacket)Pack; - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoUpdate.AgentData.SessionID != SessionId || + classifiedInfoUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendOfferCallingCard(UUID srcID, UUID transactionID) - { - // a bit special, as this uses AgentID to store the source instead - // of the destination. The destination (the receiver) goes into destID - OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard); - p.AgentData.AgentID = srcID; - p.AgentData.SessionID = UUID.Zero; - p.AgentBlock.DestID = AgentId; - p.AgentBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); - } + ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; + if (handlerClassifiedInfoUpdate != null) + handlerClassifiedInfoUpdate( + classifiedInfoUpdate.Data.ClassifiedID, + classifiedInfoUpdate.Data.Category, + Utils.BytesToString( + classifiedInfoUpdate.Data.Name), + Utils.BytesToString( + classifiedInfoUpdate.Data.Desc), + classifiedInfoUpdate.Data.ParcelID, + classifiedInfoUpdate.Data.ParentEstate, + classifiedInfoUpdate.Data.SnapshotID, + new Vector3( + classifiedInfoUpdate.Data.PosGlobal), + classifiedInfoUpdate.Data.ClassifiedFlags, + classifiedInfoUpdate.Data.PriceForListing, + this); + break; - public void SendAcceptCallingCard(UUID transactionID) - { - AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1]; - p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock(); - p.FolderData[0].FolderID = UUID.Zero; - OutPacket(p, ThrottleOutPacketType.Task); - } + case PacketType.ClassifiedDelete: + ClassifiedDeletePacket classifiedDelete = + (ClassifiedDeletePacket)Pack; - public void SendDeclineCallingCard(UUID transactionID) - { - DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = UUID.Zero; - p.TransactionBlock.TransactionID = transactionID; - OutPacket(p, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedDelete.AgentData.SessionID != SessionId || + classifiedDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendTerminateFriend(UUID exFriendID) - { - TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship); - p.AgentData.AgentID = AgentId; - p.AgentData.SessionID = SessionId; - p.ExBlock.OtherID = exFriendID; - OutPacket(p, ThrottleOutPacketType.Task); - } + ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete; + if (handlerClassifiedDelete != null) + handlerClassifiedDelete( + classifiedDelete.Data.ClassifiedID, + this); + break; - public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) - { - AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); + case PacketType.ClassifiedGodDelete: + ClassifiedGodDeletePacket classifiedGodDelete = + (ClassifiedGodDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedGodDelete.AgentData.SessionID != SessionId || + classifiedGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; - p.AgentData.AvatarID = avatarID; + ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; + if (handlerClassifiedGodDelete != null) + handlerClassifiedGodDelete( + classifiedGodDelete.Data.ClassifiedID, + this); + break; - p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; - int i = 0; - foreach (GroupMembershipData m in data) - { - p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); - p.GroupData[i].GroupPowers = m.GroupPowers; - p.GroupData[i].AcceptNotices = m.AcceptNotices; - p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); - p.GroupData[i].GroupID = m.GroupID; - p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); - p.GroupData[i].GroupInsigniaID = m.GroupPicture; - i++; - } + case PacketType.EventGodDelete: + EventGodDeletePacket eventGodDelete = + (EventGodDeletePacket)Pack; - p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); - p.NewGroupData.ListInProfile = true; + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventGodDelete.AgentData.SessionID != SessionId || + eventGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(p, ThrottleOutPacketType.Task); - } + EventGodDelete handlerEventGodDelete = OnEventGodDelete; + if (handlerEventGodDelete != null) + handlerEventGodDelete( + eventGodDelete.EventData.EventID, + eventGodDelete.QueryData.QueryID, + Utils.BytesToString( + eventGodDelete.QueryData.QueryText), + eventGodDelete.QueryData.QueryFlags, + eventGodDelete.QueryData.QueryStart, + this); + break; - public void SendJoinGroupReply(UUID groupID, bool success) - { - JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); + case PacketType.EventNotificationAddRequest: + EventNotificationAddRequestPacket eventNotificationAdd = + (EventNotificationAddRequestPacket)Pack; - p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationAdd.AgentData.SessionID != SessionId || + eventNotificationAdd.AgentData.AgentID != AgentId) + break; + } + #endregion - p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest; + if (handlerEventNotificationAddRequest != null) + handlerEventNotificationAddRequest( + eventNotificationAdd.EventData.EventID, this); + break; - OutPacket(p, ThrottleOutPacketType.Task); - } + case PacketType.EventNotificationRemoveRequest: + EventNotificationRemoveRequestPacket eventNotificationRemove = + (EventNotificationRemoveRequestPacket)Pack; - public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) - { - EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationRemove.AgentData.SessionID != SessionId || + eventNotificationRemove.AgentData.AgentID != AgentId) + break; + } + #endregion - p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = agentID; + EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; + if (handlerEventNotificationRemoveRequest != null) + handlerEventNotificationRemoveRequest( + eventNotificationRemove.EventData.EventID, this); + break; - p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; + case PacketType.RetrieveInstantMessages: + RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; - p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); - p.EjectData.Success = success; + #region Packet Session and User Check + if (m_checkPackets) + { + if (rimpInstantMessagePack.AgentData.SessionID != SessionId || + rimpInstantMessagePack.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(p, ThrottleOutPacketType.Task); - } + RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages; + if (handlerRetrieveInstantMessages != null) + handlerRetrieveInstantMessages(this); + break; - public void SendLeaveGroupReply(UUID groupID, bool success) - { - LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); + case PacketType.PickDelete: + PickDeletePacket pickDelete = + (PickDeletePacket)Pack; - p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); - p.AgentData.AgentID = AgentId; + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickDelete.AgentData.SessionID != SessionId || + pickDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); - p.GroupData.GroupID = groupID; - p.GroupData.Success = success; + PickDelete handlerPickDelete = OnPickDelete; + if (handlerPickDelete != null) + handlerPickDelete(this, pickDelete.Data.PickID); + break; + case PacketType.PickGodDelete: + PickGodDeletePacket pickGodDelete = + (PickGodDeletePacket)Pack; - OutPacket(p, ThrottleOutPacketType.Task); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickGodDelete.AgentData.SessionID != SessionId || + pickGodDelete.AgentData.AgentID != AgentId) + break; + } + #endregion - public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) - { - if (classifiedID.Length != name.Length) - return; + PickGodDelete handlerPickGodDelete = OnPickGodDelete; + if (handlerPickGodDelete != null) + handlerPickGodDelete(this, + pickGodDelete.AgentData.AgentID, + pickGodDelete.Data.PickID, + pickGodDelete.Data.QueryID); + break; + case PacketType.PickInfoUpdate: + PickInfoUpdatePacket pickInfoUpdate = + (PickInfoUpdatePacket)Pack; - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickInfoUpdate.AgentData.SessionID != SessionId || + pickInfoUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; + PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate; + if (handlerPickInfoUpdate != null) + handlerPickInfoUpdate(this, + pickInfoUpdate.Data.PickID, + pickInfoUpdate.Data.CreatorID, + pickInfoUpdate.Data.TopPick, + Utils.BytesToString(pickInfoUpdate.Data.Name), + Utils.BytesToString(pickInfoUpdate.Data.Desc), + pickInfoUpdate.Data.SnapshotID, + pickInfoUpdate.Data.SortOrder, + pickInfoUpdate.Data.Enabled); + break; + case PacketType.AvatarNotesUpdate: + AvatarNotesUpdatePacket avatarNotesUpdate = + (AvatarNotesUpdatePacket)Pack; - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length]; - int i; - for (i = 0 ; i < classifiedID.Length ; i++) - { - ac.Data[i].ClassifiedID = classifiedID[i]; - ac.Data[i].Name = Utils.StringToBytes(name[i]); - } + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarNotesUpdate.AgentData.SessionID != SessionId || + avatarNotesUpdate.AgentData.AgentID != AgentId) + break; + } + #endregion - OutPacket(ac, ThrottleOutPacketType.Task); - } + AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate; + if (handlerAvatarNotesUpdate != null) + handlerAvatarNotesUpdate(this, + avatarNotesUpdate.Data.TargetID, + Utils.BytesToString(avatarNotesUpdate.Data.Notes)); + break; - public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) - { - ClassifiedInfoReplyPacket cr = - (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ClassifiedInfoReply); +// case PacketType.AvatarInterestsUpdate: +// AvatarInterestsUpdatePacket avatarInterestUpdate = +// (AvatarInterestsUpdatePacket)Pack; +// +// break; - cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); - cr.AgentData.AgentID = AgentId; + case PacketType.PlacesQuery: + PlacesQueryPacket placesQueryPacket = + (PlacesQueryPacket)Pack; - cr.Data = new ClassifiedInfoReplyPacket.DataBlock(); - cr.Data.ClassifiedID = classifiedID; - cr.Data.CreatorID = creatorID; - cr.Data.CreationDate = creationDate; - cr.Data.ExpirationDate = expirationDate; - cr.Data.Category = category; - cr.Data.Name = Utils.StringToBytes(name); - cr.Data.Desc = Utils.StringToBytes(description); - cr.Data.ParcelID = parcelID; - cr.Data.ParentEstate = parentEstate; - cr.Data.SnapshotID = snapshotID; - cr.Data.SimName = Utils.StringToBytes(simName); - cr.Data.PosGlobal = new Vector3d(globalPos); - cr.Data.ParcelName = Utils.StringToBytes(parcelName); - cr.Data.ClassifiedFlags = classifiedFlags; - cr.Data.PriceForListing = price; + PlacesQuery handlerPlacesQuery = OnPlacesQuery; - OutPacket(cr, ThrottleOutPacketType.Task); - } + if (handlerPlacesQuery != null) + handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, + placesQueryPacket.TransactionData.TransactionID, + Utils.BytesToString( + placesQueryPacket.QueryData.QueryText), + placesQueryPacket.QueryData.QueryFlags, + (byte)placesQueryPacket.QueryData.Category, + Utils.BytesToString( + placesQueryPacket.QueryData.SimName), + this); + break; + default: + m_log.Warn("[CLIENT]: unhandled packet " + Pack); + break; - public void SendAgentDropGroup(UUID groupID) - { - AgentDropGroupPacket dg = - (AgentDropGroupPacket)PacketPool.Instance.GetPacket( - PacketType.AgentDropGroup); + #endregion + } - dg.AgentData = new AgentDropGroupPacket.AgentDataBlock(); - dg.AgentData.AgentID = AgentId; - dg.AgentData.GroupID = groupID; + PacketPool.Instance.ReturnPacket(Pack); - OutPacket(dg, ThrottleOutPacketType.Task); } - public void SendAvatarNotesReply(UUID targetID, string text) + private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) { - AvatarNotesReplyPacket an = - (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarNotesReply); + PrimitiveBaseShape shape = new PrimitiveBaseShape(); - an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock(); - an.AgentData.AgentID = AgentId; + shape.PCode = addPacket.ObjectData.PCode; + shape.State = addPacket.ObjectData.State; + shape.PathBegin = addPacket.ObjectData.PathBegin; + shape.PathEnd = addPacket.ObjectData.PathEnd; + shape.PathScaleX = addPacket.ObjectData.PathScaleX; + shape.PathScaleY = addPacket.ObjectData.PathScaleY; + shape.PathShearX = addPacket.ObjectData.PathShearX; + shape.PathShearY = addPacket.ObjectData.PathShearY; + shape.PathSkew = addPacket.ObjectData.PathSkew; + shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; + shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; + shape.Scale = addPacket.ObjectData.Scale; + shape.PathCurve = addPacket.ObjectData.PathCurve; + shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; + shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; + shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; + shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; + shape.PathTaperX = addPacket.ObjectData.PathTaperX; + shape.PathTaperY = addPacket.ObjectData.PathTaperY; + shape.PathTwist = addPacket.ObjectData.PathTwist; + shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; + Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); + shape.TextureEntry = ntex.GetBytes(); + //shape.Textures = ntex; + return shape; + } + + public ClientInfo GetClientInfo() + { + ClientInfo info = m_udpClient.GetClientInfo(); - an.Data = new AvatarNotesReplyPacket.DataBlock(); - an.Data.TargetID = targetID; - an.Data.Notes = Utils.StringToBytes(text); + info.userEP = m_userEndPoint; + info.proxyEP = null; + info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); - OutPacket(an, ThrottleOutPacketType.Task); + return info; } - public void SendAvatarPicksReply(UUID targetID, Dictionary picks) + public void SetClientInfo(ClientInfo info) { - AvatarPicksReplyPacket ap = - (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarPicksReply); + m_udpClient.SetClientInfo(info); + } - ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock(); - ap.AgentData.AgentID = AgentId; - ap.AgentData.TargetID = targetID; + public EndPoint GetClientEP() + { + return m_userEndPoint; + } - ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count]; + #region Media Parcel Members - int i = 0; - foreach (KeyValuePair pick in picks) - { - ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); - ap.Data[i].PickID = pick.Key; - ap.Data[i].PickName = Utils.StringToBytes(pick.Value); - i++; - } + public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) + { + ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); + commandMessagePacket.CommandBlock.Flags = flags; + commandMessagePacket.CommandBlock.Command =(uint) command; + commandMessagePacket.CommandBlock.Time = time; - OutPacket(ap, ThrottleOutPacketType.Task); + OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); } - public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, + byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, + byte mediaLoop) { - AvatarClassifiedReplyPacket ac = - (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket( - PacketType.AvatarClassifiedReply); - - ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock(); - ac.AgentData.AgentID = AgentId; - ac.AgentData.TargetID = targetID; - - ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count]; + ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); + updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); + updatePacket.DataBlock.MediaID = mediaTextureID; + updatePacket.DataBlock.MediaAutoScale = autoScale; - int i = 0; - foreach (KeyValuePair classified in classifieds) - { - ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock(); - ac.Data[i].ClassifiedID = classified.Key; - ac.Data[i].Name = Utils.StringToBytes(classified.Value); - i++; - } + updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); + updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); + updatePacket.DataBlockExtended.MediaWidth = mediaWidth; + updatePacket.DataBlockExtended.MediaHeight = mediaHeight; + updatePacket.DataBlockExtended.MediaLoop = mediaLoop; - OutPacket(ac, ThrottleOutPacketType.Task); + OutPacket(updatePacket, ThrottleOutPacketType.Unknown); } - public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) - { - ParcelDwellReplyPacket pd = - (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket( - PacketType.ParcelDwellReply); + #endregion - pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock(); - pd.AgentData.AgentID = AgentId; + #region Camera - pd.Data = new ParcelDwellReplyPacket.DataBlock(); - pd.Data.LocalID = localID; - pd.Data.ParcelID = parcelID; - pd.Data.Dwell = dwell; + public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) + { + SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count]; + uint idx = 0; + foreach (KeyValuePair pair in parameters) + { + SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock(); + block.Type = pair.Key; + block.Value = pair.Value; - OutPacket(pd, ThrottleOutPacketType.Land); + camPropBlock[idx++] = block; + } + packet.CameraProperty = camPropBlock; + OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendUserInfoReply(bool imViaEmail, bool visible, string email) + public void SendClearFollowCamProperties (UUID objectID) { - UserInfoReplyPacket ur = - (UserInfoReplyPacket)PacketPool.Instance.GetPacket( - PacketType.UserInfoReply); - - string Visible = "hidden"; - if (visible) - Visible = "default"; + ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + OutPacket(packet, ThrottleOutPacketType.Task); + } - ur.AgentData = new UserInfoReplyPacket.AgentDataBlock(); - ur.AgentData.AgentID = AgentId; + #endregion - ur.UserData = new UserInfoReplyPacket.UserDataBlock(); - ur.UserData.IMViaEMail = imViaEmail; - ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible); - ur.UserData.EMail = Utils.StringToBytes(email); + public void SetClientOption(string option, string value) + { + switch (option) + { + default: + break; + } + } - OutPacket(ur, ThrottleOutPacketType.Task); + public string GetClientOption(string option) + { + switch (option) + { + default: + break; + } + return string.Empty; } public void KillEndDone() { - KillPacket kp = new KillPacket(); - OutPacket(kp, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); + m_udpClient.Shutdown(); } #region IClientCore @@ -10767,13 +10273,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - protected virtual void RegisterInterfaces() - { - RegisterInterface(this); - RegisterInterface(this); - RegisterInterface(this); - } - public bool TryGet(out T iface) { if (m_clientInterfaces.ContainsKey(typeof(T))) @@ -10821,78 +10320,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void SendCreateGroupReply(UUID groupID, bool success, string message) - { - CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply); - - createGroupReply.AgentData = - new CreateGroupReplyPacket.AgentDataBlock(); - createGroupReply.ReplyData = - new CreateGroupReplyPacket.ReplyDataBlock(); - - createGroupReply.AgentData.AgentID = AgentId; - createGroupReply.ReplyData.GroupID = groupID; - - createGroupReply.ReplyData.Success = success; - createGroupReply.ReplyData.Message = Utils.StringToBytes(message); - OutPacket(createGroupReply, ThrottleOutPacketType.Task); - } - - public void SendUseCachedMuteList() - { - UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList); - - useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock(); - useCachedMuteList.AgentData.AgentID = AgentId; - - OutPacket(useCachedMuteList, ThrottleOutPacketType.Task); - } - - public void SendMuteListUpdate(string filename) - { - MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate); - - muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock(); - muteListUpdate.MuteData.AgentID = AgentId; - muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename); - - OutPacket(muteListUpdate, ThrottleOutPacketType.Task); - } - - public void SendPickInfoReply(UUID pickID,UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) - { - PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply); - - pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock(); - pickInfoReply.AgentData.AgentID = AgentId; - - pickInfoReply.Data = new PickInfoReplyPacket.DataBlock(); - pickInfoReply.Data.PickID = pickID; - pickInfoReply.Data.CreatorID = creatorID; - pickInfoReply.Data.TopPick = topPick; - pickInfoReply.Data.ParcelID = parcelID; - pickInfoReply.Data.Name = Utils.StringToBytes(name); - pickInfoReply.Data.Desc = Utils.StringToBytes(desc); - pickInfoReply.Data.SnapshotID = snapshotID; - pickInfoReply.Data.User = Utils.StringToBytes(user); - pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName); - pickInfoReply.Data.SimName = Utils.StringToBytes(simName); - pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal); - pickInfoReply.Data.SortOrder = sortOrder; - pickInfoReply.Data.Enabled = enabled; - - OutPacket(pickInfoReply, ThrottleOutPacketType.Task); - } - public string Report() { - LLPacketHandler handler = (LLPacketHandler) m_PacketHandler; - return handler.PacketQueue.GetStats(); + return m_udpClient.GetStats(); } public string XReport(string uptime, string version) { - return ""; + return String.Empty; } public void MakeAssetRequest(TransferRequestPacket transferRequest) @@ -10981,7 +10416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return numPackets; } - #region IClientIPEndpoint Members public IPAddress EndPoint -- cgit v1.1 From 8c255b374a73d03be922cef32b06b7b83d5e09bb Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 21:32:15 -0700 Subject: Uncommented log message on CAPs FetchInventoryDescendants --- OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index e561efb..f6d8eac 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -477,9 +477,9 @@ namespace OpenSim.Region.Framework.Scenes public InventoryCollection HandleFetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder, out int version) { -// m_log.DebugFormat( -// "[INVENTORY CACHE]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", -// fetchFolders, fetchItems, folderID, agentID); + m_log.DebugFormat( + "[INVENTORY CACHE]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", + fetchFolders, fetchItems, folderID, agentID); // FIXME MAYBE: We're not handling sortOrder! -- cgit v1.1 From d344ca932df5ca75f4739c693627bb1a24d9bbdf Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 6 Oct 2009 22:19:20 -0700 Subject: A small change in FetchInventoryDescendantsCAPS. --- OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index f6d8eac..4ae4dc3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -497,10 +497,11 @@ namespace OpenSim.Region.Framework.Scenes return ret; } - InventoryCollection contents = InventoryService.GetFolderContent(agentID, folderID); + InventoryCollection contents = new InventoryCollection(); if (folderID != UUID.Zero) { + contents = InventoryService.GetFolderContent(agentID, folderID); InventoryFolderBase containingFolder = new InventoryFolderBase(); containingFolder.ID = folderID; containingFolder.Owner = agentID; -- cgit v1.1 From c71b3e730d8027b31eb3300c747d011a6e38030e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 7 Oct 2009 18:54:08 -0700 Subject: Changed the locking mechanism, because the existing one is causing deadlocks to occur. --- .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 125 ++++++++++++++++----- 1 file changed, 100 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs index 7d2da68..9be9480 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs @@ -41,6 +41,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Dictionary Dictionary2; LLUDPClient[] Array; ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl(); + object m_sync = new object(); public UDPClientCollection() { @@ -58,9 +59,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) { - rwLock.EnterWriteLock(); + //rwLock.EnterWriteLock(); - try + //try + //{ + // if (Dictionary1.ContainsKey(key1)) + // { + // if (!Dictionary2.ContainsKey(key2)) + // throw new ArgumentException("key1 exists in the dictionary but not key2"); + // } + // else if (Dictionary2.ContainsKey(key2)) + // { + // if (!Dictionary1.ContainsKey(key1)) + // throw new ArgumentException("key2 exists in the dictionary but not key1"); + // } + + // Dictionary1[key1] = value; + // Dictionary2[key2] = value; + + // LLUDPClient[] oldArray = Array; + // int oldLength = oldArray.Length; + + // LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; + // for (int i = 0; i < oldLength; i++) + // newArray[i] = oldArray[i]; + // newArray[oldLength] = value; + + // Array = newArray; + //} + //finally { rwLock.ExitWriteLock(); } + + lock (m_sync) { if (Dictionary1.ContainsKey(key1)) { @@ -86,14 +115,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP Array = newArray; } - finally { rwLock.ExitWriteLock(); } + } public bool Remove(UUID key1, IPEndPoint key2) { - rwLock.EnterWriteLock(); + //rwLock.EnterWriteLock(); + + //try + //{ + // LLUDPClient value; + // if (Dictionary1.TryGetValue(key1, out value)) + // { + // Dictionary1.Remove(key1); + // Dictionary2.Remove(key2); + + // LLUDPClient[] oldArray = Array; + // int oldLength = oldArray.Length; + + // LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; + // int j = 0; + // for (int i = 0; i < oldLength; i++) + // { + // if (oldArray[i] != value) + // newArray[j++] = oldArray[i]; + // } + + // Array = newArray; + // return true; + // } + //} + //finally { rwLock.ExitWriteLock(); } - try + //return false; + + lock (m_sync) { LLUDPClient value; if (Dictionary1.TryGetValue(key1, out value)) @@ -116,22 +172,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } } - finally { rwLock.ExitWriteLock(); } return false; + } public void Clear() { - rwLock.EnterWriteLock(); + //rwLock.EnterWriteLock(); + + //try + //{ + // Dictionary1.Clear(); + // Dictionary2.Clear(); + // Array = new LLUDPClient[0]; + //} + //finally { rwLock.ExitWriteLock(); } - try + lock (m_sync) { Dictionary1.Clear(); Dictionary2.Clear(); Array = new LLUDPClient[0]; } - finally { rwLock.ExitWriteLock(); } + } public int Count @@ -151,35 +215,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP public bool TryGetValue(UUID key, out LLUDPClient value) { - bool success; - bool doLock = !rwLock.IsUpgradeableReadLockHeld; - if (doLock) rwLock.EnterReadLock(); + //bool success; + //bool doLock = !rwLock.IsUpgradeableReadLockHeld; + //if (doLock) rwLock.EnterReadLock(); + + //try { success = Dictionary1.TryGetValue(key, out value); } + //finally { if (doLock) rwLock.ExitReadLock(); } - try { success = Dictionary1.TryGetValue(key, out value); } - finally { if (doLock) rwLock.ExitReadLock(); } + //return success; + + lock (m_sync) + return Dictionary1.TryGetValue(key, out value); - return success; } public bool TryGetValue(IPEndPoint key, out LLUDPClient value) { - bool success; - bool doLock = !rwLock.IsUpgradeableReadLockHeld; - if (doLock) rwLock.EnterReadLock(); + //bool success; + //bool doLock = !rwLock.IsUpgradeableReadLockHeld; + //if (doLock) rwLock.EnterReadLock(); + + //try { success = Dictionary2.TryGetValue(key, out value); } + //finally { if (doLock) rwLock.ExitReadLock(); } - try { success = Dictionary2.TryGetValue(key, out value); } - finally { if (doLock) rwLock.ExitReadLock(); } + //return success; - return success; + lock (m_sync) + return Dictionary2.TryGetValue(key, out value); } public void ForEach(Action action) { - bool doLock = !rwLock.IsUpgradeableReadLockHeld; - if (doLock) rwLock.EnterUpgradeableReadLock(); + //bool doLock = !rwLock.IsUpgradeableReadLockHeld; + //if (doLock) rwLock.EnterUpgradeableReadLock(); + + //try { Parallel.ForEach(Array, action); } + //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } + + lock (m_sync) + Parallel.ForEach(Array, action); - try { Parallel.ForEach(Array, action); } - finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } } } } -- cgit v1.1 From dd80380df5e47c0d67466f7d509898a71e19abd0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 7 Oct 2009 19:45:57 -0700 Subject: Another go at the deadlock: not locking TryGetValue, and just catch/ignore exceptions. --- .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 46 +++++++++++++++------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs index 9be9480..36e1f49 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs @@ -215,33 +215,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP public bool TryGetValue(UUID key, out LLUDPClient value) { - //bool success; - //bool doLock = !rwLock.IsUpgradeableReadLockHeld; - //if (doLock) rwLock.EnterReadLock(); + ////bool success; + ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; + ////if (doLock) rwLock.EnterReadLock(); - //try { success = Dictionary1.TryGetValue(key, out value); } - //finally { if (doLock) rwLock.ExitReadLock(); } + ////try { success = Dictionary1.TryGetValue(key, out value); } + ////finally { if (doLock) rwLock.ExitReadLock(); } - //return success; + ////return success; - lock (m_sync) - return Dictionary1.TryGetValue(key, out value); + //lock (m_sync) + // return Dictionary1.TryGetValue(key, out value); + try + { + return Dictionary1.TryGetValue(key, out value); + } + catch { } + value = null; + return false; } public bool TryGetValue(IPEndPoint key, out LLUDPClient value) { - //bool success; - //bool doLock = !rwLock.IsUpgradeableReadLockHeld; - //if (doLock) rwLock.EnterReadLock(); + ////bool success; + ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; + ////if (doLock) rwLock.EnterReadLock(); - //try { success = Dictionary2.TryGetValue(key, out value); } - //finally { if (doLock) rwLock.ExitReadLock(); } + ////try { success = Dictionary2.TryGetValue(key, out value); } + ////finally { if (doLock) rwLock.ExitReadLock(); } - //return success; + ////return success; - lock (m_sync) + //lock (m_sync) + // return Dictionary2.TryGetValue(key, out value); + + try + { return Dictionary2.TryGetValue(key, out value); + } + catch { } + value = null; + return false; + } public void ForEach(Action action) -- cgit v1.1 From 68961ec0923fb613eae72f0f83ad3349e608cc05 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 7 Oct 2009 20:36:24 -0700 Subject: One last attempt at tunning the locking/no locking behaviour. The previous one was too lax and made the important login packets fail. --- .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs index 36e1f49..f6ccf01 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs @@ -247,16 +247,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP ////return success; - //lock (m_sync) - // return Dictionary2.TryGetValue(key, out value); - - try - { + lock (m_sync) return Dictionary2.TryGetValue(key, out value); - } - catch { } - value = null; - return false; + + //try + //{ + // return Dictionary2.TryGetValue(key, out value); + //} + //catch { } + //value = null; + //return false; } @@ -268,8 +268,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP //try { Parallel.ForEach(Array, action); } //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } + LLUDPClient[] localArray = null; lock (m_sync) - Parallel.ForEach(Array, action); + { + localArray = new LLUDPClient[Array.Length]; + Array.CopyTo(localArray, 0); + } + + Parallel.ForEach(localArray, action); } } -- cgit v1.1