/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
C# | 11145 lines | 8985 code | 1493 blank | 667 comment | 1574 complexity | 89d15798e98f9f7dccfa0f171faba23d MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- * 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;
- using System.Collections.Generic;
- using System.Net;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using System.Timers;
- using System.Xml;
- using log4net;
- using OpenMetaverse;
- using OpenMetaverse.Packets;
- using OpenMetaverse.Messages.Linden;
- using OpenMetaverse.StructuredData;
- using OpenSim.Framework;
- using OpenSim.Framework.Client;
- using OpenSim.Framework.Statistics;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes;
- using OpenSim.Services.Interfaces;
- using Timer = System.Timers.Timer;
- using AssetLandmark = OpenSim.Framework.AssetLandmark;
- using Nini.Config;
- namespace OpenSim.Region.ClientStack.LindenUDP
- {
- public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
- /// <summary>
- /// Handles new client connections
- /// Constructor takes a single Packet and authenticates everything
- /// </summary>
- public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
- {
- /// <value>
- /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details.
- /// </value>
- protected int m_debugPacketLevel = 0;
- #region Events
- public event GenericMessage OnGenericMessage;
- public event BinaryGenericMessage OnBinaryGenericMessage;
- public event Action<IClientAPI> OnLogout;
- public event ObjectPermissions OnObjectPermissions;
- public event Action<IClientAPI> OnConnectionClosed;
- public event ViewerEffectEventHandler OnViewerEffect;
- public event ImprovedInstantMessage OnInstantMessage;
- public event ChatMessage OnChatFromClient;
- public event TextureRequest OnRequestTexture;
- public event RezObject OnRezObject;
- public event DeRezObject OnDeRezObject;
- public event ModifyTerrain OnModifyTerrain;
- public event Action<IClientAPI> OnRegionHandShakeReply;
- public event GenericCall1 OnRequestWearables;
- public event SetAppearance OnSetAppearance;
- public event AvatarNowWearing OnAvatarNowWearing;
- public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
- public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv;
- public event UUIDNameRequest OnDetachAttachmentIntoInv;
- public event ObjectAttach OnObjectAttach;
- public event ObjectDeselect OnObjectDetach;
- public event ObjectDrop OnObjectDrop;
- public event GenericCall1 OnCompleteMovementToRegion;
- public event UpdateAgent OnPreAgentUpdate;
- public event UpdateAgent OnAgentUpdate;
- public event AgentRequestSit OnAgentRequestSit;
- public event AgentSit OnAgentSit;
- public event AvatarPickerRequest OnAvatarPickerRequest;
- public event StartAnim OnStartAnim;
- public event StopAnim OnStopAnim;
- public event Action<IClientAPI> OnRequestAvatarsData;
- public event LinkObjects OnLinkObjects;
- public event DelinkObjects OnDelinkObjects;
- public event GrabObject OnGrabObject;
- public event DeGrabObject OnDeGrabObject;
- public event SpinStart OnSpinStart;
- public event SpinStop OnSpinStop;
- public event ObjectDuplicate OnObjectDuplicate;
- public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
- public event MoveObject OnGrabUpdate;
- public event SpinObject OnSpinUpdate;
- public event AddNewPrim OnAddPrim;
- public event RequestGodlikePowers OnRequestGodlikePowers;
- public event GodKickUser OnGodKickUser;
- public event ObjectExtraParams OnUpdateExtraParams;
- public event UpdateShape OnUpdatePrimShape;
- public event ObjectRequest OnObjectRequest;
- public event ObjectSelect OnObjectSelect;
- public event ObjectDeselect OnObjectDeselect;
- public event GenericCall7 OnObjectDescription;
- public event GenericCall7 OnObjectName;
- public event GenericCall7 OnObjectClickAction;
- public event GenericCall7 OnObjectMaterial;
- public event ObjectIncludeInSearch OnObjectIncludeInSearch;
- public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
- public event UpdatePrimFlags OnUpdatePrimFlags;
- public event UpdatePrimTexture OnUpdatePrimTexture;
- public event UpdateVector OnUpdatePrimGroupPosition;
- public event UpdateVector OnUpdatePrimSinglePosition;
- public event UpdatePrimRotation OnUpdatePrimGroupRotation;
- public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
- public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
- public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
- public event UpdateVector OnUpdatePrimScale;
- public event UpdateVector OnUpdatePrimGroupScale;
- public event StatusChange OnChildAgentStatus;
- public event GenericCall2 OnStopMovement;
- public event Action<UUID> OnRemoveAvatar;
- public event RequestMapBlocks OnRequestMapBlocks;
- public event RequestMapName OnMapNameRequest;
- public event TeleportLocationRequest OnTeleportLocationRequest;
- public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
- public event DisconnectUser OnDisconnectUser;
- public event RequestAvatarProperties OnRequestAvatarProperties;
- public event SetAlwaysRun OnSetAlwaysRun;
- public event FetchInventory OnAgentDataUpdateRequest;
- public event TeleportLocationRequest OnSetStartLocationRequest;
- public event UpdateAvatarProperties OnUpdateAvatarProperties;
- public event CreateNewInventoryItem OnCreateNewInventoryItem;
- public event LinkInventoryItem OnLinkInventoryItem;
- public event CreateInventoryFolder OnCreateNewInventoryFolder;
- public event UpdateInventoryFolder OnUpdateInventoryFolder;
- public event MoveInventoryFolder OnMoveInventoryFolder;
- public event FetchInventoryDescendents OnFetchInventoryDescendents;
- public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
- public event FetchInventory OnFetchInventory;
- public event RequestTaskInventory OnRequestTaskInventory;
- public event UpdateInventoryItem OnUpdateInventoryItem;
- public event CopyInventoryItem OnCopyInventoryItem;
- public event MoveInventoryItem OnMoveInventoryItem;
- public event RemoveInventoryItem OnRemoveInventoryItem;
- public event RemoveInventoryFolder OnRemoveInventoryFolder;
- public event UDPAssetUploadRequest OnAssetUploadRequest;
- public event XferReceive OnXferReceive;
- public event RequestXfer OnRequestXfer;
- public event ConfirmXfer OnConfirmXfer;
- public event AbortXfer OnAbortXfer;
- public event RequestTerrain OnRequestTerrain;
- public event RezScript OnRezScript;
- public event UpdateTaskInventory OnUpdateTaskInventory;
- public event MoveTaskInventory OnMoveTaskItem;
- public event RemoveTaskInventory OnRemoveTaskItem;
- public event RequestAsset OnRequestAsset;
- public event UUIDNameRequest OnNameFromUUIDRequest;
- public event ParcelAccessListRequest OnParcelAccessListRequest;
- public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
- public event ParcelPropertiesRequest OnParcelPropertiesRequest;
- public event ParcelDivideRequest OnParcelDivideRequest;
- public event ParcelJoinRequest OnParcelJoinRequest;
- public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
- public event ParcelSelectObjects OnParcelSelectObjects;
- public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
- public event ParcelAbandonRequest OnParcelAbandonRequest;
- public event ParcelGodForceOwner OnParcelGodForceOwner;
- public event ParcelReclaim OnParcelReclaim;
- public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
- public event ParcelDeedToGroup OnParcelDeedToGroup;
- public event RegionInfoRequest OnRegionInfoRequest;
- public event EstateCovenantRequest OnEstateCovenantRequest;
- public event FriendActionDelegate OnApproveFriendRequest;
- public event FriendActionDelegate OnDenyFriendRequest;
- public event FriendshipTermination OnTerminateFriendship;
- public event GrantUserFriendRights OnGrantUserRights;
- public event MoneyTransferRequest OnMoneyTransferRequest;
- public event EconomyDataRequest OnEconomyDataRequest;
- public event MoneyBalanceRequest OnMoneyBalanceRequest;
- public event ParcelBuy OnParcelBuy;
- public event UUIDNameRequest OnTeleportHomeRequest;
- public event UUIDNameRequest OnUUIDGroupNameRequest;
- public event ScriptAnswer OnScriptAnswer;
- public event RequestPayPrice OnRequestPayPrice;
- public event ObjectSaleInfo OnObjectSaleInfo;
- public event ObjectBuy OnObjectBuy;
- public event BuyObjectInventory OnBuyObjectInventory;
- public event AgentSit OnUndo;
- public event AgentSit OnRedo;
- public event LandUndo OnLandUndo;
- public event ForceReleaseControls OnForceReleaseControls;
- public event GodLandStatRequest OnLandStatRequest;
- public event RequestObjectPropertiesFamily OnObjectGroupRequest;
- public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
- public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
- public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
- public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
- public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
- public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
- public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
- public event BakeTerrain OnBakeTerrain;
- public event RequestTerrain OnUploadTerrain;
- public event EstateChangeInfo OnEstateChangeInfo;
- public event EstateRestartSimRequest OnEstateRestartSimRequest;
- public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
- public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
- public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
- public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
- public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
- public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
- public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
- public event RegionHandleRequest OnRegionHandleRequest;
- public event ParcelInfoRequest OnParcelInfoRequest;
- public event ScriptReset OnScriptReset;
- 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;
- public event DirPopularQuery OnDirPopularQuery;
- 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;
- public event AgentFOV OnAgentFOV;
- public event FindAgentUpdate OnFindAgent;
- public event TrackAgentUpdate OnTrackAgent;
- public event NewUserReport OnUserReport;
- public event SaveStateHandler OnSaveState;
- public event GroupAccountSummaryRequest OnGroupAccountSummaryRequest;
- public event GroupAccountDetailsRequest OnGroupAccountDetailsRequest;
- public event GroupAccountTransactionsRequest OnGroupAccountTransactionsRequest;
- public event FreezeUserUpdate OnParcelFreezeUser;
- public event EjectUserUpdate OnParcelEjectUser;
- public event ParcelBuyPass OnParcelBuyPass;
- public event ParcelGodMark OnParcelGodMark;
- public event GroupActiveProposalsRequest OnGroupActiveProposalsRequest;
- public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
- public event SimWideDeletesDelegate OnSimWideDeletes;
- public event SendPostcard OnSendPostcard;
- public event MuteListEntryUpdate OnUpdateMuteListEntry;
- public event MuteListEntryRemove OnRemoveMuteListEntry;
- public event GodlikeMessage onGodlikeMessage;
- public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
- #endregion Events
- #region Class Members
- // LLClientView Only
- public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
- /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
- private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
- private readonly LLUDPServer m_udpServer;
- private readonly LLUDPClient m_udpClient;
- private readonly UUID m_sessionId;
- private readonly UUID m_secureSessionId;
- protected readonly UUID m_agentId;
- private readonly uint m_circuitCode;
- private readonly byte[] m_channelVersion = Utils.EmptyBytes;
- private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
- private readonly IGroupsModule m_GroupsModule;
- private int m_cachedTextureSerial;
- private PriorityQueue m_entityUpdates;
- private Prioritizer m_prioritizer;
- private bool m_disableFacelights = false;
- /// <value>
- /// List used in construction of data blocks for an object update packet. This is to stop us having to
- /// continually recreate it.
- /// </value>
- protected List<ObjectUpdatePacket.ObjectDataBlock> m_fullUpdateDataBlocksBuilder;
- /// <value>
- /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the
- /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
- /// ownerless phantom.
- ///
- /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
- ///
- /// </value>
- protected HashSet<uint> m_killRecord;
- // protected HashSet<uint> m_attachmentsSent;
- private int m_moneyBalance;
- private int m_animationSequenceNumber = 1;
- private bool m_SendLogoutPacketWhenClosing = true;
- private AgentUpdateArgs lastarg;
- private bool m_IsActive = true;
- private bool m_IsLoggingOut = false;
- protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
- protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
- protected Scene m_scene;
- protected LLImageManager m_imageManager;
- protected string m_firstName;
- protected string m_lastName;
- protected Thread m_clientThread;
- protected Vector3 m_startpos;
- protected EndPoint m_userEndPoint;
- protected UUID m_activeGroupID;
- protected string m_activeGroupName = String.Empty;
- protected ulong m_activeGroupPowers;
- protected Dictionary<UUID, ulong> m_groupPowers = new Dictionary<UUID, ulong>();
- protected int m_terrainCheckerCount;
- protected uint m_agentFOVCounter;
- protected IAssetService m_assetService;
- private const bool m_checkPackets = true;
- private Timer m_propertiesPacketTimer;
- private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
- #endregion Class Members
- #region Properties
- public LLUDPClient UDPClient { get { return m_udpClient; } }
- public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
- 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); }
- /// <summary>
- /// First name of the agent/avatar represented by the client
- /// </summary>
- public string FirstName { get { return m_firstName; } }
- /// <summary>
- /// Last name of the agent/avatar represented by the client
- /// </summary>
- public string LastName { get { return m_lastName; } }
- /// <summary>
- /// Full name of the client (first name and last name)
- /// </summary>
- 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 IsLoggingOut
- {
- get { return m_IsLoggingOut; }
- set { m_IsLoggingOut = value; }
- }
- public bool DisableFacelights
- {
- get { return m_disableFacelights; }
- set { m_disableFacelights = value; }
- }
- public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
- #endregion Properties
- /// <summary>
- /// Constructor
- /// </summary>
- public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
- UUID agentId, UUID sessionId, uint circuitCode)
- {
- RegisterInterface<IClientIM>(this);
- RegisterInterface<IClientChat>(this);
- RegisterInterface<IClientIPEndpoint>(this);
- InitDefaultAnimations();
- m_scene = scene;
- m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
- m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
- m_killRecord = new HashSet<uint>();
- // m_attachmentsSent = new HashSet<uint>();
- m_assetService = m_scene.RequestModuleInterface<IAssetService>();
- m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
- m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
- m_channelVersion = Util.StringToBytes256(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;
- m_udpServer = udpServer;
- m_udpClient = udpClient;
- m_udpClient.OnQueueEmpty += HandleQueueEmpty;
- m_udpClient.OnPacketStats += PopulateStats;
- m_propertiesPacketTimer = new Timer(100);
- m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket;
- m_prioritizer = new Prioritizer(m_scene);
- RegisterLocalPacketHandlers();
- }
- public void SetDebugPacketLevel(int newDebug)
- {
- m_debugPacketLevel = newDebug;
- }
- #region Client Methods
- /// <summary>
- /// Shut down the client view
- /// </summary>
- public void Close()
- {
- m_log.DebugFormat(
- "[CLIENT]: Close has been called for {0} attached to scene {1}",
- Name, m_scene.RegionInfo.RegionName);
- // Send the STOP packet
- DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
- OutPacket(disable, ThrottleOutPacketType.Unknown);
- IsActive = false;
- // Shutdown the image manager
- if (m_imageManager != null)
- m_imageManager.Close();
- // Fire the callback for this connection closing
- if (OnConnectionClosed != null)
- OnConnectionClosed(this);
- // Flush all of the packets out of the UDP server for this client
- if (m_udpServer != null)
- m_udpServer.Flush(m_udpClient);
- // Remove ourselves from the scene
- m_scene.RemoveClient(AgentId);
- // We can't reach into other scenes and close the connection
- // We need to do this over grid communications
- //m_scene.CloseAllAgents(CircuitCode);
- // Disable UDP handling for this client
- m_udpClient.Shutdown();
- //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
- //GC.Collect();
- //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
- }
- public void Kick(string message)
- {
- if (!ChildAgentStatus())
- {
- KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
- kupack.UserInfo.AgentID = AgentId;
- kupack.UserInfo.SessionID = SessionId;
- kupack.TargetBlock.TargetIP = 0;
- kupack.TargetBlock.TargetPort = 0;
- kupack.UserInfo.Reason = Util.StringToBytes256(message);
- OutPacket(kupack, ThrottleOutPacketType.Task);
- // You must sleep here or users get no message!
- Thread.Sleep(500);
- }
- }
- public void Stop()
- {
- }
- #endregion Client Methods
- #region Packet Handling
- public void PopulateStats(int inPackets, int outPackets, int unAckedBytes)
- {
- NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate;
- if (handlerNetworkStatsUpdate != null)
- {
- handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes);
- }
- }
- public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
- {
- bool result = false;
- lock (PacketHandlers)
- {
- if (!PacketHandlers.ContainsKey(packetType))
- {
- PacketHandlers.Add(packetType, handler);
- result = true;
- }
- }
- return result;
- }
- public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
- {
- return AddLocalPacketHandler(packetType, handler, true);
- }
- public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool async)
- {
- bool result = false;
- lock (m_packetHandlers)
- {
- if (!m_packetHandlers.ContainsKey(packetType))
- {
- m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = async });
- result = true;
- }
- }
- return result;
- }
- public bool AddGenericPacketHandler(string MethodName, GenericMessage handler)
- {
- MethodName = MethodName.ToLower().Trim();
- bool result = false;
- lock (m_genericPacketHandlers)
- {
- if (!m_genericPacketHandlers.ContainsKey(MethodName))
- {
- m_genericPacketHandlers.Add(MethodName, handler);
- result = true;
- }
- }
- return result;
- }
- /// <summary>
- /// Try to process a packet using registered packet handlers
- /// </summary>
- /// <param name="packet"></param>
- /// <returns>True if a handler was found which successfully processed the packet.</returns>
- protected virtual bool ProcessPacketMethod(Packet packet)
- {
- bool result = false;
- PacketProcessor pprocessor;
- if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
- {
- //there is a local handler for this packet type
- if (pprocessor.Async)
- {
- object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
- Util.FireAndForget(ProcessSpecificPacketAsync, obj);
- result = true;
- }
- else
- {
- result = pprocessor.method(this, packet);
- }
- }
- else
- {
- //there is not a local handler so see if there is a Global handler
- PacketMethod method = null;
- bool found;
- lock (PacketHandlers)
- {
- found = PacketHandlers.TryGetValue(packet.Type, out method);
- }
- if (found)
- {
- result = method(this, packet);
- }
- }
- return result;
- }
- public void ProcessSpecificPacketAsync(object state)
- {
- AsyncPacketProcess packetObject = (AsyncPacketProcess)state;
- try
- {
- packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack);
- }
- catch (Exception e)
- {
- // Make sure that we see any exception caused by the asynchronous operation.
- m_log.Error(
- string.Format("[LLCLIENTVIEW]: Caught exception while processing {0}", packetObject.Pack), e);
- }
- }
- #endregion Packet Handling
- # region Setup
- public virtual void Start()
- {
- m_scene.AddNewClient(this);
- RefreshGroupMembership();
- }
- # endregion
- public void ActivateGesture(UUID assetId, UUID gestureId)
- {
- }
- public void DeactivateGesture(UUID assetId, UUID gestureId)
- {
- }
- // Sound
- public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
- {
- }
- #region Scene/Avatar to Client
- public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
- {
- RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake);
- handshake.RegionInfo = new RegionHandshakePacket.RegionInfoBlock();
- handshake.RegionInfo.BillableFactor = args.billableFactor;
- handshake.RegionInfo.IsEstateManager = args.isEstateManager;
- handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0;
- handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1;
- handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2;
- handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3;
- handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0;
- handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1;
- handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2;
- handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3;
- handshake.RegionInfo.SimAccess = args.simAccess;
- handshake.RegionInfo.WaterHeight = args.waterHeight;
- handshake.RegionInfo.RegionFlags = args.regionFlags;
- handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
- handshake.RegionInfo.SimOwner = args.SimOwner;
- handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
- handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
- handshake.RegionInfo.TerrainBase2 = args.terrainBase2;
- handshake.RegionInfo.TerrainBase3 = args.terrainBase3;
- handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0;
- handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1;
- handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2;
- handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3;
- handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting?
- handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block();
- handshake.RegionInfo2.RegionID = regionInfo.RegionID;
- handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block();
- handshake.RegionInfo3.CPUClassID = 9;
- handshake.RegionInfo3.CPURatio = 1;
- handshake.RegionInfo3.ColoName = Utils.EmptyBytes;
- handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
- handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
- OutPacket(handshake, ThrottleOutPacketType.Task);
- }
- /// <summary>
- ///
- /// </summary>
- public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
- {
- AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
- mov.SimData.ChannelVersion = m_channelVersion;
- mov.AgentData.SessionID = m_sessionId;
- mov.AgentData.AgentID = AgentId;
- mov.Data.RegionHandle = regInfo.RegionHandle;
- mov.Data.Timestamp = (uint)Util.UnixTimeSinceEpoch();
- if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
- {
- mov.Data.Position = m_startpos;
- }
- else
- {
- mov.Data.Position = pos;
- }
- mov.Data.LookAt = look;
- // Hack to get this out immediately and skip the throttles
- OutPacket(mov, ThrottleOutPacketType.Unknown);
- }
- public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
- UUID fromAgentID, byte source, byte audible)
- {
- ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
- reply.ChatData.Audible = audible;
- reply.ChatData.Message = Util.StringToBytes1024(message);
- reply.ChatData.ChatType = type;
- reply.ChatData.SourceType = source;
- reply.ChatData.Position = fromPos;
- reply.ChatData.FromName = Util.StringToBytes256(fromName);
- reply.ChatData.OwnerID = fromAgentID;
- reply.ChatData.SourceID = fromAgentID;
- OutPacket(reply, ThrottleOutPacketType.Task);
- }
- /// <summary>
- /// Send an instant message to this client
- /// </summary>
- //
- // Don't remove transaction ID! Groups and item gives need to set it!
- public void SendInstantMessage(GridInstantMessage im)
- {
- if (((Scene)(m_scene)).Permissions.CanInstantMessage(new UUID(im.fromAgentID), new UUID(im.toAgentID)))
- {
- ImprovedInstantMessagePacket msg
- = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage);
- msg.AgentData.AgentID = new UUID(im.fromAgentID);
- msg.AgentData.SessionID = UUID.Zero;
- msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
- msg.MessageBlock.Dialog = im.dialog;
- msg.MessageBlock.FromGroup = im.fromGroup;
- if (im.imSessionID == UUID.Zero.Guid)
- msg.MessageBlock.ID = new UUID(im.fromAgentID) ^ new UUID(im.toAgentID);
- else
- msg.MessageBlock.ID = new UUID(im.imSessionID);
- msg.MessageBlock.Offline = im.offline;
- msg.MessageBlock.ParentEstateID = im.ParentEstateID;
- msg.MessageBlock.Position = im.Position;
- msg.MessageBlock.RegionID = new UUID(im.RegionID);
- msg.MessageBlock.Timestamp = im.timestamp;
- msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
- msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
- msg.MessageBlock.BinaryBucket = im.binaryBucket;
- if (im.message.StartsWith("[grouptest]"))
- { // this block is test code for implementing group IM - delete when group IM is finished
- IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
- if (eq != null)
- {
- im.dialog = 17;
- //eq.ChatterboxInvitation(
- // new UUID("00000000-68f9-1111-024e-222222111123"),
- // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
- // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
- eq.ChatterboxInvitation(
- new UUID("00000000-68f9-1111-024e-222222111123"),
- "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
- false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
- eq.ChatterBoxSessionAgentListUpdates(
- new UUID("00000000-68f9-1111-024e-222222111123"),
- new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
- }
- Console.WriteLine("SendInstantMessage: " + msg);
- }
- else
- OutPacket(msg, ThrottleOutPacketType.Task);
- }
- }
- public void SendGenericMessage(string method, List<string> message)
- {
- GenericMessagePacket gmp = new GenericMessagePacket();
- gmp.MethodData.Method = Util.StringToBytes256(method);
- gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
- int i = 0;
- foreach (string val in message)
- {
- gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
- gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
- }
- OutPacket(gmp, ThrottleOutPacketType.Task);
- }
- public void SendGenericMessage(string method, List<byte[]> message)
- {
- GenericMessagePacket gmp = new GenericMessagePacket();
- gmp.MethodData.Method = Util.StringToBytes256(method);
- gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
- int i = 0;
- foreach (byte[] val in message)
- {
- gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
- gmp.ParamList[i++].Parameter = val;
- }
- OutPacket(gmp, ThrottleOutPacketType.Task);
- }
- public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals)
- {
- int i = 0;
- foreach (GroupActiveProposals Proposal in Proposals)
- {
- GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
- GAPIRP.AgentData.AgentID = AgentId;
- GAPIRP.AgentData.GroupID = groupID;
- GAPIRP.TransactionData.TransactionID = transactionID;
- GAPIRP.TransactionData.TotalNumItems = ((uint)i+1);
- GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
- GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
- ProposalData.VoteCast = Utils.StringToBytes("false");
- ProposalData.VoteID = new UUID(Proposal.VoteID);
- ProposalData.VoteInitiator = new UUID(Proposal.VoteInitiator);
- ProposalData.Majority = (float)Convert.ToInt32(Proposal.Majority);
- ProposalData.Quorum = Convert.ToInt32(Proposal.Quorum);
- ProposalData.TerseDateID = Utils.StringToBytes(Proposal.TerseDateID);
- ProposalData.StartDateTime = Utils.StringToBytes(Proposal.StartDateTime);
- ProposalData.EndDateTime = Utils.StringToBytes(Proposal.EndDateTime);
- ProposalData.ProposalText = Utils.StringToBytes(Proposal.ProposalText);
- ProposalData.AlreadyVoted = false;
- GAPIRP.ProposalData[i] = ProposalData;
- OutPacket(GAPIRP, ThrottleOutPacketType.Task);
- i++;
- }
- if (Proposals.Length == 0)
- {
- GroupActiveProposalItemReplyPacket GAPIRP = new GroupActiveProposalItemReplyPacket();
- GAPIRP.AgentData.AgentID = AgentId;
- GAPIRP.AgentData.GroupID = groupID;
- GAPIRP.TransactionData.TransactionID = transactionID;
- GAPIRP.TransactionData.TotalNumItems = 1;
- GroupActiveProposalItemReplyPacket.ProposalDataBlock ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock();
- GAPIRP.ProposalData = new GroupActiveProposalItemReplyPacket.ProposalDataBlock[1];
- ProposalData.VoteCast = Utils.StringToBytes("false");
- ProposalData.VoteID = UUID.Zero;
- ProposalData.VoteInitiator = UUID.Zero;
- ProposalData.Majority = 0;
- ProposalData.Quorum = 0;
- ProposalData.TerseDateID = Utils.StringToBytes("");
- ProposalData.StartDateTime = Utils.StringToBytes("");
- ProposalData.EndDateTime = Utils.StringToBytes("");
- ProposalData.ProposalText = Utils.StringToBytes("");
- ProposalData.AlreadyVoted = false;
- GAPIRP.ProposalData[0] = ProposalData;
- OutPacket(GAPIRP, ThrottleOutPacketType.Task);
- }
- }
- public void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes)
- {
- int i = 0;
- foreach (GroupVoteHistory Vote in Votes)
- {
- GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
- GVHIRP.AgentData.AgentID = AgentId;
- GVHIRP.AgentData.GroupID = groupID;
- GVHIRP.TransactionData.TransactionID = transactionID;
- GVHIRP.TransactionData.TotalNumItems = ((uint)i+1);
- GVHIRP.HistoryItemData.VoteID = new UUID(Vote.VoteID);
- GVHIRP.HistoryItemData.VoteInitiator = new UUID(Vote.VoteInitiator);
- GVHIRP.HistoryItemData.Majority = (float)Convert.ToInt32(Vote.Majority);
- GVHIRP.HistoryItemData.Quorum = Convert.ToInt32(Vote.Quorum);
- GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes(Vote.TerseDateID);
- GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes(Vote.StartDateTime);
- GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes(Vote.EndDateTime);
- GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes(Vote.VoteType);
- GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes(Vote.VoteResult);
- GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes(Vote.ProposalText);
- GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
- GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
- VoteItem.CandidateID = UUID.Zero;
- VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
- VoteItem.VoteCast = Utils.StringToBytes("Yes");
- GVHIRP.VoteItem[i] = VoteItem;
- OutPacket(GVHIRP, ThrottleOutPacketType.Task);
- i++;
- }
- if (Votes.Length == 0)
- {
- GroupVoteHistoryItemReplyPacket GVHIRP = new GroupVoteHistoryItemReplyPacket();
- GVHIRP.AgentData.AgentID = AgentId;
- GVHIRP.AgentData.GroupID = groupID;
- GVHIRP.TransactionData.TransactionID = transactionID;
- GVHIRP.TransactionData.TotalNumItems = 0;
- GVHIRP.HistoryItemData.VoteID = UUID.Zero;
- GVHIRP.HistoryItemData.VoteInitiator = UUID.Zero;
- GVHIRP.HistoryItemData.Majority = 0;
- GVHIRP.HistoryItemData.Quorum = 0;
- GVHIRP.HistoryItemData.TerseDateID = Utils.StringToBytes("");
- GVHIRP.HistoryItemData.StartDateTime = Utils.StringToBytes("");
- GVHIRP.HistoryItemData.EndDateTime = Utils.StringToBytes("");
- GVHIRP.HistoryItemData.VoteType = Utils.StringToBytes("");
- GVHIRP.HistoryItemData.VoteResult = Utils.StringToBytes("");
- GVHIRP.HistoryItemData.ProposalText = Utils.StringToBytes("");
- GroupVoteHistoryItemReplyPacket.VoteItemBlock VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock();
- GVHIRP.VoteItem = new GroupVoteHistoryItemReplyPacket.VoteItemBlock[1];
- VoteItem.CandidateID = UUID.Zero;
- VoteItem.NumVotes = 0; //TODO: FIX THIS!!!
- VoteItem.VoteCast = Utils.StringToBytes("No");
- GVHIRP.VoteItem[0] = VoteItem;
- OutPacket(GVHIRP, ThrottleOutPacketType.Task);
- }
- }
- public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
- {
- GroupAccountDetailsReplyPacket GADRP = new GroupAccountDetailsReplyPacket();
- GADRP.AgentData = new GroupAccountDetailsReplyPacket.AgentDataBlock();
- GADRP.AgentData.AgentID = sender.AgentId;
- GADRP.AgentData.GroupID = groupID;
- GADRP.HistoryData = new GroupAccountDetailsReplyPacket.HistoryDataBlock[1];
- GroupAccountDetailsReplyPacket.HistoryDataBlock History = new GroupAccountDetailsReplyPacket.HistoryDataBlock();
- GADRP.MoneyData = new GroupAccountDetailsReplyPacket.MoneyDataBlock();
- GADRP.MoneyData.CurrentInterval = 0;
- GADRP.MoneyData.IntervalDays = 7;
- GADRP.MoneyData.RequestID = transactionID;
- GADRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString());
- History.Amount = amt;
- History.Description = Utils.StringToBytes("");
- GADRP.HistoryData[0] = History;
- OutPacket(GADRP, ThrottleOutPacketType.Task);
- }
- public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier)
- {
- GroupAccountSummaryReplyPacket GASRP =
- (GroupAccountSummaryReplyPacket)PacketPool.Instance.GetPacket(
- PacketType.GroupAccountSummaryReply);
- GASRP.AgentData = new GroupAccountSummaryReplyPacket.AgentDataBlock();
- GASRP.AgentData.AgentID = sender.AgentId;
- GASRP.AgentData.GroupID = groupID;
- GASRP.MoneyData = new GroupAccountSummaryReplyPacket.MoneyDataBlock();
- GASRP.MoneyData.Balance = (int)moneyAmt;
- GASRP.MoneyData.TotalCredits = totalTier;
- GASRP.MoneyData.TotalDebits = usedTier;
- GASRP.MoneyData.StartDate = new byte[1];
- GASRP.MoneyData.CurrentInterval = 1;
- GASRP.MoneyData.GroupTaxCurrent = 0;
- GASRP.MoneyData.GroupTaxEstimate = 0;
- GASRP.MoneyData.IntervalDays = 0;
- GASRP.MoneyData.LandTaxCurrent = 0;
- GASRP.MoneyData.LandTaxEstimate = 0;
- GASRP.MoneyData.LastTaxDate = new byte[1];
- GASRP.MoneyData.LightTaxCurrent = 0;
- GASRP.MoneyData.TaxDate = new byte[1];
- GASRP.MoneyData.RequestID = sender.AgentId;
- GASRP.MoneyData.ParcelDirFeeEstimate = 0;
- GASRP.MoneyData.ParcelDirFeeCurrent = 0;
- GASRP.MoneyData.ObjectTaxEstimate = 0;
- GASRP.MoneyData.NonExemptMembers = 0;
- GASRP.MoneyData.ObjectTaxCurrent = 0;
- GASRP.MoneyData.LightTaxEstimate = 0;
- OutPacket(GASRP, ThrottleOutPacketType.Task);
- }
- public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt)
- {
- GroupAccountTransactionsReplyPacket GATRP =
- (GroupAccountTransactionsReplyPacket)PacketPool.Instance.GetPacket(
- PacketType.GroupAccountTransactionsReply);
- GATRP.AgentData = new GroupAccou…
Large files files are truncated, but you can click here to view the full file