From d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 30 Apr 2011 09:24:15 -0700 Subject: First stab at cleaning up Caps. Compiles. Untested. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 12123 +++++++++++++++++++ 1 file changed, 12123 insertions(+) create mode 100644 OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs new file mode 100644 index 0000000..43903ce --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -0,0 +1,12123 @@ +/* + * 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; + +using System.IO; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public delegate bool PacketMethod(IClientAPI simClient, Packet packet); + + /// + /// Handles new client connections + /// Constructor takes a single Packet and authenticates everything + /// + public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector + { + /// + /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. + /// + protected int m_debugPacketLevel = 0; + + #region Events + + public event GenericMessage OnGenericMessage; + public event BinaryGenericMessage OnBinaryGenericMessage; + public event Action OnLogout; + public event ObjectPermissions OnObjectPermissions; + public event Action 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 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 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 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); + + /// 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; + 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 m_defaultAnimations = new Dictionary(); + private readonly IGroupsModule m_GroupsModule; + + private int m_cachedTextureSerial; + private PriorityQueue m_entityUpdates; + private PriorityQueue m_entityProps; + private Prioritizer m_prioritizer; + private bool m_disableFacelights = false; + + /// + /// List used in construction of data blocks for an object update packet. This is to stop us having to + /// continually recreate it. + /// + protected List m_fullUpdateDataBlocksBuilder; + + /// + /// 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 a lock + /// + /// + protected HashSet m_killRecord; + +// protected HashSet 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 m_packetHandlers = new Dictionary(); + protected Dictionary m_genericPacketHandlers = new Dictionary(); //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 m_groupPowers = new Dictionary(); + protected int m_terrainCheckerCount; + protected uint m_agentFOVCounter; + + protected IAssetService m_assetService; + private const bool m_checkPackets = true; + + #endregion Class Members + + #region Properties + + public LLUDPClient UDPClient { get { return m_udpClient; } } + public LLUDPServer UDPServer { get { return m_udpServer; } } + 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); } + + /// + /// Entity update queues + /// + public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } } + + /// + /// First name of the agent/avatar represented by the client + /// + public string FirstName { get { return m_firstName; } } + + /// + /// Last name of the agent/avatar represented by the client + /// + 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 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 + + /// + /// Constructor + /// + public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, + UUID agentId, UUID sessionId, uint circuitCode) + { + RegisterInterface(this); + RegisterInterface(this); + RegisterInterface(this); + + InitDefaultAnimations(); + + m_scene = scene; + + m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); + m_entityProps = new PriorityQueue(m_scene.Entities.Count); + m_fullUpdateDataBlocksBuilder = new List(); + m_killRecord = new HashSet(); +// m_attachmentsSent = new HashSet(); + + m_assetService = m_scene.RequestModuleInterface(); + m_GroupsModule = scene.RequestModuleInterface(); + m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); + 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_prioritizer = new Prioritizer(m_scene); + + RegisterLocalPacketHandlers(); + } + + public void SetDebugPacketLevel(int newDebug) + { + m_debugPacketLevel = newDebug; + } + + #region Client Methods + + /// + /// Shut down the client view + /// + 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; + } + + /// + /// Try to process a packet using registered packet handlers + /// + /// + /// True if a handler was found which successfully processed the packet. + 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.ErrorFormat( + "[LLCLIENTVIEW]: Caught exception while processing {0} for {1}, {2} {3}", + packetObject.Pack, Name, e.Message, e.StackTrace); + } + } + + #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); + } + + /// + /// + /// + 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); + } + + /// + /// Send an instant message to this client + /// + // + // 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(); + 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 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 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 GroupAccountTransactionsReplyPacket.AgentDataBlock(); + GATRP.AgentData.AgentID = sender.AgentId; + GATRP.AgentData.GroupID = groupID; + GATRP.MoneyData = new GroupAccountTransactionsReplyPacket.MoneyDataBlock(); + GATRP.MoneyData.CurrentInterval = 0; + GATRP.MoneyData.IntervalDays = 7; + GATRP.MoneyData.RequestID = transactionID; + GATRP.MoneyData.StartDate = Utils.StringToBytes(DateTime.Today.ToString()); + GATRP.HistoryData = new GroupAccountTransactionsReplyPacket.HistoryDataBlock[1]; + GroupAccountTransactionsReplyPacket.HistoryDataBlock History = new GroupAccountTransactionsReplyPacket.HistoryDataBlock(); + History.Amount = 0; + History.Item = Utils.StringToBytes(""); + History.Time = Utils.StringToBytes(""); + History.Type = 0; + History.User = Utils.StringToBytes(""); + GATRP.HistoryData[0] = History; + OutPacket(GATRP, ThrottleOutPacketType.Task); + } + + /// + /// Send the region heightmap to the client + /// + /// heightmap + public virtual void SendLayerData(float[] map) + { + Util.FireAndForget(DoSendLayerData, map); + } + + /// + /// Send terrain layer information to the client. + /// + /// + private void DoSendLayerData(object o) + { + float[] map = LLHeightFieldMoronize((float[])o); + + try + { + //for (int y = 0; y < 16; y++) + //{ + // for (int x = 0; x < 16; x++) + // { + // SendLayerData(x, y, map); + // } + //} + + // Send LayerData in a spiral pattern. Fun! + SendLayerTopRight(map, 0, 0, 15, 15); + } + catch (Exception e) + { + m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e); + } + } + + private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2) + { + // Row + for (int i = x1; i <= x2; i++) + SendLayerData(i, y1, map); + + // Column + for (int j = y1 + 1; j <= y2; j++) + SendLayerData(x2, j, map); + + if (x2 - x1 > 0) + SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); + } + + void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2) + { + // Row in reverse + for (int i = x2; i >= x1; i--) + SendLayerData(i, y2, map); + + // Column in reverse + for (int j = y2 - 1; j >= y1; j--) + SendLayerData(x1, j, map); + + if (x2 - x1 > 0) + SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); + } + + /// + /// Sends a set of four patches (x, x+1, ..., x+3) to the client + /// + /// heightmap + /// X coordinate for patches 0..12 + /// Y coordinate for patches 0..15 + // private void SendLayerPacket(float[] map, int y, int x) + // { + // int[] patches = new int[4]; + // patches[0] = x + 0 + y * 16; + // patches[1] = x + 1 + y * 16; + // patches[2] = x + 2 + y * 16; + // patches[3] = x + 3 + y * 16; + + // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); + // OutPacket(layerpack, ThrottleOutPacketType.Land); + // } + + /// + /// Sends a specified patch to a client + /// + /// Patch coordinate (x) 0..15 + /// Patch coordinate (y) 0..15 + /// heightmap + public void SendLayerData(int px, int py, float[] map) + { + try + { + int[] patches = new int[] { py * 16 + px }; + float[] heightmap = (map.Length == 65536) ? + map : + LLHeightFieldMoronize(map); + + LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); + layerpack.Header.Reliable = true; + + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + catch (Exception e) + { + m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e); + } + } + + /// + /// Munges heightfield into the LLUDP backed in restricted heightfield. + /// + /// float array in the base; Constants.RegionSize + /// float array in the base 256 + internal float[] LLHeightFieldMoronize(float[] map) + { + if (map.Length == 65536) + return map; + else + { + float[] returnmap = new float[65536]; + + if (map.Length < 65535) + { + // rebase the vector stride to 256 + for (int i = 0; i < Constants.RegionSize; i++) + Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize); + } + else + { + for (int i = 0; i < 256; i++) + Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256); + } + + //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536); + + return returnmap; + } + + } + + /// + /// Send the wind matrix to the client + /// + /// 16x16 array of wind speeds + public virtual void SendWindData(Vector2[] windSpeeds) + { + Util.FireAndForget(DoSendWindData, windSpeeds); + } + + /// + /// Send the cloud matrix to the client + /// + /// 16x16 array of cloud densities + public virtual void SendCloudData(float[] cloudDensity) + { + Util.FireAndForget(DoSendCloudData, cloudDensity); + } + + /// + /// Send wind layer information to the client. + /// + /// + private void DoSendWindData(object o) + { + Vector2[] windSpeeds = (Vector2[])o; + TerrainPatch[] patches = new TerrainPatch[2]; + patches[0] = new TerrainPatch(); + patches[0].Data = new float[16 * 16]; + patches[1] = new TerrainPatch(); + patches[1].Data = new float[16 * 16]; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X; + patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y; + } + } + + LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind); + layerpack.Header.Zerocoded = true; + OutPacket(layerpack, ThrottleOutPacketType.Wind); + } + + /// + /// Send cloud layer information to the client. + /// + /// + private void DoSendCloudData(object o) + { + float[] cloudCover = (float[])o; + TerrainPatch[] patches = new TerrainPatch[1]; + patches[0] = new TerrainPatch(); + patches[0].Data = new float[16 * 16]; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x]; + } + } + + LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud); + layerpack.Header.Zerocoded = true; + OutPacket(layerpack, ThrottleOutPacketType.Cloud); + } + + /// + /// Tell the client that the given neighbour region is ready to receive a child agent. + /// + public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint) + { + IPAddress neighbourIP = neighbourEndPoint.Address; + ushort neighbourPort = (ushort)neighbourEndPoint.Port; + + EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator); + // TODO: don't create new blocks if recycling an old packet + enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock(); + enablesimpacket.SimulatorInfo.Handle = neighbourHandle; + + byte[] byteIP = neighbourIP.GetAddressBytes(); + enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0]; + enablesimpacket.SimulatorInfo.Port = neighbourPort; + + enablesimpacket.Header.Reliable = true; // ESP's should be reliable. + + OutPacket(enablesimpacket, ThrottleOutPacketType.Task); + } + + public AgentCircuitData RequestClientInfo() + { + AgentCircuitData agentData = new AgentCircuitData(); + agentData.AgentID = AgentId; + agentData.SessionID = m_sessionId; + agentData.SecureSessionID = SecureSessionId; + agentData.circuitcode = m_circuitCode; + agentData.child = false; + agentData.firstname = m_firstName; + agentData.lastname = m_lastName; + + ICapabilitiesModule capsModule = m_scene.RequestModuleInterface(); + + if (capsModule == null) // can happen when shutting down. + return agentData; + + agentData.CapsPath = capsModule.GetCapsPath(m_agentId); + agentData.ChildrenCapSeeds = new Dictionary(capsModule.GetChildrenSeeds(m_agentId)); + + return agentData; + } + + public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, IPEndPoint externalIPEndPoint, + string capsURL) + { + Vector3 look = new Vector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10); + + //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion); + CrossedRegionPacket newSimPack = new CrossedRegionPacket(); + // TODO: don't create new blocks if recycling an old packet + newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock(); + newSimPack.AgentData.AgentID = AgentId; + newSimPack.AgentData.SessionID = m_sessionId; + newSimPack.Info = new CrossedRegionPacket.InfoBlock(); + newSimPack.Info.Position = pos; + newSimPack.Info.LookAt = look; + newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock(); + newSimPack.RegionData.RegionHandle = newRegionHandle; + byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes(); + newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24; + newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16; + newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; + newSimPack.RegionData.SimIP += (uint)byteIP[0]; + newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; + newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL); + + // Hack to get this out immediately and skip throttles + OutPacket(newSimPack, ThrottleOutPacketType.Unknown); + } + + internal void SendMapBlockSplit(List mapBlocks, uint flag) + { + MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply); + // TODO: don't create new blocks if recycling an old packet + + MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); + + mapReply.AgentData.AgentID = AgentId; + mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; + mapReply.AgentData.Flags = flag; + + for (int i = 0; i < mapBlocks2.Length; i++) + { + mapReply.Data[i] = new MapBlockReplyPacket.DataBlock(); + mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId; + //m_log.Warn(mapBlocks2[i].MapImageId.ToString()); + mapReply.Data[i].X = mapBlocks2[i].X; + mapReply.Data[i].Y = mapBlocks2[i].Y; + mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight; + mapReply.Data[i].Name = Utils.StringToBytes(mapBlocks2[i].Name); + mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; + mapReply.Data[i].Access = mapBlocks2[i].Access; + mapReply.Data[i].Agents = mapBlocks2[i].Agents; + } + OutPacket(mapReply, ThrottleOutPacketType.Land); + } + + public void SendMapBlock(List mapBlocks, uint flag) + { + + MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); + + int maxsend = 10; + + //int packets = Math.Ceiling(mapBlocks2.Length / maxsend); + + List sendingBlocks = new List(); + + for (int i = 0; i < mapBlocks2.Length; i++) + { + sendingBlocks.Add(mapBlocks2[i]); + if (((i + 1) == mapBlocks2.Length) || (((i + 1) % maxsend) == 0)) + { + SendMapBlockSplit(sendingBlocks, flag); + sendingBlocks = new List(); + } + } + } + + public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) + { + TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal); + tpLocal.Info.AgentID = AgentId; + tpLocal.Info.TeleportFlags = flags; + tpLocal.Info.LocationID = 2; + tpLocal.Info.LookAt = lookAt; + tpLocal.Info.Position = position; + + // Hack to get this out immediately and skip throttles + OutPacket(tpLocal, ThrottleOutPacketType.Unknown); + } + + public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID, + uint flags, string capsURL) + { + //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish); + + TeleportFinishPacket teleport = new TeleportFinishPacket(); + teleport.Info.AgentID = AgentId; + teleport.Info.RegionHandle = regionHandle; + teleport.Info.SimAccess = simAccess; + + teleport.Info.SeedCapability = Util.StringToBytes256(capsURL); + + IPAddress oIP = newRegionEndPoint.Address; + byte[] byteIP = oIP.GetAddressBytes(); + uint ip = (uint)byteIP[3] << 24; + ip += (uint)byteIP[2] << 16; + ip += (uint)byteIP[1] << 8; + ip += (uint)byteIP[0]; + + teleport.Info.SimIP = ip; + teleport.Info.SimPort = (ushort)newRegionEndPoint.Port; + teleport.Info.LocationID = 4; + teleport.Info.TeleportFlags = 1 << 4; + + // Hack to get this out immediately and skip throttles. + OutPacket(teleport, ThrottleOutPacketType.Unknown); + } + + /// + /// Inform the client that a teleport attempt has failed + /// + public void SendTeleportFailed(string reason) + { + TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); + tpFailed.Info.AgentID = AgentId; + tpFailed.Info.Reason = Util.StringToBytes256(reason); + tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0]; + + // Hack to get this out immediately and skip throttles + OutPacket(tpFailed, ThrottleOutPacketType.Unknown); + } + + /// + /// + /// + public void SendTeleportStart(uint flags) + { + TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart); + //TeleportStartPacket tpStart = new TeleportStartPacket(); + tpStart.Info.TeleportFlags = flags; //16; // Teleport via location + + // Hack to get this out immediately and skip throttles + OutPacket(tpStart, ThrottleOutPacketType.Unknown); + } + + public void SendTeleportProgress(uint flags, string message) + { + TeleportProgressPacket tpProgress = (TeleportProgressPacket)PacketPool.Instance.GetPacket(PacketType.TeleportProgress); + tpProgress.AgentData.AgentID = this.AgentId; + tpProgress.Info.TeleportFlags = flags; + tpProgress.Info.Message = Util.StringToBytes256(message); + + // Hack to get this out immediately and skip throttles + OutPacket(tpProgress, ThrottleOutPacketType.Unknown); + } + + public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) + { + MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); + money.MoneyData.AgentID = AgentId; + money.MoneyData.TransactionID = transaction; + money.MoneyData.TransactionSuccess = success; + money.MoneyData.Description = description; + money.MoneyData.MoneyBalance = balance; + OutPacket(money, ThrottleOutPacketType.Task); + } + + public void SendPayPrice(UUID objectID, int[] payPrice) + { + if (payPrice[0] == 0 && + payPrice[1] == 0 && + payPrice[2] == 0 && + payPrice[3] == 0 && + payPrice[4] == 0) + return; + + PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply); + payPriceReply.ObjectData.ObjectID = objectID; + payPriceReply.ObjectData.DefaultPayPrice = payPrice[0]; + + payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[4]; + payPriceReply.ButtonData[0] = new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[0].PayButton = payPrice[1]; + payPriceReply.ButtonData[1] = new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[1].PayButton = payPrice[2]; + payPriceReply.ButtonData[2] = new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[2].PayButton = payPrice[3]; + payPriceReply.ButtonData[3] = new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[3].PayButton = payPrice[4]; + + OutPacket(payPriceReply, ThrottleOutPacketType.Task); + } + + public void SendStartPingCheck(byte seq) + { + StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); + pc.Header.Reliable = false; + + pc.PingID.PingID = seq; + // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit + pc.PingID.OldestUnacked = 0; + + OutPacket(pc, ThrottleOutPacketType.Unknown); + } + + public void SendKillObject(ulong regionHandle, uint localID) + { +// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); + + KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); + // TODO: don't create new blocks if recycling an old packet + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; + kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[0].ID = localID; + kill.Header.Reliable = true; + kill.Header.Zerocoded = true; + + if (m_scene.GetScenePresence(localID) == null) + { + // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race + // condition where a kill can be processed before an out-of-date update for the same object. + lock (m_killRecord) + { + m_killRecord.Add(localID); + + // The throttle queue used here must match that being used for updates. Otherwise, there is a + // chance that a kill packet put on a separate queue will be sent to the client before an existing + // update packet on another queue. Receiving updates after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); + } + } + else + { + // OutPacket(kill, ThrottleOutPacketType.State); + OutPacket(kill, ThrottleOutPacketType.Task); + } + } + + /// + /// Send information about the items contained in a folder to the client. + /// + /// XXX This method needs some refactoring loving + /// + /// The owner of the folder + /// The id of the folder + /// The items contained in the folder identified by folderID + /// + /// Do we need to send folder information? + /// Do we need to send item information? + public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List items, + List folders, int version, + bool fetchFolders, bool fetchItems) + { + // An inventory descendents packet consists of a single agent section and an inventory details + // section for each inventory item. The size of each inventory item is approximately 550 bytes. + // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent + // packets containing metadata for in excess of 100 items. But in practice, there may be other + // factors (e.g. firewalls) restraining the maximum UDP packet size. See, + // + // http://opensimulator.org/mantis/view.php?id=226 + // + // for one example of this kind of thing. In fact, the Linden servers appear to only send about + // 6 to 7 items at a time, so let's stick with 6 + int MAX_ITEMS_PER_PACKET = 5; + int MAX_FOLDERS_PER_PACKET = 6; + + int totalItems = fetchItems ? items.Count : 0; + int totalFolders = fetchFolders ? folders.Count : 0; + int itemsSent = 0; + int foldersSent = 0; + int foldersToSend = 0; + int itemsToSend = 0; + + InventoryDescendentsPacket currentPacket = null; + + // Handle empty folders + // + if (totalItems == 0 && totalFolders == 0) + currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, 0, 0); + + // To preserve SL compatibility, we will NOT combine folders and items in one packet + // + while (itemsSent < totalItems || foldersSent < totalFolders) + { + if (currentPacket == null) // Start a new packet + { + foldersToSend = totalFolders - foldersSent; + if (foldersToSend > MAX_FOLDERS_PER_PACKET) + foldersToSend = MAX_FOLDERS_PER_PACKET; + + if (foldersToSend == 0) + { + itemsToSend = totalItems - itemsSent; + if (itemsToSend > MAX_ITEMS_PER_PACKET) + itemsToSend = MAX_ITEMS_PER_PACKET; + } + + currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, foldersToSend, itemsToSend); + } + + if (foldersToSend-- > 0) + currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]); + else if (itemsToSend-- > 0) + currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]); + else + { + OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); + currentPacket = null; + } + + } + + if (currentPacket != null) + OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); + } + + private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder) + { + InventoryDescendentsPacket.FolderDataBlock newBlock = new InventoryDescendentsPacket.FolderDataBlock(); + newBlock.FolderID = folder.ID; + newBlock.Name = Util.StringToBytes256(folder.Name); + newBlock.ParentID = folder.ParentID; + newBlock.Type = (sbyte)folder.Type; + + return newBlock; + } + + private InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item) + { + InventoryDescendentsPacket.ItemDataBlock newBlock = new InventoryDescendentsPacket.ItemDataBlock(); + newBlock.ItemID = item.ID; + newBlock.AssetID = item.AssetID; + newBlock.CreatorID = item.CreatorIdAsUuid; + newBlock.BaseMask = item.BasePermissions; + newBlock.Description = Util.StringToBytes256(item.Description); + newBlock.EveryoneMask = item.EveryOnePermissions; + newBlock.OwnerMask = item.CurrentPermissions; + newBlock.FolderID = item.Folder; + newBlock.InvType = (sbyte)item.InvType; + newBlock.Name = Util.StringToBytes256(item.Name); + newBlock.NextOwnerMask = item.NextPermissions; + newBlock.OwnerID = item.Owner; + newBlock.Type = (sbyte)item.AssetType; + + newBlock.GroupID = item.GroupID; + newBlock.GroupOwned = item.GroupOwned; + newBlock.GroupMask = item.GroupPermissions; + newBlock.CreationDate = item.CreationDate; + newBlock.SalePrice = item.SalePrice; + newBlock.SaleType = item.SaleType; + newBlock.Flags = item.Flags; + + newBlock.CRC = + Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType, + newBlock.InvType, newBlock.Type, + newBlock.AssetID, newBlock.GroupID, + newBlock.SalePrice, + newBlock.OwnerID, newBlock.CreatorID, + newBlock.ItemID, newBlock.FolderID, + newBlock.EveryoneMask, + newBlock.Flags, newBlock.OwnerMask, + newBlock.GroupMask, newBlock.NextOwnerMask); + + return newBlock; + } + + private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet) + { + packet.FolderData = new InventoryDescendentsPacket.FolderDataBlock[1]; + packet.FolderData[0] = new InventoryDescendentsPacket.FolderDataBlock(); + packet.FolderData[0].FolderID = UUID.Zero; + packet.FolderData[0].ParentID = UUID.Zero; + packet.FolderData[0].Type = -1; + packet.FolderData[0].Name = new byte[0]; + } + + private void AddNullItemBlockToDescendentsPacket(ref InventoryDescendentsPacket packet) + { + packet.ItemData = new InventoryDescendentsPacket.ItemDataBlock[1]; + packet.ItemData[0] = new InventoryDescendentsPacket.ItemDataBlock(); + packet.ItemData[0].ItemID = UUID.Zero; + packet.ItemData[0].AssetID = UUID.Zero; + packet.ItemData[0].CreatorID = UUID.Zero; + packet.ItemData[0].BaseMask = 0; + packet.ItemData[0].Description = new byte[0]; + packet.ItemData[0].EveryoneMask = 0; + packet.ItemData[0].OwnerMask = 0; + packet.ItemData[0].FolderID = UUID.Zero; + packet.ItemData[0].InvType = (sbyte)0; + packet.ItemData[0].Name = new byte[0]; + packet.ItemData[0].NextOwnerMask = 0; + packet.ItemData[0].OwnerID = UUID.Zero; + packet.ItemData[0].Type = -1; + + packet.ItemData[0].GroupID = UUID.Zero; + packet.ItemData[0].GroupOwned = false; + packet.ItemData[0].GroupMask = 0; + packet.ItemData[0].CreationDate = 0; + packet.ItemData[0].SalePrice = 0; + packet.ItemData[0].SaleType = 0; + packet.ItemData[0].Flags = 0; + + // No need to add CRC + } + + private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items) + { + InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); + descend.Header.Zerocoded = true; + descend.AgentData.AgentID = AgentId; + descend.AgentData.OwnerID = ownerID; + descend.AgentData.FolderID = folderID; + descend.AgentData.Version = version; + descend.AgentData.Descendents = descendents; + + if (folders > 0) + descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders]; + else + AddNullFolderBlockToDecendentsPacket(ref descend); + + if (items > 0) + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items]; + else + AddNullItemBlockToDescendentsPacket(ref descend); + + return descend; + } + + public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + { + const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + + FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply); + // TODO: don't create new blocks if recycling an old packet + inventoryReply.AgentData.AgentID = AgentId; + inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; + inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); + inventoryReply.InventoryData[0].ItemID = item.ID; + inventoryReply.InventoryData[0].AssetID = item.AssetID; + inventoryReply.InventoryData[0].CreatorID = item.CreatorIdAsUuid; + inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; + inventoryReply.InventoryData[0].CreationDate = item.CreationDate; + + 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 = Util.StringToBytes256(item.Name); + inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; + inventoryReply.InventoryData[0].OwnerID = item.Owner; + inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; + inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType; + + inventoryReply.InventoryData[0].GroupID = item.GroupID; + inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned; + inventoryReply.InventoryData[0].GroupMask = item.GroupPermissions; + inventoryReply.InventoryData[0].Flags = item.Flags; + inventoryReply.InventoryData[0].SalePrice = item.SalePrice; + inventoryReply.InventoryData[0].SaleType = item.SaleType; + + inventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC( + 1000, 0, inventoryReply.InventoryData[0].InvType, + inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID, + inventoryReply.InventoryData[0].GroupID, 100, + inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID, + inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + inventoryReply.Header.Zerocoded = true; + OutPacket(inventoryReply, ThrottleOutPacketType.Asset); + } + + protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase) + { + // We will use the same transaction id for all the separate packets to be sent out in this update. + UUID transactionId = UUID.Random(); + + List folderDataBlocks + = new List(); + + SendBulkUpdateInventoryFolderRecursive(folderBase, ref folderDataBlocks, transactionId); + + if (folderDataBlocks.Count > 0) + { + // We'll end up with some unsent folder blocks if there were some empty folders at the end of the list + // Send these now + BulkUpdateInventoryPacket bulkUpdate + = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); + bulkUpdate.Header.Zerocoded = true; + + bulkUpdate.AgentData.AgentID = AgentId; + bulkUpdate.AgentData.TransactionID = transactionId; + bulkUpdate.FolderData = folderDataBlocks.ToArray(); + List foo = new List(); + bulkUpdate.ItemData = foo.ToArray(); + + //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate); + OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); + } + } + + /// + /// Recursively construct bulk update packets to send folders and items + /// + /// + /// + /// + private void SendBulkUpdateInventoryFolderRecursive( + InventoryFolderBase folder, ref List folderDataBlocks, + UUID transactionId) + { + folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder)); + + const int MAX_ITEMS_PER_PACKET = 5; + + IInventoryService invService = m_scene.RequestModuleInterface(); + // If there are any items then we have to start sending them off in this packet - the next folder will have + // to be in its own bulk update packet. Also, we can only fit 5 items in a packet (at least this was the limit + // being used on the Linden grid at 20081203). + InventoryCollection contents = invService.GetFolderContent(AgentId, folder.ID); // folder.RequestListOfItems(); + List items = contents.Items; + while (items.Count > 0) + { + BulkUpdateInventoryPacket bulkUpdate + = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); + bulkUpdate.Header.Zerocoded = true; + + bulkUpdate.AgentData.AgentID = AgentId; + bulkUpdate.AgentData.TransactionID = transactionId; + bulkUpdate.FolderData = folderDataBlocks.ToArray(); + + int itemsToSend = (items.Count > MAX_ITEMS_PER_PACKET ? MAX_ITEMS_PER_PACKET : items.Count); + bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[itemsToSend]; + + for (int i = 0; i < itemsToSend; i++) + { + // Remove from the end of the list so that we don't incur a performance penalty + bulkUpdate.ItemData[i] = GenerateBulkUpdateItemDataBlock(items[items.Count - 1]); + items.RemoveAt(items.Count - 1); + } + + //m_log.Debug("SendBulkUpdateInventoryRecursive :" + bulkUpdate); + OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); + + folderDataBlocks = new List(); + + // If we're going to be sending another items packet then it needs to contain just the folder to which those + // items belong. + if (items.Count > 0) + folderDataBlocks.Add(GenerateBulkUpdateFolderDataBlock(folder)); + } + + List subFolders = contents.Folders; + foreach (InventoryFolderBase subFolder in subFolders) + { + SendBulkUpdateInventoryFolderRecursive(subFolder, ref folderDataBlocks, transactionId); + } + } + + /// + /// Generate a bulk update inventory data block for the given folder + /// + /// + /// + private BulkUpdateInventoryPacket.FolderDataBlock GenerateBulkUpdateFolderDataBlock(InventoryFolderBase folder) + { + BulkUpdateInventoryPacket.FolderDataBlock folderBlock = new BulkUpdateInventoryPacket.FolderDataBlock(); + + folderBlock.FolderID = folder.ID; + folderBlock.ParentID = folder.ParentID; + folderBlock.Type = -1; + folderBlock.Name = Util.StringToBytes256(folder.Name); + + return folderBlock; + } + + /// + /// Generate a bulk update inventory data block for the given item + /// + /// + /// + private BulkUpdateInventoryPacket.ItemDataBlock GenerateBulkUpdateItemDataBlock(InventoryItemBase item) + { + BulkUpdateInventoryPacket.ItemDataBlock itemBlock = new BulkUpdateInventoryPacket.ItemDataBlock(); + + itemBlock.ItemID = item.ID; + itemBlock.AssetID = item.AssetID; + itemBlock.CreatorID = item.CreatorIdAsUuid; + itemBlock.BaseMask = item.BasePermissions; + itemBlock.Description = Util.StringToBytes256(item.Description); + itemBlock.EveryoneMask = item.EveryOnePermissions; + itemBlock.FolderID = item.Folder; + itemBlock.InvType = (sbyte)item.InvType; + itemBlock.Name = Util.StringToBytes256(item.Name); + itemBlock.NextOwnerMask = item.NextPermissions; + itemBlock.OwnerID = item.Owner; + itemBlock.OwnerMask = item.CurrentPermissions; + itemBlock.Type = (sbyte)item.AssetType; + itemBlock.GroupID = item.GroupID; + itemBlock.GroupOwned = item.GroupOwned; + itemBlock.GroupMask = item.GroupPermissions; + itemBlock.Flags = item.Flags; + itemBlock.SalePrice = item.SalePrice; + itemBlock.SaleType = item.SaleType; + itemBlock.CreationDate = item.CreationDate; + + itemBlock.CRC = + Helpers.InventoryCRC( + 1000, 0, itemBlock.InvType, + itemBlock.Type, itemBlock.AssetID, + itemBlock.GroupID, 100, + itemBlock.OwnerID, itemBlock.CreatorID, + itemBlock.ItemID, itemBlock.FolderID, + (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, + (uint)PermissionMask.All); + + return itemBlock; + } + + public void SendBulkUpdateInventory(InventoryNodeBase node) + { + if (node is InventoryItemBase) + SendBulkUpdateInventoryItem((InventoryItemBase)node); + else if (node is InventoryFolderBase) + SendBulkUpdateInventoryFolder((InventoryFolderBase)node); + else + m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name); + } + + protected void SendBulkUpdateInventoryItem(InventoryItemBase item) + { + const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + + BulkUpdateInventoryPacket bulkUpdate + = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); + + bulkUpdate.AgentData.AgentID = AgentId; + bulkUpdate.AgentData.TransactionID = UUID.Random(); + + bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1]; + bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock(); + bulkUpdate.FolderData[0].FolderID = UUID.Zero; + bulkUpdate.FolderData[0].ParentID = UUID.Zero; + bulkUpdate.FolderData[0].Type = -1; + bulkUpdate.FolderData[0].Name = new byte[0]; + + bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1]; + bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock(); + bulkUpdate.ItemData[0].ItemID = item.ID; + bulkUpdate.ItemData[0].AssetID = item.AssetID; + 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].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].NextOwnerMask = item.NextPermissions; + bulkUpdate.ItemData[0].OwnerID = item.Owner; + bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; + bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType; + + bulkUpdate.ItemData[0].GroupID = item.GroupID; + bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned; + bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions; + bulkUpdate.ItemData[0].Flags = item.Flags; + bulkUpdate.ItemData[0].SalePrice = item.SalePrice; + bulkUpdate.ItemData[0].SaleType = item.SaleType; + + bulkUpdate.ItemData[0].CRC = + Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType, + bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID, + bulkUpdate.ItemData[0].GroupID, 100, + bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID, + bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + bulkUpdate.Header.Zerocoded = true; + OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); + } + + /// IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase) + public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) + { + const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + + UpdateCreateInventoryItemPacket InventoryReply + = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket( + PacketType.UpdateCreateInventoryItem); + + // TODO: don't create new blocks if recycling an old packet + InventoryReply.AgentData.AgentID = AgentId; + InventoryReply.AgentData.SimApproved = true; + InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; + InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); + InventoryReply.InventoryData[0].ItemID = Item.ID; + 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].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].NextOwnerMask = Item.NextPermissions; + InventoryReply.InventoryData[0].OwnerID = Item.Owner; + InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; + InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType; + InventoryReply.InventoryData[0].CallbackID = callbackId; + + InventoryReply.InventoryData[0].GroupID = Item.GroupID; + InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned; + InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions; + InventoryReply.InventoryData[0].Flags = Item.Flags; + InventoryReply.InventoryData[0].SalePrice = Item.SalePrice; + InventoryReply.InventoryData[0].SaleType = Item.SaleType; + InventoryReply.InventoryData[0].CreationDate = Item.CreationDate; + + InventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType, + InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID, + InventoryReply.InventoryData[0].GroupID, 100, + InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID, + InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + InventoryReply.Header.Zerocoded = true; + OutPacket(InventoryReply, ThrottleOutPacketType.Asset); + } + + public void SendRemoveInventoryItem(UUID itemID) + { + RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem); + // TODO: don't create new blocks if recycling an old packet + remove.AgentData.AgentID = AgentId; + remove.AgentData.SessionID = m_sessionId; + remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1]; + remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock(); + remove.InventoryData[0].ItemID = itemID; + remove.Header.Zerocoded = true; + OutPacket(remove, ThrottleOutPacketType.Asset); + } + + public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) + { + ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange); + ScriptControlChangePacket.DataBlock[] data = new ScriptControlChangePacket.DataBlock[1]; + ScriptControlChangePacket.DataBlock ddata = new ScriptControlChangePacket.DataBlock(); + ddata.Controls = (uint)controls; + ddata.PassToAgent = passToAgent; + ddata.TakeControls = TakeControls; + data[0] = ddata; + scriptcontrol.Data = data; + OutPacket(scriptcontrol, ThrottleOutPacketType.Task); + } + + public void SendTaskInventory(UUID taskID, short serial, byte[] fileName) + { + ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory); + replytask.InventoryData.TaskID = taskID; + replytask.InventoryData.Serial = serial; + replytask.InventoryData.Filename = fileName; + OutPacket(replytask, ThrottleOutPacketType.Asset); + } + + public void SendXferPacket(ulong xferID, uint packet, byte[] data) + { + SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); + sendXfer.XferID.ID = xferID; + sendXfer.XferID.Packet = packet; + sendXfer.DataPacket.Data = data; + OutPacket(sendXfer, ThrottleOutPacketType.Asset); + } + + public void SendAbortXferPacket(ulong xferID) + { + AbortXferPacket xferItem = (AbortXferPacket)PacketPool.Instance.GetPacket(PacketType.AbortXfer); + xferItem.XferID.ID = xferID; + OutPacket(xferItem, ThrottleOutPacketType.Asset); + } + + public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, + int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, + int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, + int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) + { + EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData); + economyData.Info.EnergyEfficiency = EnergyEfficiency; + economyData.Info.ObjectCapacity = ObjectCapacity; + economyData.Info.ObjectCount = ObjectCount; + economyData.Info.PriceEnergyUnit = PriceEnergyUnit; + economyData.Info.PriceGroupCreate = PriceGroupCreate; + economyData.Info.PriceObjectClaim = PriceObjectClaim; + economyData.Info.PriceObjectRent = PriceObjectRent; + economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor; + economyData.Info.PriceParcelClaim = PriceParcelClaim; + economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor; + economyData.Info.PriceParcelRent = PriceParcelRent; + economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay; + economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete; + economyData.Info.PriceRentLight = PriceRentLight; + economyData.Info.PriceUpload = PriceUpload; + economyData.Info.TeleportMinPrice = TeleportMinPrice; + economyData.Info.TeleportPriceExponent = TeleportPriceExponent; + economyData.Header.Reliable = true; + OutPacket(economyData, ThrottleOutPacketType.Task); + } + + public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List Data) + { + //construct the AvatarPickerReply packet. + AvatarPickerReplyPacket replyPacket = new AvatarPickerReplyPacket(); + replyPacket.AgentData.AgentID = AgentData.AgentID; + replyPacket.AgentData.QueryID = AgentData.QueryID; + //int i = 0; + List data_block = new List(); + foreach (AvatarPickerReplyDataArgs arg in Data) + { + AvatarPickerReplyPacket.DataBlock db = new AvatarPickerReplyPacket.DataBlock(); + db.AvatarID = arg.AvatarID; + db.FirstName = arg.FirstName; + db.LastName = arg.LastName; + data_block.Add(db); + } + replyPacket.Data = data_block.ToArray(); + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } + + public void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) + { + m_activeGroupID = activegroupid; + m_activeGroupName = groupname; + m_activeGroupPowers = grouppowers; + + AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); + sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; + sendAgentDataUpdate.AgentData.AgentID = agentid; + sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname); + sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname); + sendAgentDataUpdate.AgentData.GroupPowers = grouppowers; + sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle); + sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname); + OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task); + } + + /// + /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration + /// blue information box in the bottom right hand corner. + /// + /// + public void SendAlertMessage(string message) + { + AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); + alertPack.AlertData = new AlertMessagePacket.AlertDataBlock(); + alertPack.AlertData.Message = Util.StringToBytes256(message); + alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0]; + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + + /// + /// Send an agent alert message to the client. + /// + /// + /// On the linden client, if this true then it displays a one button text box placed in the + /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for + /// the AlertMessage packet). + public void SendAgentAlertMessage(string message, bool modal) + { + OutPacket(BuildAgentAlertPacket(message, modal), ThrottleOutPacketType.Task); + } + + /// + /// Construct an agent alert packet + /// + /// + /// + /// + public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) + { + AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); + alertPack.AgentData.AgentID = AgentId; + alertPack.AlertData.Message = Util.StringToBytes256(message); + alertPack.AlertData.Modal = modal; + + return alertPack; + } + + public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, + string url) + { + LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); + loadURL.Data.ObjectName = Util.StringToBytes256(objectname); + loadURL.Data.ObjectID = objectID; + loadURL.Data.OwnerID = ownerID; + loadURL.Data.OwnerIsGroup = groupOwned; + loadURL.Data.Message = Util.StringToBytes256(message); + loadURL.Data.URL = Util.StringToBytes256(url); + OutPacket(loadURL, ThrottleOutPacketType.Task); + } + + public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + { + ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); + dialog.Data.ObjectID = objectID; + dialog.Data.ObjectName = Util.StringToBytes256(objectname); + // this is the username of the *owner* + dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); + dialog.Data.LastName = Util.StringToBytes256(ownerLastName); + dialog.Data.Message = Util.StringToBytes1024(msg); + dialog.Data.ImageID = textureID; + dialog.Data.ChatChannel = ch; + ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; + for (int i = 0; i < buttonlabels.Length; i++) + { + buttons[i] = new ScriptDialogPacket.ButtonsBlock(); + buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); + } + dialog.Buttons = buttons; + OutPacket(dialog, ThrottleOutPacketType.Task); + } + + public void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID) + { + PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound); + // TODO: don't create new blocks if recycling an old packet + preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1]; + preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock(); + preSound.DataBlock[0].ObjectID = objectID; + preSound.DataBlock[0].OwnerID = ownerID; + preSound.DataBlock[0].SoundID = soundID; + preSound.Header.Zerocoded = true; + OutPacket(preSound, ThrottleOutPacketType.Task); + } + + public void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, byte flags) + { + AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound); + sound.DataBlock.SoundID = soundID; + sound.DataBlock.ObjectID = objectID; + sound.DataBlock.OwnerID = ownerID; + sound.DataBlock.Gain = gain; + sound.DataBlock.Flags = flags; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) + { + SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); + sound.SoundData.SoundID = soundID; + sound.SoundData.OwnerID = ownerID; + sound.SoundData.ObjectID = objectID; + sound.SoundData.ParentID = parentID; + sound.SoundData.Handle = handle; + sound.SoundData.Position = position; + sound.SoundData.Gain = gain; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendAttachedSoundGainChange(UUID objectID, float gain) + { + AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange); + sound.DataBlock.ObjectID = objectID; + sound.DataBlock.Gain = gain; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendSunPos(Vector3 Position, Vector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition) + { + // Viewers based on the Linden viwer code, do wacky things for oribital positions from Midnight to Sunrise + // So adjust for that + // Contributed by: Godfrey + + if (OrbitalPosition > m_sunPainDaHalfOrbitalCutoff) // things get weird from midnight to sunrise + { + OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff; + } + + + + SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); + viewertime.TimeInfo.SunDirection = Position; + viewertime.TimeInfo.SunAngVelocity = Velocity; + + // Sun module used to add 6 hours to adjust for linden sun hour, adding here + // to prevent existing code from breaking if it assumed that 6 hours were included. + // 21600 == 6 hours * 60 minutes * 60 Seconds + viewertime.TimeInfo.UsecSinceStart = CurrentTime + 21600; + + viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle; + viewertime.TimeInfo.SecPerYear = SecondsPerYear; + viewertime.TimeInfo.SunPhase = OrbitalPosition; + viewertime.Header.Reliable = false; + viewertime.Header.Zerocoded = true; + OutPacket(viewertime, ThrottleOutPacketType.Task); + } + + // Currently Deprecated + public void SendViewerTime(int phase) + { + /* + Console.WriteLine("SunPhase: {0}", phase); + SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); + //viewertime.TimeInfo.SecPerDay = 86400; + //viewertime.TimeInfo.SecPerYear = 31536000; + viewertime.TimeInfo.SecPerDay = 1000; + viewertime.TimeInfo.SecPerYear = 365000; + viewertime.TimeInfo.SunPhase = 1; + int sunPhase = (phase + 2) / 2; + if ((sunPhase < 6) || (sunPhase > 36)) + { + viewertime.TimeInfo.SunDirection = new Vector3(0f, 0.8f, -0.8f); + Console.WriteLine("sending night"); + } + else + { + if (sunPhase < 12) + { + sunPhase = 12; + } + sunPhase = sunPhase - 12; + + float yValue = 0.1f * (sunPhase); + Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); + if (yValue > 1.2f) + { + yValue = yValue - 1.2f; + } + + yValue = Util.Clip(yValue, 0, 1); + + if (sunPhase < 14) + { + yValue = 1 - yValue; + } + if (sunPhase < 12) + { + yValue *= -1; + } + viewertime.TimeInfo.SunDirection = new Vector3(0f, yValue, 0.3f); + Console.WriteLine("sending sun update " + yValue); + } + viewertime.TimeInfo.SunAngVelocity = new Vector3(0, 0.0f, 10.0f); + viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); + viewertime.Header.Reliable = false; + OutPacket(viewertime, ThrottleOutPacketType.Task); + */ + } + + public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) + { + ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect); + packet.Header.Reliable = false; + packet.Header.Zerocoded = true; + + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + + packet.Effect = effectBlocks; + + // OutPacket(packet, ThrottleOutPacketType.State); + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, + string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL, + UUID partnerID) + { + AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply); + avatarReply.AgentData.AgentID = AgentId; + avatarReply.AgentData.AvatarID = avatarID; + if (aboutText != null) + avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText); + else + avatarReply.PropertiesData.AboutText = Utils.EmptyBytes; + avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn); + avatarReply.PropertiesData.CharterMember = charterMember; + if (flAbout != null) + avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout); + else + avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes; + avatarReply.PropertiesData.Flags = flags; + avatarReply.PropertiesData.FLImageID = flImageID; + avatarReply.PropertiesData.ImageID = imageID; + avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL); + avatarReply.PropertiesData.PartnerID = partnerID; + 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())); + + //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); + } + } + + 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); + } + + public void SendGroupMembership(GroupMembershipData[] GroupMembership) + { + m_groupPowers.Clear(); + + 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; + + 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 = Util.StringToBytes256(GroupMembership[i].GroupName); + Group.GroupPowers = GroupMembership[i].GroupPowers; + Groups[i] = Group; + + + } + Groupupdate.GroupData = Groups; + Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock(); + Groupupdate.AgentData.AgentID = AgentId; + OutPacket(Groupupdate, ThrottleOutPacketType.Task); + + 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); + } + } + + + 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 = Util.StringToBytes256(GroupName); + uidnameblock[0] = uidnamebloc; + pack.UUIDNameBlock = uidnameblock; + OutPacket(pack, ThrottleOutPacketType.Task); + } + + 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 = Util.StringToBytes256(lsrpia[i].TaskName); + lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName); + lsrepdba[i] = lsrepdb; + } + lsrp.ReportData = lsrepdba; + OutPacket(lsrp, ThrottleOutPacketType.Task); + } + + 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; + + OutPacket(scriptRunningReply, ThrottleOutPacketType.Task); + } + + public void SendAsset(AssetRequestToClient req) + { + if (req.AssetInf.Data == null) + { + m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", + req.AssetInf.ID, req.AssetInf.Metadata.ContentType); + return; + } + + //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); + + 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; + + while (processedLength < req.AssetInf.Data.Length) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = packetNumber; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + + 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); + + TransferPacket.TransferData.Data = chunk; + + // 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); + + processedLength += chunkSize; + packetNumber++; + } + } + } + + 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) + { + float dwell = 0.0f; + IDwellModule dwellModule = m_scene.RequestModuleInterface(); + if (dwellModule != null) + dwell = dwellModule.GetDwell(land.GlobalID); + 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)( + (info.AccessLevel > 13 ? (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 + x; + reply.Data.GlobalY = info.RegionLocY + y; + reply.Data.GlobalZ = pos.Z; + reply.Data.SimName = Utils.StringToBytes(info.RegionName); + reply.Data.SnapshotID = land.SnapshotID; + reply.Data.Dwell = dwell; + reply.Data.SalePrice = land.SalePrice; + reply.Data.AuctionID = (int)land.AuctionID; + + OutPacket(reply, ThrottleOutPacketType.Land); + } + + public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) + { + ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest); + + packet.Data.ObjectName = Utils.StringToBytes(objName); + packet.Data.SimName = Utils.StringToBytes(simName); + packet.Data.SimPosition = pos; + packet.Data.LookAt = lookAt; + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) + { + DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + + packet.AgentData.AgentID = AgentId; + + packet.QueryData[0].QueryID = queryID; + + DirPlacesReplyPacket.QueryRepliesBlock[] replies = + new DirPlacesReplyPacket.QueryRepliesBlock[0]; + DirPlacesReplyPacket.StatusDataBlock[] status = + new DirPlacesReplyPacket.StatusDataBlock[0]; + + packet.QueryReplies = replies; + packet.StatusData = status; + + foreach (DirPlacesReplyData d in data) + { + int idx = replies.Length; + Array.Resize(ref replies, idx + 1); + Array.Resize(ref status, idx + 1); + + replies[idx] = new DirPlacesReplyPacket.QueryRepliesBlock(); + status[idx] = new DirPlacesReplyPacket.StatusDataBlock(); + replies[idx].ParcelID = d.parcelID; + replies[idx].Name = Utils.StringToBytes(d.name); + replies[idx].ForSale = d.forSale; + replies[idx].Auction = d.auction; + replies[idx].Dwell = d.dwell; + status[idx].Status = d.Status; + + packet.QueryReplies = replies; + packet.StatusData = status; + + if (packet.Length >= 1000) + { + OutPacket(packet, ThrottleOutPacketType.Task); + + packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + + packet.AgentData.AgentID = AgentId; + + packet.QueryData[0].QueryID = queryID; + + replies = new DirPlacesReplyPacket.QueryRepliesBlock[0]; + status = new DirPlacesReplyPacket.StatusDataBlock[0]; + } + } + + if (replies.Length > 0 || data.Length == 0) + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) + { + DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply); + + packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock(); + packet.QueryData.QueryID = queryID; + + 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++; + } + + 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]; + + packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[ + data.Length]; + + 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++; + } + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) + { + 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) + { + 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 SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) + { + 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) + { + 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 SendDirLandReply(UUID queryID, DirLandReplyData[] data) + { + DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply); + + packet.AgentData = new DirLandReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + 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 SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) + { + 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 SendEventInfoReply(EventData data) + { + EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply); + + packet.AgentData = new EventInfoReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + + 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 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); + + } + + 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); + } + + 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); + } + + 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 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); + } + + public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) + { + OSDMap llsd = new OSDMap(3); + OSDArray AgentData = new OSDArray(1); + OSDMap AgentDataMap = new OSDMap(1); + AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId)); + AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID)); + AgentData.Add(AgentDataMap); + llsd.Add("AgentData", AgentData); + OSDArray GroupData = new OSDArray(data.Length); + OSDArray NewGroupData = new OSDArray(data.Length); + foreach (GroupMembershipData m in data) + { + OSDMap GroupDataMap = new OSDMap(6); + OSDMap NewGroupDataMap = new OSDMap(1); + GroupDataMap.Add("GroupPowers", OSD.FromULong(m.GroupPowers)); + GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices)); + GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle)); + GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID)); + GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName)); + GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture)); + NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile)); + GroupData.Add(GroupDataMap); + NewGroupData.Add(NewGroupDataMap); + } + llsd.Add("GroupData", GroupData); + llsd.Add("NewGroupData", NewGroupData); + + IEventQueue eq = this.Scene.RequestModuleInterface(); + if (eq != null) + { + eq.Enqueue(BuildEvent("AvatarGroupsReply", llsd), this.AgentId); + } + } + + public void SendJoinGroupReply(UUID groupID, bool success) + { + JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); + + p.AgentData = new JoinGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; + + p.GroupData = new JoinGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; + + OutPacket(p, ThrottleOutPacketType.Task); + } + + public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) + { + EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply); + + p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = agentID; + + p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + + p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock(); + p.EjectData.Success = success; + + OutPacket(p, ThrottleOutPacketType.Task); + } + + public void SendLeaveGroupReply(UUID groupID, bool success) + { + LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply); + + p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock(); + p.AgentData.AgentID = AgentId; + + p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock(); + p.GroupData.GroupID = groupID; + p.GroupData.Success = success; + + OutPacket(p, 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); + + 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 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); + + cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock(); + cr.AgentData.AgentID = AgentId; + + 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 SendAgentDropGroup(UUID groupID) + { + 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 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); + } + + 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) + { + ap.Data[i] = new AvatarPicksReplyPacket.DataBlock(); + ap.Data[i].PickID = pick.Key; + ap.Data[i].PickName = Utils.StringToBytes(pick.Value); + i++; + } + + OutPacket(ap, ThrottleOutPacketType.Task); + } + + public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + { + 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]; + + 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 SendParcelDwellReply(int localID, UUID parcelID, float dwell) + { + 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 SendUserInfoReply(bool imViaEmail, bool visible, string email) + { + 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 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); + } + + #endregion Scene/Avatar to Client + + // Gesture + + #region Appearance/ Wearables Methods + + 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; + + int count = 0; + for (int i = 0; i < wearables.Length; i++) + count += wearables[i].Count; + + // TODO: don't create new blocks if recycling an old packet + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + int idx = 0; + for (int i = 0; i < wearables.Length; i++) + { + for (int j = 0; j < wearables[i].Count; j++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = wearables[i][j].AssetID; + awb.ItemID = wearables[i][j].ItemID; + aw.WearableData[idx] = awb; + idx++; + +// m_log.DebugFormat( +// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", +// awb.ItemID, awb.AssetID, i, Name); + } + } + + OutPacket(aw, ThrottleOutPacketType.Task); + } + + public void SendAppearance(UUID agentID, byte[] visualParams, byte[] 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; + + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) + { + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; + } + + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); + OutPacket(avp, ThrottleOutPacketType.Task); + } + + public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + { + //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) + { + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; + + ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); + if (objectIDs[i].Equals(sourceAgentId)) + ani.AnimationSourceList[i].ObjectID = UUID.Zero; + else + ani.AnimationSourceList[i].ObjectID = objectIDs[i]; + } + ani.Header.Reliable = false; + OutPacket(ani, ThrottleOutPacketType.Task); + } + + #endregion + + #region Avatar Packet/Data Sending Methods + + /// + /// Send an ObjectUpdate packet with information about an avatar + /// + public void SendAvatarDataImmediate(ISceneEntity avatar) + { + ScenePresence presence = avatar as ScenePresence; + if (presence == null) + return; + + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + objupdate.Header.Zerocoded = true; + + objupdate.RegionData.RegionHandle = presence.RegionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); + + OutPacket(objupdate, ThrottleOutPacketType.Task); + + // We need to record the avatar local id since the root prim of an attachment points to this. +// m_attachmentsSent.Add(avatar.LocalId); + } + + 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); + loc.Header.Reliable = false; + + // Each packet can only hold around 60 avatar positions and the client clears the mini-map each time + // a CoarseLocationUpdate packet is received. Oh well. + int total = Math.Min(CoarseLocations.Count, 60); + + CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock(); + + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; + + int selfindex = -1; + 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; + + lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f); + loc.Location[i] = lb; + loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); + loc.AgentData[i].AgentID = users[i]; + if (users[i] == AgentId) + selfindex = i; + } + + ib.You = (short)selfindex; + ib.Prey = -1; + loc.Index = ib; + + OutPacket(loc, ThrottleOutPacketType.Task); + } + + #endregion Avatar Packet/Data Sending Methods + + #region Primitive Packet/Data Sending Methods + + + /// + /// Generate one of the object update packets based on PrimUpdateFlags + /// and broadcast the packet to clients + /// + public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) + { + //double priority = m_prioritizer.GetUpdatePriority(this, entity); + uint priority = m_prioritizer.GetUpdatePriority(this, entity); + + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); + } + + /// + /// Requeue an EntityUpdate when it was not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdate(EntityUpdate update) + { + // If the update exists in priority queue, it will be updated. + // If it does not exist then it will be added with the current (rather than its original) priority + uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); + + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Enqueue(priority, update); + } + + /// + /// Requeue a list of EntityUpdates when they were not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) + { + // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); + + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state and priority. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); + + // Count this as a resent packet since we are going to requeue all of the updates contained in it + Interlocked.Increment(ref m_udpClient.PacketsResent); + + foreach (EntityUpdate update in updates) + ResendPrimUpdate(update); + } + + private void ProcessEntityUpdates(int maxUpdates) + { + OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> compressedUpdateBlocks = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> terseUpdateBlocks = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy>(); + + OpenSim.Framework.Lazy> objectUpdates = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> compressedUpdates = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> terseUpdates = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> terseAgentUpdates = new OpenSim.Framework.Lazy>(); + + // Check to see if this is a flush + if (maxUpdates <= 0) + { + maxUpdates = Int32.MaxValue; + } + + int updatesThisCall = 0; + + // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race + // condition where a kill can be processed before an out-of-date update for the same object. + lock (m_killRecord) + { + float avgTimeDilation = 1.0f; + IEntityUpdate iupdate; + Int32 timeinqueue; // this is just debugging code & can be dropped later + + while (updatesThisCall < maxUpdates) + { + lock (m_entityUpdates.SyncRoot) + if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue)) + break; + + EntityUpdate update = (EntityUpdate)iupdate; + + avgTimeDilation += update.TimeDilation; + avgTimeDilation *= 0.5f; + + if (update.Entity is SceneObjectPart) + { + SceneObjectPart part = (SceneObjectPart)update.Entity; + + // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client + // will never receive an update after a prim kill. Even then, keeping the kill record may be a good + // safety measure. + // + // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update + // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs + // updates and kills on different threads with different scheduling strategies, hence this protection. + // + // This doesn't appear to apply to child prims - a client will happily ignore these updates + // after the root prim has been deleted. + if (m_killRecord.Contains(part.LocalId)) + { + // m_log.WarnFormat( + // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", + // part.LocalId, Name); + continue; + } + + if (part.ParentGroup.IsAttachment && m_disableFacelights) + { + if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && + part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand) + { + part.Shape.LightEntry = false; + } + } + } + + ++updatesThisCall; + + #region UpdateFlags to packet type conversion + + PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; + + bool canUseCompressed = true; + bool canUseImproved = true; + + // Compressed object updates only make sense for LL primitives + if (!(update.Entity is SceneObjectPart)) + { + canUseCompressed = false; + } + + if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) + { + canUseCompressed = false; + canUseImproved = false; + } + else + { + if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || + updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || + updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || + updateFlags.HasFlag(PrimUpdateFlags.Joint)) + { + canUseCompressed = false; + } + + if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || + updateFlags.HasFlag(PrimUpdateFlags.ParentID) || + updateFlags.HasFlag(PrimUpdateFlags.Scale) || + updateFlags.HasFlag(PrimUpdateFlags.PrimData) || + updateFlags.HasFlag(PrimUpdateFlags.Text) || + updateFlags.HasFlag(PrimUpdateFlags.NameValue) || + updateFlags.HasFlag(PrimUpdateFlags.ExtraData) || + updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) || + updateFlags.HasFlag(PrimUpdateFlags.Sound) || + updateFlags.HasFlag(PrimUpdateFlags.Particles) || + updateFlags.HasFlag(PrimUpdateFlags.Material) || + updateFlags.HasFlag(PrimUpdateFlags.ClickAction) || + updateFlags.HasFlag(PrimUpdateFlags.MediaURL) || + updateFlags.HasFlag(PrimUpdateFlags.Joint)) + { + canUseImproved = false; + } + } + + #endregion UpdateFlags to packet type conversion + + #region Block Construction + + // TODO: Remove this once we can build compressed updates + canUseCompressed = false; + + if (!canUseImproved && !canUseCompressed) + { + if (update.Entity is ScenePresence) + { + objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); + objectUpdates.Value.Add(update); + } + else + { + objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); + objectUpdates.Value.Add(update); + } + } + else if (!canUseImproved) + { + compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); + compressedUpdates.Value.Add(update); + } + else + { + if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) + { + // Self updates go into a special list + terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + terseAgentUpdates.Value.Add(update); + } + else + { + // Everything else goes here + terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + terseUpdates.Value.Add(update); + } + } + + #endregion Block Construction + } + + + #region Packet Sending + ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); + + if (terseAgentUpdateBlocks.IsValueCreated) + { + List blocks = terseAgentUpdateBlocks.Value; + + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + // If any of the packets created from this call go unacknowledged, all of the updates will be resent + OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); + } + + if (objectUpdateBlocks.IsValueCreated) + { + List blocks = objectUpdateBlocks.Value; + + ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + // If any of the packets created from this call go unacknowledged, all of the updates will be resent + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); }); + } + + if (compressedUpdateBlocks.IsValueCreated) + { + List blocks = compressedUpdateBlocks.Value; + + ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + // If any of the packets created from this call go unacknowledged, all of the updates will be resent + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); }); + } + + if (terseUpdateBlocks.IsValueCreated) + { + List blocks = terseUpdateBlocks.Value; + + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + // If any of the packets created from this call go unacknowledged, all of the updates will be resent + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); + } + } + + #endregion Packet Sending + } + + public void ReprioritizeUpdates() + { + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Reprioritize(UpdatePriorityHandler); + } + + private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity) + { + if (entity != null) + { + priority = m_prioritizer.GetUpdatePriority(this, entity); + return true; + } + + return false; + } + + public void FlushPrimUpdates() + { + m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); + + while (m_entityUpdates.Count > 0) + ProcessEntityUpdates(-1); + } + + #endregion Primitive Packet/Data Sending Methods + + // These are used to implement an adaptive backoff in the number + // of updates converted to packets. Since we don't want packets + // to sit in the queue with old data, only convert enough updates + // to packets that can be sent in 200ms. + private Int32 m_LastQueueFill = 0; + private Int32 m_maxUpdates = 0; + + void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) + { + if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) + { + if (m_maxUpdates == 0 || m_LastQueueFill == 0) + { + m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; + } + else + { + if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200) + m_maxUpdates += 5; + else + m_maxUpdates = m_maxUpdates >> 1; + } + m_maxUpdates = Util.Clamp(m_maxUpdates,10,500); + m_LastQueueFill = Util.EnvironmentTickCount(); + + if (m_entityUpdates.Count > 0) + ProcessEntityUpdates(m_maxUpdates); + + if (m_entityProps.Count > 0) + ProcessEntityPropertyRequests(m_maxUpdates); + } + + if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) + { + ProcessTextureRequests(); + } + } + + void ProcessTextureRequests() + { + if (m_imageManager != null) + m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); + } + + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) + { + 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 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); + } + + 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); + } + + 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 (ImageSize > 0) + im.ImageID.Size = ImageSize; + + im.ImageData.Data = ImageData; + im.ImageID.Codec = imageCodec; + im.Header.Zerocoded = true; + OutPacket(im, ThrottleOutPacketType.Texture); + } + + 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(im, ThrottleOutPacketType.Texture); + } + + public void SendImageNotFound(UUID imageid) + { + ImageNotInDatabasePacket notFoundPacket + = (ImageNotInDatabasePacket)PacketPool.Instance.GetPacket(PacketType.ImageNotInDatabase); + + notFoundPacket.ImageID.ID = imageid; + + OutPacket(notFoundPacket, ThrottleOutPacketType.Texture); + } + + public void SendShutdownConnectionNotice() + { + OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); + } + + 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; + + pack.Header.Reliable = false; + + OutPacket(pack, ThrottleOutPacketType.Task); + } + + private class ObjectPropertyUpdate : IEntityUpdate + { + internal bool SendFamilyProps; + internal bool SendObjectProps; + + public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj) + : base(entity,flags) + { + SendFamilyProps = sendfam; + SendObjectProps = sendobj; + } + public void Update(ObjectPropertyUpdate update) + { + SendFamilyProps = SendFamilyProps || update.SendFamilyProps; + SendObjectProps = SendObjectProps || update.SendObjectProps; + // other properties may need to be updated by base class + base.Update(update); + } + } + + public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags) + { + uint priority = 0; // time based ordering only + lock (m_entityProps.SyncRoot) + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); + } + + private void ResendPropertyUpdate(ObjectPropertyUpdate update) + { + uint priority = 0; + lock (m_entityProps.SyncRoot) + m_entityProps.Enqueue(priority, update); + } + + private void ResendPropertyUpdates(List updates, OutgoingPacket oPacket) + { + // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime); + + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); + + // Count this as a resent packet since we are going to requeue all of the updates contained in it + Interlocked.Increment(ref m_udpClient.PacketsResent); + + foreach (ObjectPropertyUpdate update in updates) + ResendPropertyUpdate(update); + } + + public void SendObjectPropertiesReply(ISceneEntity entity) + { + uint priority = 0; // time based ordering only + lock (m_entityProps.SyncRoot) + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); + } + + private void ProcessEntityPropertyRequests(int maxUpdates) + { + OpenSim.Framework.Lazy> objectFamilyBlocks = + new OpenSim.Framework.Lazy>(); + + OpenSim.Framework.Lazy> objectPropertiesBlocks = + new OpenSim.Framework.Lazy>(); + + OpenSim.Framework.Lazy> familyUpdates = + new OpenSim.Framework.Lazy>(); + + OpenSim.Framework.Lazy> propertyUpdates = + new OpenSim.Framework.Lazy>(); + + IEntityUpdate iupdate; + Int32 timeinqueue; // this is just debugging code & can be dropped later + + int updatesThisCall = 0; + while (updatesThisCall < m_maxUpdates) + { + lock (m_entityProps.SyncRoot) + if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) + break; + + ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; + if (update.SendFamilyProps) + { + if (update.Entity is SceneObjectPart) + { + SceneObjectPart sop = (SceneObjectPart)update.Entity; + ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); + objectFamilyBlocks.Value.Add(objPropDB); + familyUpdates.Value.Add(update); + } + } + + if (update.SendObjectProps) + { + if (update.Entity is SceneObjectPart) + { + SceneObjectPart sop = (SceneObjectPart)update.Entity; + ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); + objectPropertiesBlocks.Value.Add(objPropDB); + propertyUpdates.Value.Add(update); + } + } + + updatesThisCall++; + } + + + // Int32 ppcnt = 0; + // Int32 pbcnt = 0; + + if (objectPropertiesBlocks.IsValueCreated) + { + List blocks = objectPropertiesBlocks.Value; + List updates = propertyUpdates.Value; + + ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + + packet.Header.Zerocoded = true; + + // Pass in the delegate so that if this packet needs to be resent, we send the current properties + // of the object rather than the properties when the packet was created + OutPacket(packet, ThrottleOutPacketType.Task, true, + delegate(OutgoingPacket oPacket) + { + ResendPropertyUpdates(updates, oPacket); + }); + + // pbcnt += blocks.Count; + // ppcnt++; + } + + // Int32 fpcnt = 0; + // Int32 fbcnt = 0; + + if (objectFamilyBlocks.IsValueCreated) + { + List blocks = objectFamilyBlocks.Value; + + // one packet per object block... uggh... + for (int i = 0; i < blocks.Count; i++) + { + ObjectPropertiesFamilyPacket packet = + (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); + + packet.ObjectData = blocks[i]; + packet.Header.Zerocoded = true; + + // Pass in the delegate so that if this packet needs to be resent, we send the current properties + // of the object rather than the properties when the packet was created + List updates = new List(); + updates.Add(familyUpdates.Value[i]); + OutPacket(packet, ThrottleOutPacketType.Task, true, + delegate(OutgoingPacket oPacket) + { + ResendPropertyUpdates(updates, oPacket); + }); + + // fpcnt++; + // fbcnt++; + } + + } + + // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt); + // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt); + } + + private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags) + { + ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); + + block.RequestFlags = requestFlags; + block.ObjectID = sop.UUID; + if (sop.OwnerID == sop.GroupID) + block.OwnerID = UUID.Zero; + else + block.OwnerID = sop.OwnerID; + block.GroupID = sop.GroupID; + block.BaseMask = sop.BaseMask; + block.OwnerMask = sop.OwnerMask; + block.GroupMask = sop.GroupMask; + block.EveryoneMask = sop.EveryoneMask; + block.NextOwnerMask = sop.NextOwnerMask; + + // TODO: More properties are needed in SceneObjectPart! + block.OwnershipCost = sop.OwnershipCost; + block.SaleType = sop.ObjectSaleType; + block.SalePrice = sop.SalePrice; + block.Category = sop.Category; + block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right? + block.Name = Util.StringToBytes256(sop.Name); + block.Description = Util.StringToBytes256(sop.Description); + + return block; + } + + private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) + { + //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + // TODO: don't create new blocks if recycling an old packet + + ObjectPropertiesPacket.ObjectDataBlock block = + new ObjectPropertiesPacket.ObjectDataBlock(); + + block.ObjectID = sop.UUID; + block.Name = Util.StringToBytes256(sop.Name); + block.Description = Util.StringToBytes256(sop.Description); + + block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds + block.CreatorID = sop.CreatorID; + block.GroupID = sop.GroupID; + block.LastOwnerID = sop.LastOwnerID; + if (sop.OwnerID == sop.GroupID) + block.OwnerID = UUID.Zero; + else + block.OwnerID = sop.OwnerID; + + block.ItemID = sop.FromUserInventoryItemID; + block.FolderID = UUID.Zero; // sop.FromFolderID ?? + block.FromTaskID = UUID.Zero; // ??? + block.InventorySerial = (short)sop.InventorySerial; + + SceneObjectPart root = sop.ParentGroup.RootPart; + + block.TouchName = Util.StringToBytes256(root.TouchName); + block.TextureID = new byte[0]; // TextureID ??? + block.SitName = Util.StringToBytes256(root.SitName); + block.OwnerMask = root.OwnerMask; + block.NextOwnerMask = root.NextOwnerMask; + block.GroupMask = root.GroupMask; + block.EveryoneMask = root.EveryoneMask; + block.BaseMask = root.BaseMask; + block.SaleType = root.ObjectSaleType; + block.SalePrice = root.SalePrice; + + return block; + } + + #region Estate Data Sending Methods + + 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; + } + + public void SendEstateList(UUID invoice, int code, UUID[] Data, 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"); + + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + Data.Length]; + + for (int i = 0; i < (6 + Data.Length); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; + + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(code.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("0"); j++; + + j = 2; // Agents + if ((code & 2) != 0) + j = 3; // Groups + if ((code & 8) != 0) + j = 5; // Managers + + returnblock[j].Parameter = Utils.StringToBytes(Data.Length.ToString()); + j = 6; + + for (int i = 0; i < Data.Length; i++) + { + returnblock[j].Parameter = Data[i].GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = true; + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) + { + List BannedUsers = 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); + } + + 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"); + + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + + 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++; + + foreach (UUID banned in BannedUsers) + { + returnblock[j].Parameter = banned.GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = false; + OutPacket(packet, ThrottleOutPacketType.Task); + } + + 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 = Util.StringToBytes256(args.regionType); + rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; + + rinfopack.HasVariableBlocks = true; + rinfopack.RegionInfo = rinfoblk; + rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); + rinfopack.AgentData.AgentID = AgentId; + rinfopack.AgentData.SessionID = SessionId; + + + OutPacket(rinfopack, ThrottleOutPacketType.Task); + } + + public void SendEstateCovenantInformation(UUID covenant) + { +// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name); + + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); + EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); + edata.CovenantID = covenant; + edata.CovenantTimestamp = 0; + edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); + einfopack.Data = edata; + OutPacket(einfopack, ThrottleOutPacketType.Task); + } + + public void SendDetailedEstateData( + UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, + UUID covenant, string abuseEmail, UUID estateOwner) + { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant); + + 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++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + + //Sending Estate Settings + returnblock[0].Parameter = Utils.StringToBytes(estateName); + returnblock[1].Parameter = Utils.StringToBytes(estateOwner.ToString()); + returnblock[2].Parameter = Utils.StringToBytes(estateID.ToString()); + + 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); + + packet.ParamList = returnblock; + packet.Header.Reliable = false; + //m_log.Debug("[ESTATE]: SIM--->" + packet.ToString()); + OutPacket(packet, ThrottleOutPacketType.Task); + } + + #endregion + + #region Land Data Sending Methods + + 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, ILandObject lo, + float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + { +// m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name); + + LandData landData = lo.LandData; + + ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage(); + + updateMessage.AABBMax = landData.AABBMax; + updateMessage.AABBMin = landData.AABBMin; + updateMessage.Area = landData.Area; + updateMessage.AuctionID = landData.AuctionID; + updateMessage.AuthBuyerID = landData.AuthBuyerID; + updateMessage.Bitmap = landData.Bitmap; + updateMessage.Desc = landData.Description; + updateMessage.Category = landData.Category; + updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate); + updateMessage.ClaimPrice = landData.ClaimPrice; + updateMessage.GroupID = landData.GroupID; + updateMessage.IsGroupOwned = landData.IsGroupOwned; + updateMessage.LandingType = (LandingType) landData.LandingType; + updateMessage.LocalID = landData.LocalID; + + if (landData.Area > 0) + { + updateMessage.MaxPrims = parcelObjectCapacity; + } + else + { + updateMessage.MaxPrims = 0; + } + + updateMessage.MediaAutoScale = Convert.ToBoolean(landData.MediaAutoScale); + updateMessage.MediaID = landData.MediaID; + updateMessage.MediaURL = landData.MediaURL; + updateMessage.MusicURL = landData.MusicURL; + updateMessage.Name = landData.Name; + updateMessage.OtherCleanTime = landData.OtherCleanTime; + updateMessage.OtherCount = 0; //TODO: Unimplemented + updateMessage.OwnerID = landData.OwnerID; + updateMessage.ParcelFlags = (ParcelFlags) landData.Flags; + updateMessage.ParcelPrimBonus = simObjectBonusFactor; + updateMessage.PassHours = landData.PassHours; + updateMessage.PassPrice = landData.PassPrice; + updateMessage.PublicCount = 0; //TODO: Unimplemented + + updateMessage.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0; + updateMessage.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0; + + //updateMessage.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0; + //updateMessage.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0; + + updateMessage.RentPrice = 0; + updateMessage.RequestResult = (ParcelResult) request_result; + updateMessage.SalePrice = landData.SalePrice; + updateMessage.SelfCount = 0; //TODO: Unimplemented + updateMessage.SequenceID = sequence_id; + + if (landData.SimwideArea > 0) + { + int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + updateMessage.SimWideMaxPrims = simulatorCapacity; + } + else + { + updateMessage.SimWideMaxPrims = 0; + } + + updateMessage.SnapSelection = snap_selection; + updateMessage.SnapshotID = landData.SnapshotID; + updateMessage.Status = (ParcelStatus) landData.Status; + updateMessage.UserLocation = landData.UserLocation; + updateMessage.UserLookAt = landData.UserLookAt; + + updateMessage.MediaType = landData.MediaType; + updateMessage.MediaDesc = landData.MediaDescription; + updateMessage.MediaWidth = landData.MediaWidth; + updateMessage.MediaHeight = landData.MediaHeight; + updateMessage.MediaLoop = landData.MediaLoop; + updateMessage.ObscureMusic = landData.ObscureMusic; + updateMessage.ObscureMedia = landData.ObscureMedia; + + IPrimCounts pc = lo.PrimCounts; + updateMessage.OwnerPrims = pc.Owner; + updateMessage.GroupPrims = pc.Group; + updateMessage.OtherPrims = pc.Others; + updateMessage.SelectedPrims = pc.Selected; + updateMessage.TotalPrims = pc.Total; + updateMessage.SimWideTotalPrims = pc.Simulator; + + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + eq.ParcelProperties(updateMessage, this.AgentId); + } + else + { + m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data."); + } + } + catch (Exception ex) + { + m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString()); + } + } + + 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; + + 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); + } + + replyPacket.List = list.ToArray(); + replyPacket.Header.Zerocoded = true; + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } + + public void SendForceClientSelectObjects(List ObjectIDs) + { + m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); + + 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 (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); + } + } + + 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 SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) + { + int notifyCount = ownersAndCount.Count; + ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); + + 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; + } + + 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]; + + if (land.GroupID == owner || groups.Contains(owner)) + dataBlock[num].IsGroupOwned = true; + + dataBlock[num].OnlineStatus = true; //TODO: fix me later + dataBlock[num].OwnerID = owner; + + num++; + + if (num >= notifyCount) + { + break; + } + } + + pack.Data = dataBlock; + } + else + { + pack.Data = new ParcelObjectOwnersReplyPacket.DataBlock[0]; + } + pack.Header.Zerocoded = true; + this.OutPacket(pack, ThrottleOutPacketType.Task); + } + + #endregion + + #region Helper Methods + + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture) + { + #region ScenePresence/SOP Handling + + bool avatar = (entity is ScenePresence); + uint localID = entity.LocalId; + uint attachPoint; + Vector4 collisionPlane; + Vector3 position, velocity, acceleration, angularVelocity; + Quaternion rotation; + byte[] textureEntry; + + if (entity is ScenePresence) + { + ScenePresence presence = (ScenePresence)entity; + + attachPoint = 0; + collisionPlane = presence.CollisionPlane; + position = presence.OffsetPosition; + velocity = presence.Velocity; + acceleration = Vector3.Zero; + angularVelocity = Vector3.Zero; + rotation = presence.Rotation; + + if (sendTexture) + textureEntry = presence.Appearance.Texture.GetBytes(); + else + textureEntry = null; + } + else + { + SceneObjectPart part = (SceneObjectPart)entity; + + attachPoint = part.AttachmentPoint; + collisionPlane = Vector4.Zero; + position = part.RelativePosition; + velocity = part.Velocity; + acceleration = part.Acceleration; + angularVelocity = part.AngularVelocity; + rotation = part.RotationOffset; + + if (sendTexture) + textureEntry = part.Shape.TextureEntry; + else + textureEntry = null; + } + + #endregion ScenePresence/SOP Handling + + int pos = 0; + byte[] data = new byte[(avatar ? 60 : 44)]; + + // LocalID + Utils.UIntToBytes(localID, data, pos); + pos += 4; + + // Avatar/CollisionPlane + data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; + if (avatar) + { + data[pos++] = 1; + + if (collisionPlane == Vector4.Zero) + collisionPlane = Vector4.UnitW; + //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane); + collisionPlane.ToBytes(data, pos); + pos += 16; + } + else + { + ++pos; + } + + // Position + position.ToBytes(data, pos); + pos += 12; + + // Velocity + Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2; + + // Acceleration + Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2; + + // Rotation + Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2; + + // Angular Velocity + Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; + Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; + + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + block.Data = data; + + if (textureEntry != null && textureEntry.Length > 0) + { + byte[] teBytesFinal = new byte[textureEntry.Length + 4]; + + // Texture Length + Utils.IntToBytes(textureEntry.Length, textureEntry, 0); + // Texture + Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length); + + block.TextureEntry = teBytesFinal; + } + else + { + block.TextureEntry = Utils.EmptyBytes; + } + + return block; + } + + protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) + { + byte[] objectData = new byte[76]; + + data.CollisionPlane.ToBytes(objectData, 0); + data.OffsetPosition.ToBytes(objectData, 16); + //data.Velocity.ToBytes(objectData, 28); + //data.Acceleration.ToBytes(objectData, 40); + data.Rotation.ToBytes(objectData, 52); + //data.AngularVelocity.ToBytes(objectData, 64); + + ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); + + update.Data = Utils.EmptyBytes; + update.ExtraParams = new byte[1]; + update.FullID = data.UUID; + update.ID = data.LocalId; + update.Material = (byte)Material.Flesh; + update.MediaURL = Utils.EmptyBytes; + update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); + update.ObjectData = objectData; + update.ParentID = data.ParentID; + update.PathCurve = 16; + update.PathScaleX = 100; + update.PathScaleY = 100; + update.PCode = (byte)PCode.Avatar; + update.ProfileCurve = 1; + update.PSBlock = Utils.EmptyBytes; + update.Scale = new Vector3(0.45f, 0.6f, 1.9f); + update.Text = Utils.EmptyBytes; + update.TextColor = new byte[4]; + update.TextureAnim = Utils.EmptyBytes; + update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; + update.UpdateFlags = (uint)( + PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | + PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | + PrimFlags.ObjectOwnerModify); + + return update; + } + + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) + { + byte[] objectData = new byte[60]; + data.RelativePosition.ToBytes(objectData, 0); + data.Velocity.ToBytes(objectData, 12); + data.Acceleration.ToBytes(objectData, 24); + try + { + data.RotationOffset.ToBytes(objectData, 36); + } + catch (Exception e) + { + m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString()); + OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36); + } + data.AngularVelocity.ToBytes(objectData, 48); + + ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); + update.ClickAction = (byte)data.ClickAction; + update.CRC = 0; + update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes; + update.FullID = data.UUID; + update.ID = data.LocalId; + //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated + //update.JointPivot = Vector3.Zero; + //update.JointType = 0; + update.Material = data.Material; + update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim + if (data.IsAttachment) + { + update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); + update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16)); + } + else + { + update.NameValue = Utils.EmptyBytes; + update.State = data.Shape.State; + } + + update.ObjectData = objectData; + update.ParentID = data.ParentID; + update.PathBegin = data.Shape.PathBegin; + update.PathCurve = data.Shape.PathCurve; + update.PathEnd = data.Shape.PathEnd; + update.PathRadiusOffset = data.Shape.PathRadiusOffset; + update.PathRevolutions = data.Shape.PathRevolutions; + update.PathScaleX = data.Shape.PathScaleX; + update.PathScaleY = data.Shape.PathScaleY; + update.PathShearX = data.Shape.PathShearX; + update.PathShearY = data.Shape.PathShearY; + update.PathSkew = data.Shape.PathSkew; + update.PathTaperX = data.Shape.PathTaperX; + update.PathTaperY = data.Shape.PathTaperY; + update.PathTwist = data.Shape.PathTwist; + update.PathTwistBegin = data.Shape.PathTwistBegin; + update.PCode = data.Shape.PCode; + update.ProfileBegin = data.Shape.ProfileBegin; + update.ProfileCurve = data.Shape.ProfileCurve; + update.ProfileEnd = data.Shape.ProfileEnd; + update.ProfileHollow = data.Shape.ProfileHollow; + update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes; + update.TextColor = data.GetTextColor().GetBytes(false); + update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes; + update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; + update.Scale = data.Shape.Scale; + update.Text = Util.StringToBytes256(data.Text); + update.MediaURL = Util.StringToBytes256(data.MediaUrl); + + #region PrimFlags + + PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID); + + // Don't send the CreateSelected flag to everyone + flags &= ~PrimFlags.CreateSelected; + + if (recipientID == data.OwnerID) + { + if (data.CreateSelected) + { + // Only send this flag once, then unset it + flags |= PrimFlags.CreateSelected; + data.CreateSelected = false; + } + } + +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Constructing client update for part {0} {1} with flags {2}, localId {3}", +// data.Name, update.FullID, flags, update.ID); + + update.UpdateFlags = (uint)flags; + + #endregion PrimFlags + + if (data.Sound != UUID.Zero) + { + update.Sound = data.Sound; + update.OwnerID = data.OwnerID; + update.Gain = (float)data.SoundGain; + update.Radius = (float)data.SoundRadius; + update.Flags = data.SoundFlags; + } + + switch ((PCode)data.Shape.PCode) + { + case PCode.Grass: + case PCode.Tree: + case PCode.NewTree: + update.Data = new byte[] { data.Shape.State }; + break; + default: + update.Data = Utils.EmptyBytes; + break; + } + + return update; + } + + protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) + { + // TODO: Implement this + return null; + } + + 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 = Util.StringToBytes256(firstname); + packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname); + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + 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); + } + + #endregion + + /// + /// This is a different way of processing packets then ProcessInPacket + /// + protected virtual void RegisterLocalPacketHandlers() + { + AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); + AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); + AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); + AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); + AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); + AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); + AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); + AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); + AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); + AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); + AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); + AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); + AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFrendship); + AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); + AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); + AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); + AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); + AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); + AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); + AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); + AddLocalPacketHandler(PacketType.RezSingleAttachmentFromInv, HandlerRezSingleAttachmentFromInv); + AddLocalPacketHandler(PacketType.RezMultipleAttachmentsFromInv, HandleRezMultipleAttachmentsFromInv); + AddLocalPacketHandler(PacketType.DetachAttachmentIntoInv, HandleDetachAttachmentIntoInv); + AddLocalPacketHandler(PacketType.ObjectAttach, HandleObjectAttach); + AddLocalPacketHandler(PacketType.ObjectDetach, HandleObjectDetach); + AddLocalPacketHandler(PacketType.ObjectDrop, HandleObjectDrop); + AddLocalPacketHandler(PacketType.SetAlwaysRun, HandleSetAlwaysRun, false); + AddLocalPacketHandler(PacketType.CompleteAgentMovement, HandleCompleteAgentMovement); + AddLocalPacketHandler(PacketType.AgentAnimation, HandleAgentAnimation, false); + AddLocalPacketHandler(PacketType.AgentRequestSit, HandleAgentRequestSit); + AddLocalPacketHandler(PacketType.AgentSit, HandleAgentSit); + AddLocalPacketHandler(PacketType.SoundTrigger, HandleSoundTrigger); + AddLocalPacketHandler(PacketType.AvatarPickerRequest, HandleAvatarPickerRequest); + AddLocalPacketHandler(PacketType.AgentDataUpdateRequest, HandleAgentDataUpdateRequest); + AddLocalPacketHandler(PacketType.UserInfoRequest, HandleUserInfoRequest); + AddLocalPacketHandler(PacketType.UpdateUserInfo, HandleUpdateUserInfo); + AddLocalPacketHandler(PacketType.SetStartLocationRequest, HandleSetStartLocationRequest); + AddLocalPacketHandler(PacketType.AgentThrottle, HandleAgentThrottle, false); + AddLocalPacketHandler(PacketType.AgentPause, HandleAgentPause, false); + AddLocalPacketHandler(PacketType.AgentResume, HandleAgentResume, false); + AddLocalPacketHandler(PacketType.ForceScriptControlRelease, HandleForceScriptControlRelease); + AddLocalPacketHandler(PacketType.ObjectLink, HandleObjectLink); + AddLocalPacketHandler(PacketType.ObjectDelink, HandleObjectDelink); + AddLocalPacketHandler(PacketType.ObjectAdd, HandleObjectAdd); + AddLocalPacketHandler(PacketType.ObjectShape, HandleObjectShape); + AddLocalPacketHandler(PacketType.ObjectExtraParams, HandleObjectExtraParams); + AddLocalPacketHandler(PacketType.ObjectDuplicate, HandleObjectDuplicate); + AddLocalPacketHandler(PacketType.RequestMultipleObjects, HandleRequestMultipleObjects); + AddLocalPacketHandler(PacketType.ObjectSelect, HandleObjectSelect); + AddLocalPacketHandler(PacketType.ObjectDeselect, HandleObjectDeselect); + AddLocalPacketHandler(PacketType.ObjectPosition, HandleObjectPosition); + AddLocalPacketHandler(PacketType.ObjectScale, HandleObjectScale); + AddLocalPacketHandler(PacketType.ObjectRotation, HandleObjectRotation); + AddLocalPacketHandler(PacketType.ObjectFlagUpdate, HandleObjectFlagUpdate); + + // Handle ObjectImage (TextureEntry) updates synchronously, since when updating multiple prim faces at once, + // some clients will send out a separate ObjectImage packet for each face + AddLocalPacketHandler(PacketType.ObjectImage, HandleObjectImage, false); + + AddLocalPacketHandler(PacketType.ObjectGrab, HandleObjectGrab, false); + AddLocalPacketHandler(PacketType.ObjectGrabUpdate, HandleObjectGrabUpdate, false); + AddLocalPacketHandler(PacketType.ObjectDeGrab, HandleObjectDeGrab); + AddLocalPacketHandler(PacketType.ObjectSpinStart, HandleObjectSpinStart, false); + AddLocalPacketHandler(PacketType.ObjectSpinUpdate, HandleObjectSpinUpdate, false); + AddLocalPacketHandler(PacketType.ObjectSpinStop, HandleObjectSpinStop, false); + AddLocalPacketHandler(PacketType.ObjectDescription, HandleObjectDescription, false); + AddLocalPacketHandler(PacketType.ObjectName, HandleObjectName, false); + AddLocalPacketHandler(PacketType.ObjectPermissions, HandleObjectPermissions, false); + AddLocalPacketHandler(PacketType.Undo, HandleUndo, false); + AddLocalPacketHandler(PacketType.UndoLand, HandleLandUndo, false); + AddLocalPacketHandler(PacketType.Redo, HandleRedo, false); + AddLocalPacketHandler(PacketType.ObjectDuplicateOnRay, HandleObjectDuplicateOnRay); + AddLocalPacketHandler(PacketType.RequestObjectPropertiesFamily, HandleRequestObjectPropertiesFamily, false); + AddLocalPacketHandler(PacketType.ObjectIncludeInSearch, HandleObjectIncludeInSearch); + AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); + AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); + AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); + AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); + AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); + AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); + AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); + AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); + AddLocalPacketHandler(PacketType.ConfirmXferPacket, HandleConfirmXferPacket); + AddLocalPacketHandler(PacketType.AbortXfer, HandleAbortXfer); + AddLocalPacketHandler(PacketType.CreateInventoryFolder, HandleCreateInventoryFolder); + AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); + AddLocalPacketHandler(PacketType.MoveInventoryFolder, HandleMoveInventoryFolder); + AddLocalPacketHandler(PacketType.CreateInventoryItem, HandleCreateInventoryItem); + AddLocalPacketHandler(PacketType.LinkInventoryItem, HandleLinkInventoryItem); + AddLocalPacketHandler(PacketType.FetchInventory, HandleFetchInventory); + AddLocalPacketHandler(PacketType.FetchInventoryDescendents, HandleFetchInventoryDescendents); + AddLocalPacketHandler(PacketType.PurgeInventoryDescendents, HandlePurgeInventoryDescendents); + AddLocalPacketHandler(PacketType.UpdateInventoryItem, HandleUpdateInventoryItem); + AddLocalPacketHandler(PacketType.CopyInventoryItem, HandleCopyInventoryItem); + AddLocalPacketHandler(PacketType.MoveInventoryItem, HandleMoveInventoryItem); + AddLocalPacketHandler(PacketType.RemoveInventoryItem, HandleRemoveInventoryItem); + AddLocalPacketHandler(PacketType.RemoveInventoryFolder, HandleRemoveInventoryFolder); + AddLocalPacketHandler(PacketType.RemoveInventoryObjects, HandleRemoveInventoryObjects); + AddLocalPacketHandler(PacketType.RequestTaskInventory, HandleRequestTaskInventory); + AddLocalPacketHandler(PacketType.UpdateTaskInventory, HandleUpdateTaskInventory); + AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory); + AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory); + AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); + AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false); + AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); + AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false); + AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); + AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); + AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); + AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); + AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); + AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); + AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); + AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false); + AddLocalPacketHandler(PacketType.ParcelDivide, HandleParcelDivide); + AddLocalPacketHandler(PacketType.ParcelJoin, HandleParcelJoin); + AddLocalPacketHandler(PacketType.ParcelPropertiesUpdate, HandleParcelPropertiesUpdate); + AddLocalPacketHandler(PacketType.ParcelSelectObjects, HandleParcelSelectObjects); + AddLocalPacketHandler(PacketType.ParcelObjectOwnersRequest, HandleParcelObjectOwnersRequest); + AddLocalPacketHandler(PacketType.ParcelGodForceOwner, HandleParcelGodForceOwner); + AddLocalPacketHandler(PacketType.ParcelRelease, HandleParcelRelease); + AddLocalPacketHandler(PacketType.ParcelReclaim, HandleParcelReclaim); + AddLocalPacketHandler(PacketType.ParcelReturnObjects, HandleParcelReturnObjects); + AddLocalPacketHandler(PacketType.ParcelSetOtherCleanTime, HandleParcelSetOtherCleanTime); + AddLocalPacketHandler(PacketType.LandStatRequest, HandleLandStatRequest); + AddLocalPacketHandler(PacketType.ParcelDwellRequest, HandleParcelDwellRequest); + AddLocalPacketHandler(PacketType.EstateOwnerMessage, HandleEstateOwnerMessage); + AddLocalPacketHandler(PacketType.RequestRegionInfo, HandleRequestRegionInfo, false); + AddLocalPacketHandler(PacketType.EstateCovenantRequest, HandleEstateCovenantRequest); + AddLocalPacketHandler(PacketType.RequestGodlikePowers, HandleRequestGodlikePowers); + AddLocalPacketHandler(PacketType.GodKickUser, HandleGodKickUser); + AddLocalPacketHandler(PacketType.MoneyBalanceRequest, HandleMoneyBalanceRequest); + AddLocalPacketHandler(PacketType.EconomyDataRequest, HandleEconomyDataRequest); + AddLocalPacketHandler(PacketType.RequestPayPrice, HandleRequestPayPrice); + AddLocalPacketHandler(PacketType.ObjectSaleInfo, HandleObjectSaleInfo); + AddLocalPacketHandler(PacketType.ObjectBuy, HandleObjectBuy); + AddLocalPacketHandler(PacketType.GetScriptRunning, HandleGetScriptRunning); + AddLocalPacketHandler(PacketType.SetScriptRunning, HandleSetScriptRunning); + AddLocalPacketHandler(PacketType.ScriptReset, HandleScriptReset); + AddLocalPacketHandler(PacketType.ActivateGestures, HandleActivateGestures); + AddLocalPacketHandler(PacketType.DeactivateGestures, HandleDeactivateGestures); + AddLocalPacketHandler(PacketType.ObjectOwner, HandleObjectOwner); + AddLocalPacketHandler(PacketType.AgentFOV, HandleAgentFOV, false); + AddLocalPacketHandler(PacketType.ViewerStats, HandleViewerStats); + AddLocalPacketHandler(PacketType.MapItemRequest, HandleMapItemRequest, false); + AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); + AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); + AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); + AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); + AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); + AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); + AddLocalPacketHandler(PacketType.DirFindQuery, HandleDirFindQuery); + AddLocalPacketHandler(PacketType.DirLandQuery, HandleDirLandQuery); + AddLocalPacketHandler(PacketType.DirPopularQuery, HandleDirPopularQuery); + AddLocalPacketHandler(PacketType.DirClassifiedQuery, HandleDirClassifiedQuery); + AddLocalPacketHandler(PacketType.EventInfoRequest, HandleEventInfoRequest); + AddLocalPacketHandler(PacketType.OfferCallingCard, HandleOfferCallingCard); + AddLocalPacketHandler(PacketType.AcceptCallingCard, HandleAcceptCallingCard); + AddLocalPacketHandler(PacketType.DeclineCallingCard, HandleDeclineCallingCard); + AddLocalPacketHandler(PacketType.ActivateGroup, HandleActivateGroup); + AddLocalPacketHandler(PacketType.GroupTitlesRequest, HandleGroupTitlesRequest); + AddLocalPacketHandler(PacketType.GroupProfileRequest, HandleGroupProfileRequest); + AddLocalPacketHandler(PacketType.GroupMembersRequest, HandleGroupMembersRequest); + AddLocalPacketHandler(PacketType.GroupRoleDataRequest, HandleGroupRoleDataRequest); + AddLocalPacketHandler(PacketType.GroupRoleMembersRequest, HandleGroupRoleMembersRequest); + AddLocalPacketHandler(PacketType.CreateGroupRequest, HandleCreateGroupRequest); + AddLocalPacketHandler(PacketType.UpdateGroupInfo, HandleUpdateGroupInfo); + AddLocalPacketHandler(PacketType.SetGroupAcceptNotices, HandleSetGroupAcceptNotices); + AddLocalPacketHandler(PacketType.GroupTitleUpdate, HandleGroupTitleUpdate); + AddLocalPacketHandler(PacketType.ParcelDeedToGroup, HandleParcelDeedToGroup); + AddLocalPacketHandler(PacketType.GroupNoticesListRequest, HandleGroupNoticesListRequest); + AddLocalPacketHandler(PacketType.GroupNoticeRequest, HandleGroupNoticeRequest); + AddLocalPacketHandler(PacketType.GroupRoleUpdate, HandleGroupRoleUpdate); + AddLocalPacketHandler(PacketType.GroupRoleChanges, HandleGroupRoleChanges); + AddLocalPacketHandler(PacketType.JoinGroupRequest, HandleJoinGroupRequest); + AddLocalPacketHandler(PacketType.LeaveGroupRequest, HandleLeaveGroupRequest); + AddLocalPacketHandler(PacketType.EjectGroupMemberRequest, HandleEjectGroupMemberRequest); + AddLocalPacketHandler(PacketType.InviteGroupRequest, HandleInviteGroupRequest); + AddLocalPacketHandler(PacketType.StartLure, HandleStartLure); + AddLocalPacketHandler(PacketType.TeleportLureRequest, HandleTeleportLureRequest); + AddLocalPacketHandler(PacketType.ClassifiedInfoRequest, HandleClassifiedInfoRequest); + AddLocalPacketHandler(PacketType.ClassifiedInfoUpdate, HandleClassifiedInfoUpdate); + AddLocalPacketHandler(PacketType.ClassifiedDelete, HandleClassifiedDelete); + AddLocalPacketHandler(PacketType.ClassifiedGodDelete, HandleClassifiedGodDelete); + AddLocalPacketHandler(PacketType.EventGodDelete, HandleEventGodDelete); + AddLocalPacketHandler(PacketType.EventNotificationAddRequest, HandleEventNotificationAddRequest); + AddLocalPacketHandler(PacketType.EventNotificationRemoveRequest, HandleEventNotificationRemoveRequest); + AddLocalPacketHandler(PacketType.RetrieveInstantMessages, HandleRetrieveInstantMessages); + AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); + AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); + AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); + AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate); + AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate); + AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); + AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); + AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); + AddLocalPacketHandler(PacketType.RemoveMuteListEntry, HandleRemoveMuteListEntry); + AddLocalPacketHandler(PacketType.UserReport, HandleUserReport); + AddLocalPacketHandler(PacketType.FindAgent, HandleFindAgent); + AddLocalPacketHandler(PacketType.TrackAgent, HandleTrackAgent); + AddLocalPacketHandler(PacketType.GodUpdateRegionInfo, HandleGodUpdateRegionInfoUpdate); + AddLocalPacketHandler(PacketType.GodlikeMessage, HandleGodlikeMessage); + AddLocalPacketHandler(PacketType.StateSave, HandleSaveStatePacket); + AddLocalPacketHandler(PacketType.GroupAccountDetailsRequest, HandleGroupAccountDetailsRequest); + AddLocalPacketHandler(PacketType.GroupAccountSummaryRequest, HandleGroupAccountSummaryRequest); + AddLocalPacketHandler(PacketType.GroupAccountTransactionsRequest, HandleGroupTransactionsDetailsRequest); + AddLocalPacketHandler(PacketType.FreezeUser, HandleFreezeUser); + AddLocalPacketHandler(PacketType.EjectUser, HandleEjectUser); + AddLocalPacketHandler(PacketType.ParcelBuyPass, HandleParcelBuyPass); + AddLocalPacketHandler(PacketType.ParcelGodMarkAsContent, HandleParcelGodMarkAsContent); + AddLocalPacketHandler(PacketType.GroupActiveProposalsRequest, HandleGroupActiveProposalsRequest); + AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); + AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); + AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); + } + + #region Packet Handlers + + #region Scene/Avatar + + private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) + { + if (OnAgentUpdate != null) + { + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + + #region Packet Session and User Check + if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + return false; + #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; + UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; + lastarg = arg; // save this set of arguments for nexttime + if (handlerPreAgentUpdate != null) + OnPreAgentUpdate(this, arg); + if (handlerAgentUpdate != null) + OnAgentUpdate(this, arg); + + handlerAgentUpdate = null; + handlerPreAgentUpdate = null; + } + } + + return true; + } + + 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)); + } + + return true; + } + + return false; + } + + private bool HandleParcelGodMarkAsContent(IClientAPI client, Packet Packet) + { + ParcelGodMarkAsContentPacket ParcelGodMarkAsContent = + (ParcelGodMarkAsContentPacket)Packet; + + ParcelGodMark ParcelGodMarkAsContentHandler = OnParcelGodMark; + if (ParcelGodMarkAsContentHandler != null) + { + ParcelGodMarkAsContentHandler(this, + ParcelGodMarkAsContent.AgentData.AgentID, + ParcelGodMarkAsContent.ParcelData.LocalID); + return true; + } + return false; + } + + private bool HandleFreezeUser(IClientAPI client, Packet Packet) + { + FreezeUserPacket FreezeUser = (FreezeUserPacket)Packet; + + FreezeUserUpdate FreezeUserHandler = OnParcelFreezeUser; + if (FreezeUserHandler != null) + { + FreezeUserHandler(this, + FreezeUser.AgentData.AgentID, + FreezeUser.Data.Flags, + FreezeUser.Data.TargetID); + return true; + } + return false; + } + + private bool HandleEjectUser(IClientAPI client, Packet Packet) + { + EjectUserPacket EjectUser = + (EjectUserPacket)Packet; + + EjectUserUpdate EjectUserHandler = OnParcelEjectUser; + if (EjectUserHandler != null) + { + EjectUserHandler(this, + EjectUser.AgentData.AgentID, + EjectUser.Data.Flags, + EjectUser.Data.TargetID); + return true; + } + return false; + } + + private bool HandleParcelBuyPass(IClientAPI client, Packet Packet) + { + ParcelBuyPassPacket ParcelBuyPass = + (ParcelBuyPassPacket)Packet; + + ParcelBuyPass ParcelBuyPassHandler = OnParcelBuyPass; + if (ParcelBuyPassHandler != null) + { + ParcelBuyPassHandler(this, + ParcelBuyPass.AgentData.AgentID, + ParcelBuyPass.ParcelData.LocalID); + return true; + } + return false; + } + + 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; + } + + private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) + { + UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; + + + for (int i = 0; i < upack.UUIDNameBlock.Length; i++) + { + UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; + if (handlerUUIDGroupNameRequest != null) + { + handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); + } + } + + return true; + } + + 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; + + GenericMessage handlerGenericMessage = null; + + string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); + + if (m_genericPacketHandlers.TryGetValue(method, out handlerGenericMessage)) + { + List msg = new List(); + List msgBytes = new List(); + + 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.ErrorFormat( + "[LLCLIENTVIEW]: Exeception when handling generic message {0}{1}", e.Message, e.StackTrace); + } + } + } + + //m_log.Debug("[LLCLIENTVIEW]: 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; + } + + 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); + } + + handlerViewerEffect(sender, args); + } + + return true; + } + + private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) + { + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarProperties.AgentData.SessionID != SessionId || + avatarProperties.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties; + if (handlerRequestAvatarProperties != null) + { + handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); + } + return true; + } + + private bool HandleChatFromViewer(IClientAPI sender, Packet Pack) + { + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (inchatpack.AgentData.SessionID != SessionId || + inchatpack.AgentData.AgentID != AgentId) + return true; + } + #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) + { + 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); + } + return true; + } + + private bool HandlerAvatarPropertiesUpdate(IClientAPI sender, Packet Pack) + { + AvatarPropertiesUpdatePacket avatarProps = (AvatarPropertiesUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarProps.AgentData.SessionID != SessionId || + avatarProps.AgentData.AgentID != AgentId) + return true; + } + #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); + UserProfile.UserFlags &= ~3; + UserProfile.UserFlags |= Properties.AllowPublish ? 1 : 0; + UserProfile.UserFlags |= Properties.MaturePublish ? 2 : 0; + + handlerUpdateAvatarProperties(this, UserProfile); + } + return true; + } + + private bool HandlerScriptDialogReply(IClientAPI sender, Packet Pack) + { + ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; + + //m_log.DebugFormat("[CLIENT]: Received ScriptDialogReply from {0}", rdialog.Data.ObjectID); + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rdialog.AgentData.SessionID != SessionId || + rdialog.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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; + ChatMessage handlerChatFromClient2 = OnChatFromClient; + if (handlerChatFromClient2 != null) + handlerChatFromClient2(this, args); + } + + return true; + } + + private bool HandlerImprovedInstantMessage(IClientAPI sender, Packet Pack) + { + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (msgpack.AgentData.SessionID != SessionId || + msgpack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); + ImprovedInstantMessage handlerInstantMessage = OnInstantMessage; + + 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); + + handlerInstantMessage(this, im); + } + return true; + + } + + private bool HandlerAcceptFriendship(IClientAPI sender, Packet Pack) + { + AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (afriendpack.AgentData.SessionID != SessionId || + afriendpack.AgentData.AgentID != AgentId) + return true; + } + #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++) + { + callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); + } + + FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; + if (handlerApproveFriendRequest != null) + { + handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + } + return true; + + } + + private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack) + { + DeclineFriendshipPacket dfriendpack = (DeclineFriendshipPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dfriendpack.AgentData.SessionID != SessionId || + dfriendpack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnDenyFriendRequest != null) + { + OnDenyFriendRequest(this, + dfriendpack.AgentData.AgentID, + dfriendpack.TransactionBlock.TransactionID, + null); + } + return true; + } + + private bool HandlerTerminateFrendship(IClientAPI sender, Packet Pack) + { + TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (tfriendpack.AgentData.SessionID != SessionId || + tfriendpack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; + UUID exFriendID = tfriendpack.ExBlock.OtherID; + + FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship; + if (handlerTerminateFriendship != null) + { + handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); + } + return true; + } + + private bool HandleFindAgent(IClientAPI client, Packet Packet) + { + FindAgentPacket FindAgent = + (FindAgentPacket)Packet; + + FindAgentUpdate FindAgentHandler = OnFindAgent; + if (FindAgentHandler != null) + { + FindAgentHandler(this,FindAgent.AgentBlock.Hunter,FindAgent.AgentBlock.Prey); + return true; + } + return false; + } + + private bool HandleTrackAgent(IClientAPI client, Packet Packet) + { + TrackAgentPacket TrackAgent = + (TrackAgentPacket)Packet; + + TrackAgentUpdate TrackAgentHandler = OnTrackAgent; + if (TrackAgentHandler != null) + { + TrackAgentHandler(this, + TrackAgent.AgentData.AgentID, + TrackAgent.TargetData.PreyID); + return true; + } + return false; + } + + private bool HandlerRezObject(IClientAPI sender, Packet Pack) + { + RezObjectPacket rezPacket = (RezObjectPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rezPacket.AgentData.SessionID != SessionId || + rezPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandlerDeRezObject(IClientAPI sender, Packet Pack) + { + DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (DeRezPacket.AgentData.SessionID != SessionId || + DeRezPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + DeRezObject handlerDeRezObject = OnDeRezObject; + if (handlerDeRezObject != null) + { + 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); + + } + return true; + } + + private bool HandlerModifyLand(IClientAPI sender, Packet Pack) + { + ModifyLandPacket modify = (ModifyLandPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (modify.AgentData.SessionID != SessionId || + modify.AgentData.AgentID != AgentId) + return true; + } + + #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); + } + } + } + } + + return true; + } + + private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack) + { + Action handlerRegionHandShakeReply = OnRegionHandShakeReply; + if (handlerRegionHandShakeReply != null) + { + handlerRegionHandShakeReply(this); + } + + return true; + } + + private bool HandlerAgentWearablesRequest(IClientAPI sender, Packet Pack) + { + GenericCall1 handlerRequestWearables = OnRequestWearables; + + if (handlerRequestWearables != null) + { + handlerRequestWearables(sender); + } + + Action handlerRequestAvatarsData = OnRequestAvatarsData; + + if (handlerRequestAvatarsData != null) + { + handlerRequestAvatarsData(this); + } + + return true; + } + + private bool HandlerAgentSetAppearance(IClientAPI sender, Packet Pack) + { + AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (appear.AgentData.SessionID != SessionId || + appear.AgentData.AgentID != AgentId) + return true; + } + #endregion + + SetAppearance 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; + + Primitive.TextureEntry te = null; + if (appear.ObjectData.TextureEntry.Length > 1) + te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); + + handlerSetAppearance(sender, te, visualparams); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}", + e); + } + } + + return true; + } + + private bool HandlerAgentIsNowWearing(IClientAPI sender, Packet Pack) + { + if (OnAvatarNowWearing != null) + { + AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (nowWearing.AgentData.SessionID != SessionId || + nowWearing.AgentData.AgentID != AgentId) + return true; + } + #endregion + + AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); + for (int i = 0; i < nowWearing.WearableData.Length; i++) + { + m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID); + 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); + } + } + return true; + } + + private bool HandlerRezSingleAttachmentFromInv(IClientAPI sender, Packet Pack) + { + RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; + if (handlerRezSingleAttachment != null) + { + RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rez.AgentData.SessionID != SessionId || + rez.AgentData.AgentID != AgentId) + return true; + } + #endregion + + handlerRezSingleAttachment(this, rez.ObjectData.ItemID, + rez.ObjectData.AttachmentPt); + } + + return true; + } + + private bool HandleRezMultipleAttachmentsFromInv(IClientAPI sender, Packet Pack) + { + RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; + if (handlerRezMultipleAttachments != null) + { + RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; + handlerRezMultipleAttachments(this, rez.HeaderData, + rez.ObjectData); + } + + return true; + } + + private bool HandleDetachAttachmentIntoInv(IClientAPI sender, Packet Pack) + { + UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; + if (handlerDetachAttachmentIntoInv != 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); + } + return true; + } + + private bool HandleObjectAttach(IClientAPI sender, Packet Pack) + { + if (OnObjectAttach != null) + { + ObjectAttachPacket att = (ObjectAttachPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (att.AgentData.SessionID != SessionId || + att.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectAttach handlerObjectAttach = OnObjectAttach; + + if (handlerObjectAttach != null) + { + if (att.ObjectData.Length > 0) + { + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false); + } + } + } + return true; + } + + private bool HandleObjectDetach(IClientAPI sender, Packet Pack) + { + ObjectDetachPacket dett = (ObjectDetachPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dett.AgentData.SessionID != SessionId || + dett.AgentData.AgentID != AgentId) + return true; + } + #endregion + + for (int j = 0; j < dett.ObjectData.Length; j++) + { + uint obj = dett.ObjectData[j].ObjectLocalID; + ObjectDeselect handlerObjectDetach = OnObjectDetach; + if (handlerObjectDetach != null) + { + handlerObjectDetach(obj, this); + } + + } + return true; + } + + private bool HandleObjectDrop(IClientAPI sender, Packet Pack) + { + ObjectDropPacket dropp = (ObjectDropPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dropp.AgentData.SessionID != SessionId || + dropp.AgentData.AgentID != AgentId) + return true; + } + #endregion + + for (int j = 0; j < dropp.ObjectData.Length; j++) + { + uint obj = dropp.ObjectData[j].ObjectLocalID; + ObjectDrop handlerObjectDrop = OnObjectDrop; + if (handlerObjectDrop != null) + { + handlerObjectDrop(obj, this); + } + } + return true; + } + + private bool HandleSetAlwaysRun(IClientAPI sender, Packet Pack) + { + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (run.AgentData.SessionID != SessionId || + run.AgentData.AgentID != AgentId) + return true; + } + #endregion + + SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun; + if (handlerSetAlwaysRun != null) + handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); + + return true; + } + + private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) + { + GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; + if (handlerCompleteMovementToRegion != null) + { + handlerCompleteMovementToRegion(sender); + } + handlerCompleteMovementToRegion = null; + + return true; + } + + private bool HandleAgentAnimation(IClientAPI sender, Packet Pack) + { + AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (AgentAni.AgentData.SessionID != SessionId || + AgentAni.AgentData.AgentID != AgentId) + return true; + } + #endregion + + StartAnim handlerStartAnim = null; + StopAnim handlerStopAnim = null; + + for (int i = 0; i < AgentAni.AnimationList.Length; i++) + { + 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); + } + } + } + return true; + } + + private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #endregion + + AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; + if (handlerAgentRequestSit != null) + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + } + return true; + } + + private bool HandleAgentSit(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #endregion + + AgentSit handlerAgentSit = OnAgentSit; + if (handlerAgentSit != null) + { + OnAgentSit(this, agentSit.AgentData.AgentID); + } + } + return true; + } + + private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) + { + SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + // UNSUPPORTED ON THIS PACKET + } + #endregion + + SoundTrigger handlerSoundTrigger = OnSoundTrigger; + if (handlerSoundTrigger != null) + { + // UUIDS are sent as zeroes by the client, substitute agent's id + handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, AgentId, + AgentId, AgentId, + soundTriggerPacket.SoundData.Gain, soundTriggerPacket.SoundData.Position, + soundTriggerPacket.SoundData.Handle, 0); + + } + return true; + } + + private bool HandleAvatarPickerRequest(IClientAPI sender, Packet Pack) + { + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avRequestQuery.AgentData.SessionID != SessionId || + avRequestQuery.AgentData.AgentID != AgentId) + return true; + } + #endregion + + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); + + AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest; + if (handlerAvatarPickerRequest != null) + { + handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, + Utils.BytesToString(querydata.Name)); + } + return true; + } + + private bool HandleAgentDataUpdateRequest(IClientAPI sender, Packet Pack) + { + AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avRequestDataUpdatePacket.AgentData.SessionID != SessionId || + avRequestDataUpdatePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; + + if (handlerAgentDataUpdateRequest != null) + { + handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID); + } + + return true; + } + + private bool HandleUserInfoRequest(IClientAPI sender, Packet Pack) + { + UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest; + if (handlerUserInfoRequest != null) + { + handlerUserInfoRequest(this); + } + else + { + SendUserInfoReply(false, true, ""); + } + return true; + + } + + private bool HandleUpdateUserInfo(IClientAPI sender, Packet Pack) + { + UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (updateUserInfo.AgentData.SessionID != SessionId || + updateUserInfo.AgentData.AgentID != AgentId) + return true; + } + #endregion + + UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo; + if (handlerUpdateUserInfo != null) + { + bool visible = true; + string DirectoryVisibility = + Utils.BytesToString(updateUserInfo.UserData.DirectoryVisibility); + if (DirectoryVisibility == "hidden") + visible = false; + + handlerUpdateUserInfo( + updateUserInfo.UserData.IMViaEMail, + visible, this); + } + return true; + } + + private bool HandleSetStartLocationRequest(IClientAPI sender, Packet Pack) + { + SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avSetStartLocationRequestPacket.AgentData.SessionID != SessionId || + avSetStartLocationRequestPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) + { + // Linden Client limitation.. + if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f + || avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f) + { + ScenePresence avatar = null; + if (((Scene)m_scene).TryGetScenePresence(AgentId, out avatar)) + { + if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.X == 255.5f) + { + avSetStartLocationRequestPacket.StartLocationData.LocationPos.X = avatar.AbsolutePosition.X; + } + if (avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y == 255.5f) + { + avSetStartLocationRequestPacket.StartLocationData.LocationPos.Y = avatar.AbsolutePosition.Y; + } + } + + } + TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest; + if (handlerSetStartLocationRequest != null) + { + handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, + avSetStartLocationRequestPacket.StartLocationData.LocationLookAt, + avSetStartLocationRequestPacket.StartLocationData.LocationID); + } + } + return true; + } + + private bool HandleAgentThrottle(IClientAPI sender, Packet Pack) + { + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (atpack.AgentData.SessionID != SessionId || + atpack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + m_udpClient.SetThrottles(atpack.Throttle.Throttles); + return true; + } + + private bool HandleAgentPause(IClientAPI sender, Packet Pack) + { + m_udpClient.IsPaused = true; + return true; + } + + private bool HandleAgentResume(IClientAPI sender, Packet Pack) + { + m_udpClient.IsPaused = false; + SendStartPingCheck(m_udpClient.CurrentPingSequence++); + return true; + } + + private bool HandleForceScriptControlRelease(IClientAPI sender, Packet Pack) + { + ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls; + if (handlerForceReleaseControls != null) + { + handlerForceReleaseControls(this, AgentId); + } + return true; + } + + #endregion Scene/Avatar + + #region Objects/m_sceneObjects + + private bool HandleObjectLink(IClientAPI sender, Packet Pack) + { + ObjectLinkPacket link = (ObjectLinkPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (link.AgentData.SessionID != SessionId || + link.AgentData.AgentID != AgentId) + return true; + } + #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); + } + } + LinkObjects handlerLinkObjects = OnLinkObjects; + if (handlerLinkObjects != null) + { + handlerLinkObjects(this, parentprimid, childrenprims); + } + return true; + } + + private bool HandleObjectDelink(IClientAPI sender, Packet Pack) + { + ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (delink.AgentData.SessionID != SessionId || + delink.AgentData.AgentID != AgentId) + return true; + } + #endregion + + // 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) + { + handlerDelinkObjects(prims, this); + } + + return true; + } + + private bool HandleObjectAdd(IClientAPI sender, Packet Pack) + { + if (OnAddPrim != null) + { + ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (addPacket.AgentData.SessionID != SessionId || + addPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleObjectShape(IClientAPI sender, Packet Pack) + { + ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (shapePacket.AgentData.SessionID != SessionId || + shapePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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; + + handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, + shapeData); + } + } + return true; + } + + private bool HandleObjectExtraParams(IClientAPI sender, Packet Pack) + { + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (extraPar.AgentData.SessionID != SessionId || + extraPar.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectExtraParams 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); + } + } + return true; + } + + private bool HandleObjectDuplicate(IClientAPI sender, Packet Pack) + { + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dupe.AgentData.SessionID != SessionId || + dupe.AgentData.AgentID != AgentId) + return true; + } + #endregion + +// ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + + ObjectDuplicate handlerObjectDuplicate = null; + + 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, AgentId, + m_activeGroupID); + } + } + + return true; + } + + private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack) + { + RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (incomingRequest.AgentData.SessionID != SessionId || + incomingRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectRequest handlerObjectRequest = null; + + for (int i = 0; i < incomingRequest.ObjectData.Length; i++) + { + handlerObjectRequest = OnObjectRequest; + if (handlerObjectRequest != null) + { + handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); + } + } + return true; + } + + private bool HandleObjectSelect(IClientAPI sender, Packet Pack) + { + ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (incomingselect.AgentData.SessionID != SessionId || + incomingselect.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectSelect handlerObjectSelect = null; + + for (int i = 0; i < incomingselect.ObjectData.Length; i++) + { + handlerObjectSelect = OnObjectSelect; + if (handlerObjectSelect != null) + { + handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); + } + } + return true; + } + + private bool HandleObjectDeselect(IClientAPI sender, Packet Pack) + { + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (incomingdeselect.AgentData.SessionID != SessionId || + incomingdeselect.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectDeselect handlerObjectDeselect = null; + + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) + { + handlerObjectDeselect = OnObjectDeselect; + if (handlerObjectDeselect != null) + { + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); + } + } + return true; + } + + private bool HandleObjectPosition(IClientAPI sender, Packet Pack) + { + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectPositionPacket position = (ObjectPositionPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (position.AgentData.SessionID != SessionId || + position.AgentData.AgentID != AgentId) + return true; + } + #endregion + + + for (int i = 0; i < position.ObjectData.Length; i++) + { + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; + if (handlerUpdateVector != null) + handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); + } + + return true; + } + + private bool HandleObjectScale(IClientAPI sender, Packet Pack) + { + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectScalePacket scale = (ObjectScalePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (scale.AgentData.SessionID != SessionId || + scale.AgentData.AgentID != AgentId) + return true; + } + #endregion + + for (int i = 0; i < scale.ObjectData.Length; i++) + { + UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; + if (handlerUpdatePrimGroupScale != null) + handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); + } + + return true; + } + + private bool HandleObjectRotation(IClientAPI sender, Packet Pack) + { + // DEPRECATED: but till libsecondlife removes it, people will use it + ObjectRotationPacket rotation = (ObjectRotationPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rotation.AgentData.SessionID != SessionId || + rotation.AgentData.AgentID != AgentId) + return true; + } + #endregion + + for (int i = 0; i < rotation.ObjectData.Length; i++) + { + UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; + if (handlerUpdatePrimRotation != null) + handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); + } + + return true; + } + + private bool HandleObjectFlagUpdate(IClientAPI sender, Packet Pack) + { + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (flags.AgentData.SessionID != SessionId || + flags.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleObjectImage(IClientAPI sender, Packet Pack) + { + ObjectImagePacket imagePack = (ObjectImagePacket)Pack; + + UpdatePrimTexture 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); + } + } + return true; + } + + private bool HandleObjectGrab(IClientAPI sender, Packet Pack) + { + ObjectGrabPacket grab = (ObjectGrabPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (grab.AgentData.SessionID != SessionId || + grab.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + } + return true; + } + + private bool HandleObjectGrabUpdate(IClientAPI sender, Packet Pack) + { + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (grabUpdate.AgentData.SessionID != SessionId || + grabUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + MoveObject handlerGrabUpdate = OnGrabUpdate; + + if (handlerGrabUpdate != 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); + } + return true; + } + + private bool HandleObjectDeGrab(IClientAPI sender, Packet Pack) + { + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (deGrab.AgentData.SessionID != SessionId || + deGrab.AgentData.AgentID != AgentId) + return true; + } + #endregion + + DeGrabObject handlerDeGrabObject = OnDeGrabObject; + if (handlerDeGrabObject != 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); + } + return true; + } + + private bool HandleObjectSpinStart(IClientAPI sender, Packet Pack) + { + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStart packet"); + ObjectSpinStartPacket spinStart = (ObjectSpinStartPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (spinStart.AgentData.SessionID != SessionId || + spinStart.AgentData.AgentID != AgentId) + return true; + } + #endregion + + SpinStart handlerSpinStart = OnSpinStart; + if (handlerSpinStart != null) + { + handlerSpinStart(spinStart.ObjectData.ObjectID, this); + } + return true; + } + + private bool HandleObjectSpinUpdate(IClientAPI sender, Packet Pack) + { + //m_log.Warn("[CLIENT]: unhandled ObjectSpinUpdate packet"); + ObjectSpinUpdatePacket spinUpdate = (ObjectSpinUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (spinUpdate.AgentData.SessionID != SessionId || + spinUpdate.AgentData.AgentID != AgentId) + return true; + } + #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) + { + handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); + } + return true; + } + + private bool HandleObjectSpinStop(IClientAPI sender, Packet Pack) + { + //m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); + ObjectSpinStopPacket spinStop = (ObjectSpinStopPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (spinStop.AgentData.SessionID != SessionId || + spinStop.AgentData.AgentID != AgentId) + return true; + } + #endregion + + SpinStop handlerSpinStop = OnSpinStop; + if (handlerSpinStop != null) + { + handlerSpinStop(spinStop.ObjectData.ObjectID, this); + } + return true; + } + + private bool HandleObjectDescription(IClientAPI sender, Packet Pack) + { + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objDes.AgentData.SessionID != SessionId || + objDes.AgentData.AgentID != AgentId) + return true; + } + #endregion + + GenericCall7 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)); + } + } + return true; + } + + private bool HandleObjectName(IClientAPI sender, Packet Pack) + { + ObjectNamePacket objName = (ObjectNamePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objName.AgentData.SessionID != SessionId || + objName.AgentData.AgentID != AgentId) + return true; + } + #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)); + } + } + return true; + } + + private bool HandleObjectPermissions(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #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. + + return true; + } + + private bool HandleUndo(IClientAPI sender, Packet Pack) + { + UndoPacket undoitem = (UndoPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (undoitem.AgentData.SessionID != SessionId || + undoitem.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (undoitem.ObjectData.Length > 0) + { + for (int i = 0; i < undoitem.ObjectData.Length; i++) + { + UUID objiD = undoitem.ObjectData[i].ObjectID; + AgentSit handlerOnUndo = OnUndo; + if (handlerOnUndo != null) + { + handlerOnUndo(this, objiD); + } + + } + } + return true; + } + + private bool HandleLandUndo(IClientAPI sender, Packet Pack) + { + UndoLandPacket undolanditem = (UndoLandPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (undolanditem.AgentData.SessionID != SessionId || + undolanditem.AgentData.AgentID != AgentId) + return true; + } + #endregion + + LandUndo handlerOnUndo = OnLandUndo; + if (handlerOnUndo != null) + { + handlerOnUndo(this); + } + return true; + } + + private bool HandleRedo(IClientAPI sender, Packet Pack) + { + RedoPacket redoitem = (RedoPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (redoitem.AgentData.SessionID != SessionId || + redoitem.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (redoitem.ObjectData.Length > 0) + { + for (int i = 0; i < redoitem.ObjectData.Length; i++) + { + UUID objiD = redoitem.ObjectData[i].ObjectID; + AgentSit handlerOnRedo = OnRedo; + if (handlerOnRedo != null) + { + handlerOnRedo(this, objiD); + } + + } + } + return true; + } + + private bool HandleObjectDuplicateOnRay(IClientAPI sender, Packet Pack) + { + ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dupeOnRay.AgentData.SessionID != SessionId || + dupeOnRay.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null; + + for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) + { + handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay; + if (handlerObjectDuplicateOnRay != null) + { + handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, + AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, + dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); + } + } + + return true; + } + + private bool HandleRequestObjectPropertiesFamily(IClientAPI sender, Packet Pack) + { + //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 (packToolTip.AgentData.SessionID != SessionId || + packToolTip.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + + RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; + + if (handlerRequestObjectPropertiesFamily != null) + { + handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, + packObjBlock.ObjectID); + } + + return true; + } + + private bool HandleObjectIncludeInSearch(IClientAPI sender, Packet Pack) + { + //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 (packInSearch.AgentData.SessionID != SessionId || + packInSearch.AgentData.AgentID != AgentId) + return true; + } + #endregion + + foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) + { + bool inSearch = objData.IncludeInSearch; + uint localID = objData.ObjectLocalID; + + handlerObjectIncludeInSearch = OnObjectIncludeInSearch; + + if (handlerObjectIncludeInSearch != null) + { + handlerObjectIncludeInSearch(this, inSearch, localID); + } + } + return true; + } + + private bool HandleScriptAnswerYes(IClientAPI sender, Packet Pack) + { + ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (scriptAnswer.AgentData.SessionID != SessionId || + scriptAnswer.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ScriptAnswer handlerScriptAnswer = OnScriptAnswer; + if (handlerScriptAnswer != null) + { + handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); + } + return true; + } + + private bool HandleObjectClickAction(IClientAPI sender, Packet Pack) + { + ObjectClickActionPacket ocpacket = (ObjectClickActionPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (ocpacket.AgentData.SessionID != SessionId || + ocpacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + GenericCall7 handlerObjectClickAction = OnObjectClickAction; + if (handlerObjectClickAction != null) + { + foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) + { + byte action = odata.ClickAction; + uint localID = odata.ObjectLocalID; + handlerObjectClickAction(this, localID, action.ToString()); + } + } + return true; + } + + private bool HandleObjectMaterial(IClientAPI sender, Packet Pack) + { + ObjectMaterialPacket ompacket = (ObjectMaterialPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (ompacket.AgentData.SessionID != SessionId || + ompacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + GenericCall7 handlerObjectMaterial = OnObjectMaterial; + if (handlerObjectMaterial != null) + { + foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) + { + byte material = odata.Material; + uint localID = odata.ObjectLocalID; + handlerObjectMaterial(this, localID, material.ToString()); + } + } + return true; + } + + #endregion Objects/m_sceneObjects + + #region Inventory/Asset/Other related packets + + private bool HandleRequestImage(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #endregion + + //handlerTextureRequest = null; + for (int i = 0; i < imageRequest.RequestImage.Length; i++) + { + TextureRequestArgs args = new TextureRequestArgs(); + + RequestImagePacket.RequestImageBlock block = imageRequest.RequestImage[i]; + + args.RequestedAssetID = block.Image; + args.DiscardLevel = block.DiscardLevel; + args.PacketNumber = block.Packet; + args.Priority = block.DownloadPriority; + args.requestSequence = imageRequest.Header.Sequence; + + // NOTE: This is not a built in part of the LLUDP protocol, but we double the + // priority of avatar textures to get avatars rezzing in faster than the + // surrounding scene + if ((ImageType)block.Type == ImageType.Baked) + args.Priority *= 2.0f; + + // in the end, we null this, so we have to check if it's null + if (m_imageManager != null) + { + m_imageManager.EnqueueReq(args); + } + } + return true; + } + + /// + /// This is the entry point for the UDP route by which the client can retrieve asset data. If the request + /// is successful then a TransferInfo packet will be sent back, followed by one or more TransferPackets + /// + /// + /// + /// This parameter may be ignored since we appear to return true whatever happens + private bool HandleTransferRequest(IClientAPI sender, Packet Pack) + { + //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 + // + UUID taskID = UUID.Zero; + if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + { + taskID = new UUID(transfer.TransferInfo.Params, 48); + UUID itemID = new UUID(transfer.TransferInfo.Params, 64); + UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + +// m_log.DebugFormat( +// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}", +// requestID, itemID, taskID, Name); + + if (!(((Scene)m_scene).Permissions.BypassPermissions())) + { + if (taskID != UUID.Zero) // Prim + { + SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + + if (part == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist", + Name, requestID, itemID, taskID); + return true; + } + + TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); + if (tii == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.Type == (int)AssetType.LSLText) + { + if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) + return true; + } + else if (tii.Type == (int)AssetType.Notecard) + { + if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId)) + return true; + } + else + { + // TODO: Change this code to allow items other than notecards and scripts to be successfully + // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule + if (part.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}", + Name, requestID, itemID, taskID, part.OwnerID); + return true; + } + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", + Name, requestID, itemID, taskID, tii.OwnerID); + return true; + } + + if (( + tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", + Name, requestID, itemID, taskID, tii.AssetID); + return true; + } + } + } + else // Agent + { + IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); + if (invAccess != null) + { + if (!invAccess.GetAgentInventoryItem(this, itemID, requestID)) + return false; + + } + else + return false; + + } + } + } + + MakeAssetRequest(transfer, taskID); + + return true; + } + + private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) + { + 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) + { + handlerAssetUploadRequest(this, temp, + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, + request.AssetBlock.Tempfile); + } + return true; + } + + private bool HandleRequestXfer(IClientAPI sender, Packet Pack) + { + RequestXferPacket xferReq = (RequestXferPacket)Pack; + + RequestXfer handlerRequestXfer = OnRequestXfer; + + if (handlerRequestXfer != null) + { + handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + } + return true; + } + + private bool HandleSendXferPacket(IClientAPI sender, Packet Pack) + { + SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; + + XferReceive handlerXferReceive = OnXferReceive; + if (handlerXferReceive != null) + { + handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + } + return true; + } + + private bool HandleConfirmXferPacket(IClientAPI sender, Packet Pack) + { + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; + + ConfirmXfer handlerConfirmXfer = OnConfirmXfer; + if (handlerConfirmXfer != null) + { + handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); + } + return true; + } + + private bool HandleAbortXfer(IClientAPI sender, Packet Pack) + { + AbortXferPacket abortXfer = (AbortXferPacket)Pack; + AbortXfer handlerAbortXfer = OnAbortXfer; + if (handlerAbortXfer != null) + { + handlerAbortXfer(this, abortXfer.XferID.ID); + } + + return true; + } + + private bool HandleCreateInventoryFolder(IClientAPI sender, Packet Pack) + { + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (invFolder.AgentData.SessionID != SessionId || + invFolder.AgentData.AgentID != AgentId) + return true; + } + #endregion + + CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder; + if (handlerCreateInventoryFolder != null) + { + handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort)invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + return true; + } + + private bool HandleUpdateInventoryFolder(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #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); + } + } + } + return true; + } + + private bool HandleMoveInventoryFolder(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #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); + } + } + } + return true; + } + + private bool HandleCreateInventoryItem(IClientAPI sender, Packet Pack) + { + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createItem.AgentData.SessionID != SessionId || + createItem.AgentData.AgentID != AgentId) + return true; + } + #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()); + } + return true; + } + + private bool HandleLinkInventoryItem(IClientAPI sender, Packet Pack) + { + LinkInventoryItemPacket createLink = (LinkInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createLink.AgentData.SessionID != SessionId || + createLink.AgentData.AgentID != AgentId) + return true; + } + #endregion + + LinkInventoryItem linkInventoryItem = OnLinkInventoryItem; + + if (linkInventoryItem != null) + { + linkInventoryItem( + this, + createLink.InventoryBlock.TransactionID, + createLink.InventoryBlock.FolderID, + createLink.InventoryBlock.CallbackID, + Util.FieldToString(createLink.InventoryBlock.Description), + Util.FieldToString(createLink.InventoryBlock.Name), + createLink.InventoryBlock.InvType, + createLink.InventoryBlock.Type, + createLink.InventoryBlock.OldItemID); + } + + return true; + } + + private bool HandleFetchInventory(IClientAPI sender, Packet Pack) + { + 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) + return true; + } + #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); + } + } + } + return true; + } + + private bool HandleFetchInventoryDescendents(IClientAPI sender, Packet Pack) + { + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (Fetch.AgentData.SessionID != SessionId || + Fetch.AgentData.AgentID != AgentId) + return true; + } + #endregion + + FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents; + if (handlerFetchInventoryDescendents != null) + { + handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); + } + return true; + } + + private bool HandlePurgeInventoryDescendents(IClientAPI sender, Packet Pack) + { + PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (Purge.AgentData.SessionID != SessionId || + Purge.AgentData.AgentID != AgentId) + return true; + } + #endregion + + PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; + if (handlerPurgeInventoryDescendents != null) + { + handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + } + return true; + } + + private bool HandleUpdateInventoryItem(IClientAPI sender, Packet Pack) + { + UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (inventoryItemUpdate.AgentData.SessionID != SessionId || + inventoryItemUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnUpdateInventoryItem != null) + { + UpdateInventoryItem 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, + itemUpd); + } + } + } + return true; + } + + private bool HandleCopyInventoryItem(IClientAPI sender, Packet Pack) + { + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (copyitem.AgentData.SessionID != SessionId || + copyitem.AgentData.AgentID != AgentId) + return true; + } + #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)); + } + } + } + return true; + } + + private bool HandleMoveInventoryItem(IClientAPI sender, Packet Pack) + { + MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (moveitem.AgentData.SessionID != SessionId || + moveitem.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnMoveInventoryItem != 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); + } + } + return true; + } + + private bool HandleRemoveInventoryItem(IClientAPI sender, Packet Pack) + { + RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (removeItem.AgentData.SessionID != SessionId || + removeItem.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + } + + } + return true; + } + + private bool HandleRemoveInventoryFolder(IClientAPI sender, Packet Pack) + { + RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (removeFolder.AgentData.SessionID != SessionId || + removeFolder.AgentData.AgentID != AgentId) + return true; + } + #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); + } + } + return true; + } + + private bool HandleRemoveInventoryObjects(IClientAPI sender, Packet Pack) + { + RemoveInventoryObjectsPacket removeObject = (RemoveInventoryObjectsPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (removeObject.AgentData.SessionID != SessionId || + removeObject.AgentData.AgentID != AgentId) + return true; + } + #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); + } + } + + 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); + } + } + return true; + } + + private bool HandleRequestTaskInventory(IClientAPI sender, Packet Pack) + { + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (requesttask.AgentData.SessionID != SessionId || + requesttask.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory; + if (handlerRequestTaskInventory != null) + { + handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); + } + return true; + } + + private bool HandleUpdateTaskInventory(IClientAPI sender, Packet Pack) + { + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (updatetask.AgentData.SessionID != SessionId || + updatetask.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnUpdateTaskInventory != null) + { + if (updatetask.UpdateData.Key == 0) + { + 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; + + // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something + // different + //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); + } + } + } + + return true; + } + + private bool HandleRemoveTaskInventory(IClientAPI sender, Packet Pack) + { + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (removeTask.AgentData.SessionID != SessionId || + removeTask.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem; + + if (handlerRemoveTaskItem != null) + { + handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); + } + + return true; + } + + private bool HandleMoveTaskInventory(IClientAPI sender, Packet Pack) + { + MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (moveTaskInventoryPacket.AgentData.SessionID != SessionId || + moveTaskInventoryPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem; + + if (handlerMoveTaskItem != null) + { + handlerMoveTaskItem( + this, moveTaskInventoryPacket.AgentData.FolderID, + moveTaskInventoryPacket.InventoryData.LocalID, + moveTaskInventoryPacket.InventoryData.ItemID); + } + + return true; + } + + private bool HandleRezScript(IClientAPI sender, Packet Pack) + { + //m_log.Debug(Pack.ToString()); + RezScriptPacket rezScriptx = (RezScriptPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rezScriptx.AgentData.SessionID != SessionId || + rezScriptx.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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) + { + handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID); + } + return true; + } + + private bool HandleMapLayerRequest(IClientAPI sender, Packet Pack) + { + RequestMapLayer(); + return true; + } + + private bool HandleMapBlockRequest(IClientAPI sender, Packet Pack) + { + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (MapRequest.AgentData.SessionID != SessionId || + MapRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks; + if (handlerRequestMapBlocks != null) + { + handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags); + } + return true; + } + + private bool HandleMapNameRequest(IClientAPI sender, Packet Pack) + { + MapNameRequestPacket map = (MapNameRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (map.AgentData.SessionID != SessionId || + map.AgentData.AgentID != AgentId) + return true; + } + #endregion + + string mapName = Util.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + RequestMapName handlerMapNameRequest = OnMapNameRequest; + if (handlerMapNameRequest != null) + { + handlerMapNameRequest(this, mapName); + } + return true; + } + + private bool HandleTeleportLandmarkRequest(IClientAPI sender, Packet Pack) + { + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (tpReq.Info.SessionID != SessionId || + tpReq.Info.AgentID != AgentId) + return true; + } + #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) + { + // 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); + return true; + } + } + else + { + // Teleport home request + UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest; + if (handlerTeleportHomeRequest != null) + { + handlerTeleportHomeRequest(AgentId, this); + } + return true; + } + + TeleportLandmarkRequest 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); + + } + return true; + } + + private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack) + { + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; + // m_log.Debug(tpLocReq.ToString()); + + #region Packet Session and User Check + if (m_checkPackets) + { + if (tpLocReq.AgentData.SessionID != SessionId || + tpLocReq.AgentData.AgentID != AgentId) + return true; + } + #endregion + + TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; + if (handlerTeleportLocationRequest != null) + { + 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); + } + return true; + } + + #endregion Inventory/Asset/Other related packets + + private bool HandleUUIDNameRequest(IClientAPI sender, Packet Pack) + { + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest; + if (handlerNameRequest != null) + { + handlerNameRequest(UUIDBlock.ID, this); + } + } + return true; + } + + #region Parcel related packets + + private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) + { + RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; + + RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; + if (handlerRegionHandleRequest != null) + { + handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); + } + return true; + } + + private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) + { + ParcelInfoRequestPacket pirPack = (ParcelInfoRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (pirPack.AgentData.SessionID != SessionId || + pirPack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest; + if (handlerParcelInfoRequest != null) + { + handlerParcelInfoRequest(this, pirPack.Data.ParcelID); + } + return true; + } + + private bool HandleParcelAccessListRequest(IClientAPI sender, Packet Pack) + { + ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (requestPacket.AgentData.SessionID != SessionId || + requestPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest; + + if (handlerParcelAccessListRequest != null) + { + handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, + requestPacket.Data.Flags, requestPacket.Data.SequenceID, + requestPacket.Data.LocalID, this); + } + return true; + } + + private bool HandleParcelAccessListUpdate(IClientAPI sender, Packet Pack) + { + ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (updatePacket.AgentData.SessionID != SessionId || + updatePacket.AgentData.AgentID != AgentId) + return true; + } + #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 = Util.ToDateTime(block.Time); + entries.Add(entry); + } + + ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; + if (handlerParcelAccessListUpdateRequest != null) + { + handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, + updatePacket.Data.Flags, + updatePacket.Data.LocalID, + updatePacket.Data.TransactionID, + updatePacket.Data.SequenceID, + updatePacket.Data.Sections, + entries, this); + } + return true; + } + + private bool HandleParcelPropertiesRequest(IClientAPI sender, Packet Pack) + { + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (propertiesRequest.AgentData.SessionID != SessionId || + propertiesRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest; + if (handlerParcelPropertiesRequest != 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); + } + return true; + } + + private bool HandleParcelDivide(IClientAPI sender, Packet Pack) + { + ParcelDividePacket landDivide = (ParcelDividePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (landDivide.AgentData.SessionID != SessionId || + landDivide.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest; + if (handlerParcelDivideRequest != 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); + } + return true; + } + + private bool HandleParcelJoin(IClientAPI sender, Packet Pack) + { + ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (landJoin.AgentData.SessionID != SessionId || + landJoin.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleParcelPropertiesUpdate(IClientAPI sender, Packet Pack) + { + ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (parcelPropertiesPacket.AgentData.SessionID != SessionId || + parcelPropertiesPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelPropertiesUpdateRequest 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); + } + return true; + } + + private bool HandleParcelSelectObjects(IClientAPI sender, Packet Pack) + { + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (selectPacket.AgentData.SessionID != SessionId || + selectPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + List returnIDs = new List(); + + foreach (ParcelSelectObjectsPacket.ReturnIDsBlock rb in + selectPacket.ReturnIDs) + { + returnIDs.Add(rb.ReturnID); + } + + ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects; + + if (handlerParcelSelectObjects != null) + { + handlerParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), returnIDs, this); + } + return true; + } + + private bool HandleParcelObjectOwnersRequest(IClientAPI sender, Packet Pack) + { + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (reqPacket.AgentData.SessionID != SessionId || + reqPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; + + if (handlerParcelObjectOwnerRequest != null) + { + handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); + } + return true; + + } + + private bool HandleParcelGodForceOwner(IClientAPI sender, Packet Pack) + { + ParcelGodForceOwnerPacket godForceOwnerPacket = (ParcelGodForceOwnerPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (godForceOwnerPacket.AgentData.SessionID != SessionId || + godForceOwnerPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner; + if (handlerParcelGodForceOwner != null) + { + handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); + } + return true; + } + + private bool HandleParcelRelease(IClientAPI sender, Packet Pack) + { + ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (releasePacket.AgentData.SessionID != SessionId || + releasePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest; + if (handlerParcelAbandonRequest != null) + { + handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); + } + return true; + } + + private bool HandleParcelReclaim(IClientAPI sender, Packet Pack) + { + ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (reclaimPacket.AgentData.SessionID != SessionId || + reclaimPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelReclaim handlerParcelReclaim = OnParcelReclaim; + if (handlerParcelReclaim != null) + { + handlerParcelReclaim(reclaimPacket.Data.LocalID, this); + } + return true; + } + + private bool HandleParcelReturnObjects(IClientAPI sender, Packet Pack) + { + ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (parcelReturnObjects.AgentData.SessionID != SessionId || + parcelReturnObjects.AgentData.AgentID != AgentId) + return true; + } + #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) + { + handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); + + } + return true; + } + + private bool HandleParcelSetOtherCleanTime(IClientAPI sender, Packet Pack) + { + ParcelSetOtherCleanTimePacket parcelSetOtherCleanTimePacket = (ParcelSetOtherCleanTimePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (parcelSetOtherCleanTimePacket.AgentData.SessionID != SessionId || + parcelSetOtherCleanTimePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; + if (handlerParcelSetOtherCleanTime != null) + { + handlerParcelSetOtherCleanTime(this, + parcelSetOtherCleanTimePacket.ParcelData.LocalID, + parcelSetOtherCleanTimePacket.ParcelData.OtherCleanTime); + } + return true; + } + + private bool HandleLandStatRequest(IClientAPI sender, Packet Pack) + { + LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (lsrp.AgentData.SessionID != SessionId || + lsrp.AgentData.AgentID != AgentId) + return true; + } + #endregion + + GodLandStatRequest handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); + } + return true; + } + + private bool HandleParcelDwellRequest(IClientAPI sender, Packet Pack) + { + ParcelDwellRequestPacket dwellrq = + (ParcelDwellRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dwellrq.AgentData.SessionID != SessionId || + dwellrq.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest; + if (handlerParcelDwellRequest != null) + { + handlerParcelDwellRequest(dwellrq.Data.LocalID, this); + } + return true; + } + + #endregion Parcel related packets + + #region Estate Packets + + private bool HandleEstateOwnerMessage(IClientAPI sender, Packet Pack) + { + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; + //m_log.Debug(messagePacket.ToString()); + GodLandStatRequest handlerLandStatRequest; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (messagePacket.AgentData.SessionID != SessionId || + messagePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + switch (Utils.BytesToString(messagePacket.MethodData.Method)) + { + case "getinfo": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice); + } + return true; + 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), Culture.NumberFormatInfo)), + (float)Convert.ToDecimal(Utils.BytesToString(messagePacket.ParamList[5].Parameter), Culture.NumberFormatInfo), + Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[6].Parameter)), + convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); + } + return true; + // 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); + } + } + } + + return true; + 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], Culture.NumberFormatInfo); + float highValue = (float)Convert.ToDecimal(splitField[2], Culture.NumberFormatInfo); + + OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue); + } + } + } + return true; + case "texturecommit": + OnCommitEstateTerrainTextureRequest(this); + return true; + 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, Culture.NumberFormatInfo); + tmp = Utils.BytesToString(messagePacket.ParamList[1].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo); + tmp = Utils.BytesToString(messagePacket.ParamList[2].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainLowerLimit = (float)Convert.ToDecimal(tmp, Culture.NumberFormatInfo); + 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), Culture.NumberFormatInfo); + 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), Culture.NumberFormatInfo); + + 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); + } + } + } + + return true; + 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); + + } + } + return true; + 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); + } + } + return true; + 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))); + + } + return true; + 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); + } + return true; + case "instantmessage": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + if (messagePacket.ParamList.Length < 2) + return true; + + UUID invoice = messagePacket.MethodData.Invoice; + UUID sessionID = messagePacket.AgentData.SessionID; + + UUID SenderID; + string SenderName; + string Message; + + if (messagePacket.ParamList.Length < 5) + { + SenderID = AgentId; + SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter); + Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter); + } + else + { + SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); + SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter); + Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter); + } + + OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); + } + return true; + 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); + + OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics); + } + return true; + case "teleporthomeuser": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UUID Prey; + + UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); + + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + } + return true; + case "teleporthomeallusers": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + OnEstateTeleportAllUsersHomeRequest(this, invoice, SenderID); + } + return true; + case "colliders": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 1, 0, "", this); + } + return true; + case "scripts": + handlerLandStatRequest = OnLandStatRequest; + if (handlerLandStatRequest != null) + { + handlerLandStatRequest(0, 0, 0, "", this); + } + return true; + 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)); + } + } + } + + } + + + } + return true; + + 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)); + + EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo; + if (handlerEstateChangeInfo != null) + { + handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); + } + } + return true; + + default: + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + return true; + } + + //int parcelID, uint reportType, uint requestflags, string filter + + //lsrp.RequestData.ParcelLocalID; + //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts + //lsrp.RequestData.RequestFlags; + //lsrp.RequestData.Filter; + +// return true; + } + + private bool HandleRequestRegionInfo(IClientAPI sender, Packet Pack) + { + RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (mPacket.SessionID != SessionId || + mPacket.AgentID != AgentId) + return true; + } + #endregion + + RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest; + if (handlerRegionInfoRequest != null) + { + handlerRegionInfoRequest(this); + } + return true; + } + + private bool HandleEstateCovenantRequest(IClientAPI sender, Packet Pack) + { + + //EstateCovenantRequestPacket.AgentDataBlock epack = + // ((EstateCovenantRequestPacket)Pack).AgentData; + + EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest; + if (handlerEstateCovenantRequest != null) + { + handlerEstateCovenantRequest(this); + } + return true; + + } + + #endregion Estate Packets + + #region GodPackets + + private bool HandleRequestGodlikePowers(IClientAPI sender, Packet Pack) + { + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + UUID token = rblock.Token; + + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + + RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers; + + if (handlerReqGodlikePowers != null) + { + handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this); + } + + return true; + } + + private bool HandleGodUpdateRegionInfoUpdate(IClientAPI client, Packet Packet) + { + GodUpdateRegionInfoPacket GodUpdateRegionInfo = + (GodUpdateRegionInfoPacket)Packet; + + GodUpdateRegionInfoUpdate handlerGodUpdateRegionInfo = OnGodUpdateRegionInfoUpdate; + if (handlerGodUpdateRegionInfo != null) + { + handlerGodUpdateRegionInfo(this, + GodUpdateRegionInfo.RegionInfo.BillableFactor, + GodUpdateRegionInfo.RegionInfo.EstateID, + GodUpdateRegionInfo.RegionInfo.RegionFlags, + GodUpdateRegionInfo.RegionInfo.SimName, + GodUpdateRegionInfo.RegionInfo.RedirectGridX, + GodUpdateRegionInfo.RegionInfo.RedirectGridY); + return true; + } + return false; + } + + private bool HandleSimWideDeletes(IClientAPI client, Packet Packet) + { + SimWideDeletesPacket SimWideDeletesRequest = + (SimWideDeletesPacket)Packet; + SimWideDeletesDelegate handlerSimWideDeletesRequest = OnSimWideDeletes; + if (handlerSimWideDeletesRequest != null) + { + handlerSimWideDeletesRequest(this, SimWideDeletesRequest.AgentData.AgentID,(int)SimWideDeletesRequest.DataBlock.Flags,SimWideDeletesRequest.DataBlock.TargetID); + return true; + } + return false; + } + + private bool HandleGodlikeMessage(IClientAPI client, Packet Packet) + { + GodlikeMessagePacket GodlikeMessage = + (GodlikeMessagePacket)Packet; + + GodlikeMessage handlerGodlikeMessage = onGodlikeMessage; + if (handlerGodlikeMessage != null) + { + handlerGodlikeMessage(this, + GodlikeMessage.MethodData.Invoice, + GodlikeMessage.MethodData.Method, + GodlikeMessage.ParamList[0].Parameter); + return true; + } + return false; + } + + private bool HandleSaveStatePacket(IClientAPI client, Packet Packet) + { + StateSavePacket SaveStateMessage = + (StateSavePacket)Packet; + SaveStateHandler handlerSaveStatePacket = OnSaveState; + if (handlerSaveStatePacket != null) + { + handlerSaveStatePacket(this,SaveStateMessage.AgentData.AgentID); + return true; + } + return false; + } + + private bool HandleGodKickUser(IClientAPI sender, Packet Pack) + { + GodKickUserPacket gkupack = (GodKickUserPacket)Pack; + + if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) + { + GodKickUser handlerGodKickUser = OnGodKickUser; + if (handlerGodKickUser != null) + { + handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, + gkupack.UserInfo.AgentID, gkupack.UserInfo.KickFlags, 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); + return true; + } + #endregion GodPackets + + #region Economy/Transaction Packets + + private bool HandleMoneyBalanceRequest(IClientAPI sender, Packet Pack) + { + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (moneybalancerequestpacket.AgentData.SessionID != SessionId || + moneybalancerequestpacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest; + + if (handlerMoneyBalanceRequest != null) + { + handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + } + + return true; + } + private bool HandleEconomyDataRequest(IClientAPI sender, Packet Pack) + { + EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; + if (handlerEconomoyDataRequest != null) + { + handlerEconomoyDataRequest(AgentId); + } + return true; + } + private bool HandleRequestPayPrice(IClientAPI sender, Packet Pack) + { + RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + + RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice; + if (handlerRequestPayPrice != null) + { + handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); + } + return true; + } + private bool HandleObjectSaleInfo(IClientAPI sender, Packet Pack) + { + ObjectSaleInfoPacket objectSaleInfoPacket = (ObjectSaleInfoPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objectSaleInfoPacket.AgentData.SessionID != SessionId || + objectSaleInfoPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo; + if (handlerObjectSaleInfo != null) + { + foreach (ObjectSaleInfoPacket.ObjectDataBlock d + in objectSaleInfoPacket.ObjectData) + { + handlerObjectSaleInfo(this, + objectSaleInfoPacket.AgentData.AgentID, + objectSaleInfoPacket.AgentData.SessionID, + d.LocalID, + d.SaleType, + d.SalePrice); + } + } + return true; + } + private bool HandleObjectBuy(IClientAPI sender, Packet Pack) + { + ObjectBuyPacket objectBuyPacket = (ObjectBuyPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objectBuyPacket.AgentData.SessionID != SessionId || + objectBuyPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ObjectBuy handlerObjectBuy = OnObjectBuy; + + if (handlerObjectBuy != 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); + } + } + return true; + } + + #endregion Economy/Transaction Packets + + #region Script Packets + private bool HandleGetScriptRunning(IClientAPI sender, Packet Pack) + { + GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; + + GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning; + if (handlerGetScriptRunning != null) + { + handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); + } + return true; + } + private bool HandleSetScriptRunning(IClientAPI sender, Packet Pack) + { + SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (setScriptRunning.AgentData.SessionID != SessionId || + setScriptRunning.AgentData.AgentID != AgentId) + return true; + } + #endregion + + SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning; + if (handlerSetScriptRunning != null) + { + handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); + } + return true; + } + + private bool HandleScriptReset(IClientAPI sender, Packet Pack) + { + ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (scriptResetPacket.AgentData.SessionID != SessionId || + scriptResetPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ScriptReset handlerScriptReset = OnScriptReset; + if (handlerScriptReset != null) + { + handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); + } + return true; + } + + #endregion Script Packets + + #region Gesture Managment + + private bool HandleActivateGestures(IClientAPI sender, Packet Pack) + { + ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (activateGesturePacket.AgentData.SessionID != SessionId || + activateGesturePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ActivateGesture handlerActivateGesture = OnActivateGesture; + if (handlerActivateGesture != null) + { + handlerActivateGesture(this, + activateGesturePacket.Data[0].AssetID, + activateGesturePacket.Data[0].ItemID); + } + else m_log.Error("Null pointer for activateGesture"); + + return true; + } + private bool HandleDeactivateGestures(IClientAPI sender, Packet Pack) + { + DeactivateGesturesPacket deactivateGesturePacket = (DeactivateGesturesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (deactivateGesturePacket.AgentData.SessionID != SessionId || + deactivateGesturePacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture; + if (handlerDeactivateGesture != null) + { + handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); + } + return true; + } + private bool HandleObjectOwner(IClientAPI sender, Packet Pack) + { + ObjectOwnerPacket objectOwnerPacket = (ObjectOwnerPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (objectOwnerPacket.AgentData.SessionID != SessionId || + objectOwnerPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + List localIDs = new List(); + + foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) + localIDs.Add(d.ObjectLocalID); + + ObjectOwner handlerObjectOwner = OnObjectOwner; + if (handlerObjectOwner != null) + { + handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); + } + return true; + } + + #endregion Gesture Managment + + private bool HandleAgentFOV(IClientAPI sender, Packet Pack) + { + AgentFOVPacket fovPacket = (AgentFOVPacket)Pack; + + if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter) + { + m_agentFOVCounter = fovPacket.FOVBlock.GenCounter; + AgentFOV handlerAgentFOV = OnAgentFOV; + if (handlerAgentFOV != null) + { + handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle); + } + } + return true; + } + + #region unimplemented handlers + + private bool HandleViewerStats(IClientAPI sender, Packet Pack) + { + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); + return true; + } + + private bool HandleMapItemRequest(IClientAPI sender, Packet Pack) + { + MapItemRequestPacket mirpk = (MapItemRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (mirpk.AgentData.SessionID != SessionId || + mirpk.AgentData.AgentID != AgentId) + return true; + } + #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); + + } + return true; + } + + private bool HandleTransferAbort(IClientAPI sender, Packet Pack) + { + return true; + } + + private bool HandleMuteListRequest(IClientAPI sender, Packet Pack) + { + MuteListRequestPacket muteListRequest = + (MuteListRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (muteListRequest.AgentData.SessionID != SessionId || + muteListRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + MuteListRequest handlerMuteListRequest = OnMuteListRequest; + if (handlerMuteListRequest != null) + { + handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); + } + else + { + SendUseCachedMuteList(); + } + return true; + } + + private bool HandleUpdateMuteListEntry(IClientAPI client, Packet Packet) + { + UpdateMuteListEntryPacket UpdateMuteListEntry = + (UpdateMuteListEntryPacket)Packet; + MuteListEntryUpdate handlerUpdateMuteListEntry = OnUpdateMuteListEntry; + if (handlerUpdateMuteListEntry != null) + { + handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, + Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), + UpdateMuteListEntry.MuteData.MuteType, + UpdateMuteListEntry.AgentData.AgentID); + return true; + } + return false; + } + + private bool HandleRemoveMuteListEntry(IClientAPI client, Packet Packet) + { + RemoveMuteListEntryPacket RemoveMuteListEntry = + (RemoveMuteListEntryPacket)Packet; + MuteListEntryRemove handlerRemoveMuteListEntry = OnRemoveMuteListEntry; + if (handlerRemoveMuteListEntry != null) + { + handlerRemoveMuteListEntry(this, + RemoveMuteListEntry.MuteData.MuteID, + Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), + RemoveMuteListEntry.AgentData.AgentID); + return true; + } + return false; + } + + private bool HandleUserReport(IClientAPI client, Packet Packet) + { + UserReportPacket UserReport = + (UserReportPacket)Packet; + + NewUserReport handlerUserReport = OnUserReport; + if (handlerUserReport != null) + { + handlerUserReport(this, + Utils.BytesToString(UserReport.ReportData.AbuseRegionName), + UserReport.ReportData.AbuserID, + UserReport.ReportData.Category, + UserReport.ReportData.CheckFlags, + Utils.BytesToString(UserReport.ReportData.Details), + UserReport.ReportData.ObjectID, + UserReport.ReportData.Position, + UserReport.ReportData.ReportType, + UserReport.ReportData.ScreenshotID, + Utils.BytesToString(UserReport.ReportData.Summary), + UserReport.AgentData.AgentID); + return true; + } + return false; + } + + private bool HandleSendPostcard(IClientAPI client, Packet packet) + { +// SendPostcardPacket SendPostcard = +// (SendPostcardPacket)packet; + SendPostcard handlerSendPostcard = OnSendPostcard; + if (handlerSendPostcard != null) + { + handlerSendPostcard(this); + return true; + } + return false; + } + + private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) + { + return true; + } + + private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) + { + return true; + } + + private bool HandleInventoryDescendents(IClientAPI sender, Packet Pack) + { + return true; + } + + #endregion unimplemented handlers + + #region Dir handlers + + private bool HandleDirPlacesQuery(IClientAPI sender, Packet Pack) + { + DirPlacesQueryPacket dirPlacesQueryPacket = (DirPlacesQueryPacket)Pack; + //m_log.Debug(dirPlacesQueryPacket.ToString()); + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dirPlacesQueryPacket.AgentData.SessionID != SessionId || + dirPlacesQueryPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleDirFindQuery(IClientAPI sender, Packet Pack) + { + DirFindQueryPacket dirFindQueryPacket = (DirFindQueryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dirFindQueryPacket.AgentData.SessionID != SessionId || + dirFindQueryPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + DirFindQuery handlerDirFindQuery = OnDirFindQuery; + if (handlerDirFindQuery != null) + { + handlerDirFindQuery(this, + dirFindQueryPacket.QueryData.QueryID, + Utils.BytesToString( + dirFindQueryPacket.QueryData.QueryText), + dirFindQueryPacket.QueryData.QueryFlags, + dirFindQueryPacket.QueryData.QueryStart); + } + return true; + } + + private bool HandleDirLandQuery(IClientAPI sender, Packet Pack) + { + DirLandQueryPacket dirLandQueryPacket = (DirLandQueryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dirLandQueryPacket.AgentData.SessionID != SessionId || + dirLandQueryPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleDirPopularQuery(IClientAPI sender, Packet Pack) + { + DirPopularQueryPacket dirPopularQueryPacket = (DirPopularQueryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dirPopularQueryPacket.AgentData.SessionID != SessionId || + dirPopularQueryPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery; + if (handlerDirPopularQuery != null) + { + handlerDirPopularQuery(this, + dirPopularQueryPacket.QueryData.QueryID, + dirPopularQueryPacket.QueryData.QueryFlags); + } + return true; + } + + private bool HandleDirClassifiedQuery(IClientAPI sender, Packet Pack) + { + DirClassifiedQueryPacket dirClassifiedQueryPacket = (DirClassifiedQueryPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (dirClassifiedQueryPacket.AgentData.SessionID != SessionId || + dirClassifiedQueryPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleEventInfoRequest(IClientAPI sender, Packet Pack) + { + EventInfoRequestPacket eventInfoRequestPacket = (EventInfoRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventInfoRequestPacket.AgentData.SessionID != SessionId || + eventInfoRequestPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnEventInfoRequest != null) + { + OnEventInfoRequest(this, eventInfoRequestPacket.EventData.EventID); + } + return true; + } + + #endregion + + #region Calling Card + + private bool HandleOfferCallingCard(IClientAPI sender, Packet Pack) + { + OfferCallingCardPacket offerCallingCardPacket = (OfferCallingCardPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (offerCallingCardPacket.AgentData.SessionID != SessionId || + offerCallingCardPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnOfferCallingCard != null) + { + OnOfferCallingCard(this, + offerCallingCardPacket.AgentBlock.DestID, + offerCallingCardPacket.AgentBlock.TransactionID); + } + return true; + } + + private bool HandleAcceptCallingCard(IClientAPI sender, Packet Pack) + { + AcceptCallingCardPacket acceptCallingCardPacket = (AcceptCallingCardPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (acceptCallingCardPacket.AgentData.SessionID != SessionId || + acceptCallingCardPacket.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + + private bool HandleDeclineCallingCard(IClientAPI sender, Packet Pack) + { + DeclineCallingCardPacket declineCallingCardPacket = (DeclineCallingCardPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (declineCallingCardPacket.AgentData.SessionID != SessionId || + declineCallingCardPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (OnDeclineCallingCard != null) + { + OnDeclineCallingCard(this, + declineCallingCardPacket.TransactionBlock.TransactionID); + } + return true; + } + + #endregion Calling Card + + #region Groups + + private bool HandleActivateGroup(IClientAPI sender, Packet Pack) + { + ActivateGroupPacket activateGroupPacket = (ActivateGroupPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (activateGroupPacket.AgentData.SessionID != SessionId || + activateGroupPacket.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.ActivateGroup(this, activateGroupPacket.AgentData.GroupID); + m_GroupsModule.SendAgentGroupDataUpdate(this); + } + return true; + + } + + private bool HandleGroupVoteHistoryRequest(IClientAPI client, Packet Packet) + { + GroupVoteHistoryRequestPacket GroupVoteHistoryRequest = + (GroupVoteHistoryRequestPacket)Packet; + GroupVoteHistoryRequest handlerGroupVoteHistoryRequest = OnGroupVoteHistoryRequest; + if (handlerGroupVoteHistoryRequest != null) + { + handlerGroupVoteHistoryRequest(this, GroupVoteHistoryRequest.AgentData.AgentID,GroupVoteHistoryRequest.AgentData.SessionID,GroupVoteHistoryRequest.GroupData.GroupID,GroupVoteHistoryRequest.TransactionData.TransactionID); + return true; + } + return false; + } + + private bool HandleGroupActiveProposalsRequest(IClientAPI client, Packet Packet) + { + GroupActiveProposalsRequestPacket GroupActiveProposalsRequest = + (GroupActiveProposalsRequestPacket)Packet; + GroupActiveProposalsRequest handlerGroupActiveProposalsRequest = OnGroupActiveProposalsRequest; + if (handlerGroupActiveProposalsRequest != null) + { + handlerGroupActiveProposalsRequest(this, GroupActiveProposalsRequest.AgentData.AgentID,GroupActiveProposalsRequest.AgentData.SessionID,GroupActiveProposalsRequest.GroupData.GroupID,GroupActiveProposalsRequest.TransactionData.TransactionID); + return true; + } + return false; + } + + private bool HandleGroupAccountDetailsRequest(IClientAPI client, Packet Packet) + { + GroupAccountDetailsRequestPacket GroupAccountDetailsRequest = + (GroupAccountDetailsRequestPacket)Packet; + GroupAccountDetailsRequest handlerGroupAccountDetailsRequest = OnGroupAccountDetailsRequest; + if (handlerGroupAccountDetailsRequest != null) + { + handlerGroupAccountDetailsRequest(this, GroupAccountDetailsRequest.AgentData.AgentID,GroupAccountDetailsRequest.AgentData.GroupID,GroupAccountDetailsRequest.MoneyData.RequestID,GroupAccountDetailsRequest.AgentData.SessionID); + return true; + } + return false; + } + + private bool HandleGroupAccountSummaryRequest(IClientAPI client, Packet Packet) + { + GroupAccountSummaryRequestPacket GroupAccountSummaryRequest = + (GroupAccountSummaryRequestPacket)Packet; + GroupAccountSummaryRequest handlerGroupAccountSummaryRequest = OnGroupAccountSummaryRequest; + if (handlerGroupAccountSummaryRequest != null) + { + handlerGroupAccountSummaryRequest(this, GroupAccountSummaryRequest.AgentData.AgentID,GroupAccountSummaryRequest.AgentData.GroupID); + return true; + } + return false; + } + + private bool HandleGroupTransactionsDetailsRequest(IClientAPI client, Packet Packet) + { + GroupAccountTransactionsRequestPacket GroupAccountTransactionsRequest = + (GroupAccountTransactionsRequestPacket)Packet; + GroupAccountTransactionsRequest handlerGroupAccountTransactionsRequest = OnGroupAccountTransactionsRequest; + if (handlerGroupAccountTransactionsRequest != null) + { + handlerGroupAccountTransactionsRequest(this, GroupAccountTransactionsRequest.AgentData.AgentID,GroupAccountTransactionsRequest.AgentData.GroupID,GroupAccountTransactionsRequest.MoneyData.RequestID,GroupAccountTransactionsRequest.AgentData.SessionID); + return true; + } + return false; + } + + private bool HandleGroupTitlesRequest(IClientAPI sender, Packet Pack) + { + GroupTitlesRequestPacket groupTitlesRequest = + (GroupTitlesRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitlesRequest.AgentData.SessionID != SessionId || + groupTitlesRequest.AgentData.AgentID != AgentId) + return true; + } + #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 = + Util.StringToBytes256(d.Name); + groupTitlesReply.GroupData[i].RoleID = + d.UUID; + groupTitlesReply.GroupData[i].Selected = + d.Selected; + i++; + } + + OutPacket(groupTitlesReply, ThrottleOutPacketType.Task); + } + return true; + } + private bool HandleGroupProfileRequest(IClientAPI sender, Packet Pack) + { + GroupProfileRequestPacket groupProfileRequest = + (GroupProfileRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupProfileRequest.AgentData.SessionID != SessionId || + groupProfileRequest.AgentData.AgentID != AgentId) + return true; + } + #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 = Util.StringToBytes256(d.Name); + groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter); + groupProfileReply.GroupData.ShowInList = d.ShowInList; + groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(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); + } + return true; + } + private bool HandleGroupMembersRequest(IClientAPI sender, Packet Pack) + { + GroupMembersRequestPacket groupMembersRequestPacket = + (GroupMembersRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupMembersRequestPacket.AgentData.SessionID != SessionId || + groupMembersRequestPacket.AgentData.AgentID != AgentId) + return true; + } + #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++) + { + 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 = + Util.StringToBytes256(m.OnlineStatus); + groupMembersReply.MemberData[i].AgentPowers = + m.AgentPowers; + groupMembersReply.MemberData[i].Title = + Util.StringToBytes256(m.Title); + groupMembersReply.MemberData[i].IsOwner = + m.IsOwner; + } + OutPacket(groupMembersReply, ThrottleOutPacketType.Task); + if (members.Count == 0) + return true; + } + } + return true; + } + private bool HandleGroupRoleDataRequest(IClientAPI sender, Packet Pack) + { + GroupRoleDataRequestPacket groupRolesRequest = + (GroupRoleDataRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRolesRequest.AgentData.SessionID != SessionId || + groupRolesRequest.AgentData.AgentID != AgentId) + return true; + } + #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 = + Util.StringToBytes256(d.Name); + groupRolesReply.RoleData[i].Title = + Util.StringToBytes256(d.Title); + groupRolesReply.RoleData[i].Description = + Util.StringToBytes1024(d.Description); + groupRolesReply.RoleData[i].Powers = + d.Powers; + groupRolesReply.RoleData[i].Members = + (uint)d.Members; + + i++; + } + + OutPacket(groupRolesReply, ThrottleOutPacketType.Task); + } + return true; + } + private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack) + { + GroupRoleMembersRequestPacket groupRoleMembersRequest = + (GroupRoleMembersRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleMembersRequest.AgentData.SessionID != SessionId || + groupRoleMembersRequest.AgentData.AgentID != AgentId) + return true; + } + #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; + + groupRoleMembersReply.MemberData = + new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; + + for (int i = 0; i < pairs; i++) + { + GroupRoleMembersData d = mappings[0]; + mappings.RemoveAt(0); + + groupRoleMembersReply.MemberData[i] = + new GroupRoleMembersReplyPacket.MemberDataBlock(); + + groupRoleMembersReply.MemberData[i].RoleID = + d.RoleID; + groupRoleMembersReply.MemberData[i].MemberID = + d.MemberID; + } + + OutPacket(groupRoleMembersReply, ThrottleOutPacketType.Task); + } + } + return true; + } + private bool HandleCreateGroupRequest(IClientAPI sender, Packet Pack) + { + CreateGroupRequestPacket createGroupRequest = + (CreateGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (createGroupRequest.AgentData.SessionID != SessionId || + createGroupRequest.AgentData.AgentID != AgentId) + return true; + } + #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); + } + return true; + } + private bool HandleUpdateGroupInfo(IClientAPI sender, Packet Pack) + { + UpdateGroupInfoPacket updateGroupInfo = + (UpdateGroupInfoPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (updateGroupInfo.AgentData.SessionID != SessionId || + updateGroupInfo.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + } + + return true; + } + private bool HandleSetGroupAcceptNotices(IClientAPI sender, Packet Pack) + { + SetGroupAcceptNoticesPacket setGroupAcceptNotices = + (SetGroupAcceptNoticesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (setGroupAcceptNotices.AgentData.SessionID != SessionId || + setGroupAcceptNotices.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.SetGroupAcceptNotices(this, + setGroupAcceptNotices.Data.GroupID, + setGroupAcceptNotices.Data.AcceptNotices, + setGroupAcceptNotices.NewData.ListInProfile); + } + + return true; + } + private bool HandleGroupTitleUpdate(IClientAPI sender, Packet Pack) + { + GroupTitleUpdatePacket groupTitleUpdate = + (GroupTitleUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupTitleUpdate.AgentData.SessionID != SessionId || + groupTitleUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.GroupTitleUpdate(this, + groupTitleUpdate.AgentData.GroupID, + groupTitleUpdate.AgentData.TitleRoleID); + } + + return true; + } + private bool HandleParcelDeedToGroup(IClientAPI sender, Packet Pack) + { + ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; + if (m_GroupsModule != null) + { + ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; + if (handlerParcelDeedToGroup != null) + { + handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, this); + + } + } + + return true; + } + private bool HandleGroupNoticesListRequest(IClientAPI sender, Packet Pack) + { + GroupNoticesListRequestPacket groupNoticesListRequest = + (GroupNoticesListRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticesListRequest.AgentData.SessionID != SessionId || + groupNoticesListRequest.AgentData.AgentID != AgentId) + return true; + } + #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 = + Util.StringToBytes256(g.FromName); + groupNoticesListReply.Data[i].Subject = + Util.StringToBytes256(g.Subject); + groupNoticesListReply.Data[i].HasAttachment = + g.HasAttachment; + groupNoticesListReply.Data[i].AssetType = + g.AssetType; + i++; + } + + OutPacket(groupNoticesListReply, ThrottleOutPacketType.Task); + } + + return true; + } + private bool HandleGroupNoticeRequest(IClientAPI sender, Packet Pack) + { + GroupNoticeRequestPacket groupNoticeRequest = + (GroupNoticeRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupNoticeRequest.AgentData.SessionID != SessionId || + groupNoticeRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.GroupNoticeRequest(this, + groupNoticeRequest.Data.GroupNoticeID); + } + return true; + } + private bool HandleGroupRoleUpdate(IClientAPI sender, Packet Pack) + { + GroupRoleUpdatePacket groupRoleUpdate = + (GroupRoleUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleUpdate.AgentData.SessionID != SessionId || + groupRoleUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + } + return true; + } + private bool HandleGroupRoleChanges(IClientAPI sender, Packet Pack) + { + GroupRoleChangesPacket groupRoleChanges = + (GroupRoleChangesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (groupRoleChanges.AgentData.SessionID != SessionId || + groupRoleChanges.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + } + return true; + } + private bool HandleJoinGroupRequest(IClientAPI sender, Packet Pack) + { + JoinGroupRequestPacket joinGroupRequest = + (JoinGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (joinGroupRequest.AgentData.SessionID != SessionId || + joinGroupRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.JoinGroupRequest(this, + joinGroupRequest.GroupData.GroupID); + } + return true; + } + private bool HandleLeaveGroupRequest(IClientAPI sender, Packet Pack) + { + LeaveGroupRequestPacket leaveGroupRequest = + (LeaveGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (leaveGroupRequest.AgentData.SessionID != SessionId || + leaveGroupRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + m_GroupsModule.LeaveGroupRequest(this, + leaveGroupRequest.GroupData.GroupID); + } + return true; + } + private bool HandleEjectGroupMemberRequest(IClientAPI sender, Packet Pack) + { + EjectGroupMemberRequestPacket ejectGroupMemberRequest = + (EjectGroupMemberRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (ejectGroupMemberRequest.AgentData.SessionID != SessionId || + ejectGroupMemberRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + foreach (EjectGroupMemberRequestPacket.EjectDataBlock e + in ejectGroupMemberRequest.EjectData) + { + m_GroupsModule.EjectGroupMemberRequest(this, + ejectGroupMemberRequest.GroupData.GroupID, + e.EjecteeID); + } + } + return true; + } + private bool HandleInviteGroupRequest(IClientAPI sender, Packet Pack) + { + InviteGroupRequestPacket inviteGroupRequest = + (InviteGroupRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (inviteGroupRequest.AgentData.SessionID != SessionId || + inviteGroupRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + if (m_GroupsModule != null) + { + foreach (InviteGroupRequestPacket.InviteDataBlock b in + inviteGroupRequest.InviteData) + { + m_GroupsModule.InviteGroupRequest(this, + inviteGroupRequest.GroupData.GroupID, + b.InviteeID, + b.RoleID); + } + } + return true; + } + + #endregion Groups + + private bool HandleStartLure(IClientAPI sender, Packet Pack) + { + StartLurePacket startLureRequest = (StartLurePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (startLureRequest.AgentData.SessionID != SessionId || + startLureRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + StartLure handlerStartLure = OnStartLure; + if (handlerStartLure != null) + handlerStartLure(startLureRequest.Info.LureType, + Utils.BytesToString( + startLureRequest.Info.Message), + startLureRequest.TargetData[0].TargetID, + this); + return true; + } + private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) + { + TeleportLureRequestPacket teleportLureRequest = + (TeleportLureRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (teleportLureRequest.Info.SessionID != SessionId || + teleportLureRequest.Info.AgentID != AgentId) + return true; + } + #endregion + + TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest; + if (handlerTeleportLureRequest != null) + handlerTeleportLureRequest( + teleportLureRequest.Info.LureID, + teleportLureRequest.Info.TeleportFlags, + this); + return true; + } + private bool HandleClassifiedInfoRequest(IClientAPI sender, Packet Pack) + { + ClassifiedInfoRequestPacket classifiedInfoRequest = + (ClassifiedInfoRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoRequest.AgentData.SessionID != SessionId || + classifiedInfoRequest.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest; + if (handlerClassifiedInfoRequest != null) + handlerClassifiedInfoRequest( + classifiedInfoRequest.Data.ClassifiedID, + this); + return true; + } + private bool HandleClassifiedInfoUpdate(IClientAPI sender, Packet Pack) + { + ClassifiedInfoUpdatePacket classifiedInfoUpdate = + (ClassifiedInfoUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedInfoUpdate.AgentData.SessionID != SessionId || + classifiedInfoUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + return true; + } + private bool HandleClassifiedDelete(IClientAPI sender, Packet Pack) + { + ClassifiedDeletePacket classifiedDelete = + (ClassifiedDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedDelete.AgentData.SessionID != SessionId || + classifiedDelete.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete; + if (handlerClassifiedDelete != null) + handlerClassifiedDelete( + classifiedDelete.Data.ClassifiedID, + this); + return true; + } + private bool HandleClassifiedGodDelete(IClientAPI sender, Packet Pack) + { + ClassifiedGodDeletePacket classifiedGodDelete = + (ClassifiedGodDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (classifiedGodDelete.AgentData.SessionID != SessionId || + classifiedGodDelete.AgentData.AgentID != AgentId) + return true; + } + #endregion + + ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; + if (handlerClassifiedGodDelete != null) + handlerClassifiedGodDelete( + classifiedGodDelete.Data.ClassifiedID, + this); + return true; + } + private bool HandleEventGodDelete(IClientAPI sender, Packet Pack) + { + EventGodDeletePacket eventGodDelete = + (EventGodDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventGodDelete.AgentData.SessionID != SessionId || + eventGodDelete.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + return true; + } + private bool HandleEventNotificationAddRequest(IClientAPI sender, Packet Pack) + { + EventNotificationAddRequestPacket eventNotificationAdd = + (EventNotificationAddRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationAdd.AgentData.SessionID != SessionId || + eventNotificationAdd.AgentData.AgentID != AgentId) + return true; + } + #endregion + + EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest; + if (handlerEventNotificationAddRequest != null) + handlerEventNotificationAddRequest( + eventNotificationAdd.EventData.EventID, this); + return true; + } + private bool HandleEventNotificationRemoveRequest(IClientAPI sender, Packet Pack) + { + EventNotificationRemoveRequestPacket eventNotificationRemove = + (EventNotificationRemoveRequestPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (eventNotificationRemove.AgentData.SessionID != SessionId || + eventNotificationRemove.AgentData.AgentID != AgentId) + return true; + } + #endregion + + EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; + if (handlerEventNotificationRemoveRequest != null) + handlerEventNotificationRemoveRequest( + eventNotificationRemove.EventData.EventID, this); + return true; + } + private bool HandleRetrieveInstantMessages(IClientAPI sender, Packet Pack) + { + RetrieveInstantMessagesPacket rimpInstantMessagePack = (RetrieveInstantMessagesPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (rimpInstantMessagePack.AgentData.SessionID != SessionId || + rimpInstantMessagePack.AgentData.AgentID != AgentId) + return true; + } + #endregion + + RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages; + if (handlerRetrieveInstantMessages != null) + handlerRetrieveInstantMessages(this); + return true; + } + private bool HandlePickDelete(IClientAPI sender, Packet Pack) + { + PickDeletePacket pickDelete = + (PickDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickDelete.AgentData.SessionID != SessionId || + pickDelete.AgentData.AgentID != AgentId) + return true; + } + #endregion + + PickDelete handlerPickDelete = OnPickDelete; + if (handlerPickDelete != null) + handlerPickDelete(this, pickDelete.Data.PickID); + return true; + } + private bool HandlePickGodDelete(IClientAPI sender, Packet Pack) + { + PickGodDeletePacket pickGodDelete = + (PickGodDeletePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickGodDelete.AgentData.SessionID != SessionId || + pickGodDelete.AgentData.AgentID != AgentId) + return true; + } + #endregion + + PickGodDelete handlerPickGodDelete = OnPickGodDelete; + if (handlerPickGodDelete != null) + handlerPickGodDelete(this, + pickGodDelete.AgentData.AgentID, + pickGodDelete.Data.PickID, + pickGodDelete.Data.QueryID); + return true; + } + private bool HandlePickInfoUpdate(IClientAPI sender, Packet Pack) + { + PickInfoUpdatePacket pickInfoUpdate = + (PickInfoUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (pickInfoUpdate.AgentData.SessionID != SessionId || + pickInfoUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + 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); + return true; + } + private bool HandleAvatarNotesUpdate(IClientAPI sender, Packet Pack) + { + AvatarNotesUpdatePacket avatarNotesUpdate = + (AvatarNotesUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarNotesUpdate.AgentData.SessionID != SessionId || + avatarNotesUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate; + if (handlerAvatarNotesUpdate != null) + handlerAvatarNotesUpdate(this, + avatarNotesUpdate.Data.TargetID, + Utils.BytesToString(avatarNotesUpdate.Data.Notes)); + return true; + } + private bool HandleAvatarInterestsUpdate(IClientAPI sender, Packet Pack) + { + AvatarInterestsUpdatePacket avatarInterestUpdate = + (AvatarInterestsUpdatePacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (avatarInterestUpdate.AgentData.SessionID != SessionId || + avatarInterestUpdate.AgentData.AgentID != AgentId) + return true; + } + #endregion + + AvatarInterestUpdate handlerAvatarInterestUpdate = OnAvatarInterestUpdate; + if (handlerAvatarInterestUpdate != null) + handlerAvatarInterestUpdate(this, + avatarInterestUpdate.PropertiesData.WantToMask, + Utils.BytesToString(avatarInterestUpdate.PropertiesData.WantToText), + avatarInterestUpdate.PropertiesData.SkillsMask, + Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText), + Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText)); + return true; + } + private bool HandleGrantUserRights(IClientAPI sender, Packet Pack) + { + GrantUserRightsPacket GrantUserRights = + (GrantUserRightsPacket)Pack; + #region Packet Session and User Check + if (m_checkPackets) + { + if (GrantUserRights.AgentData.SessionID != SessionId || + GrantUserRights.AgentData.AgentID != AgentId) + return true; + } + #endregion + GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights; + if (GrantUserRightsHandler != null) + GrantUserRightsHandler(this, + GrantUserRights.AgentData.AgentID, + GrantUserRights.Rights[0].AgentRelated, + GrantUserRights.Rights[0].RelatedRights); + return true; + } + private bool HandlePlacesQuery(IClientAPI sender, Packet Pack) + { + PlacesQueryPacket placesQueryPacket = + (PlacesQueryPacket)Pack; + + PlacesQuery 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); + return true; + } + + #endregion Packet Handlers + + 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 = Util.StringToBytes256(taskName); + scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName); + + 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 (nod.Attributes["name"] != null) + { + string name = nod.Attributes["name"].Value.ToLower(); + string id = nod.InnerText; + m_defaultAnimations.Add(name, (UUID)id); + } + } + } + } + + public UUID GetDefaultAnimation(string name) + { + if (m_defaultAnimations.ContainsKey(name)) + return m_defaultAnimations[name]; + return UUID.Zero; + } + + /// + /// Handler called when we receive a logout packet. + /// + /// + /// + /// + protected virtual bool HandleLogout(IClientAPI client, Packet packet) + { + if (packet.Type == PacketType.LogoutRequest) + { + if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; + } + + return Logout(client); + } + + /// + /// + /// + /// + /// + protected virtual bool Logout(IClientAPI client) + { + m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); + + Action handlerLogout = OnLogout; + + if (handlerLogout != null) + { + handlerLogout(client); + } + + return true; + } + + /// + /// 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 HandleAgentTextureCached(IClientAPI simclient, Packet packet) + { + //m_log.Debug("texture cached: " + packet.ToString()); + AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + + if (cachedtex.AgentData.SessionID != SessionId) return 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]; + + 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]; + } + + cachedresp.Header.Zerocoded = true; + OutPacket(cachedresp, ThrottleOutPacketType.Task); + + return true; + } + + protected bool HandleMultipleObjUpdate(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; + + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; + + // Can't act on Null Data + if (block.Data != null) + { + uint localId = block.ObjectLocalID; + SceneObjectPart part = tScene.GetSceneObjectPart(localId); + + 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; + + switch (block.Type) + { + case 1: + Vector3 pos1 = new Vector3(block.Data, 0); + + 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); + + 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); + + 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); + + 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: + + Vector3 scale1 = new Vector3(block.Data, 12); + Vector3 pos11 = new Vector3(block.Data, 0); + + handlerUpdatePrimScale = OnUpdatePrimScale; + if (handlerUpdatePrimScale != null) + { + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + handlerUpdatePrimScale(localId, scale1, this); + + handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; + if (handlerUpdatePrimSinglePosition != null) + { + handlerUpdatePrimSinglePosition(localId, pos11, this); + } + } + break; + case 9: + Vector3 pos2 = new Vector3(block.Data, 0); + + UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; + + if (handlerUpdateVector != null) + { + + handlerUpdateVector(localId, pos2, this); + } + break; + case 10: + Quaternion rot3 = new Quaternion(block.Data, 0, true); + + 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); + + 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); + + 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); + + 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; + } + } + } + } + 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(multiplier); + } + + /// + /// 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 + protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) + { + #region BinaryStats + LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); + #endregion BinaryStats + + OutPacket(packet, throttlePacketType, true); + } + + /// + /// This is the starting point for sending a simulator packet out to the client + /// + /// Packet to send + /// Throttling category for the packet + /// True to automatically split oversized + /// packets (the default), or false to disable splitting if the calling code + /// handles splitting manually + protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) + { + OutPacket(packet, throttlePacketType, doAutomaticSplitting, null); + } + + /// + /// This is the starting point for sending a simulator packet out to the client + /// + /// Packet to send + /// Throttling category for the packet + /// True to automatically split oversized + /// packets (the default), or false to disable splitting if the calling code + /// handles splitting manually + /// The method to be called in the event this packet is reliable + /// and unacknowledged. The server will provide normal resend capability if you do not + /// provide your own method. + protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) + { + if (m_debugPacketLevel > 0) + { + bool logPacket = true; + + if (m_debugPacketLevel <= 255 + && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage)) + logPacket = false; + + if (m_debugPacketLevel <= 200 + && (packet.Type == PacketType.ImagePacket + || packet.Type == PacketType.ImageData + || packet.Type == PacketType.LayerData + || packet.Type == PacketType.CoarseLocationUpdate)) + logPacket = false; + + if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) + logPacket = false; + + if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) + logPacket = false; + + if (logPacket) + m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); + } + + m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); + } + + public bool AddMoney(int debit) + { + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("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 + { + 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; + } + + UpdateVector 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); + + + 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; + + } + } + + /// + /// Entryway from the client to the simulator. All UDP packets from the client will end up here + /// + /// OpenMetaverse.packet + public void ProcessInPacket(Packet packet) + { + if (m_debugPacketLevel > 0) + { + bool outputPacket = true; + + if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate) + outputPacket = false; + + if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage) + outputPacket = false; + + if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) + outputPacket = false; + + if (outputPacket) + m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type); + } + + if (!ProcessPacketMethod(packet)) + m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); + + PacketPool.Instance.ReturnPacket(packet); + } + + 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; + } + + public ClientInfo GetClientInfo() + { + ClientInfo info = m_udpClient.GetClientInfo(); + + info.userEP = m_userEndPoint; + info.proxyEP = null; + info.agentcircuit = RequestClientInfo(); + + return info; + } + + public void SetClientInfo(ClientInfo info) + { + m_udpClient.SetClientInfo(info); + } + + public EndPoint GetClientEP() + { + return m_userEndPoint; + } + + #region Media Parcel Members + + 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(commandMessagePacket, ThrottleOutPacketType.Task); + } + + 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 = Util.StringToBytes256(mediaUrl); + updatePacket.DataBlock.MediaID = mediaTextureID; + updatePacket.DataBlock.MediaAutoScale = autoScale; + + updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType); + updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc); + updatePacket.DataBlockExtended.MediaWidth = mediaWidth; + updatePacket.DataBlockExtended.MediaHeight = mediaHeight; + updatePacket.DataBlockExtended.MediaLoop = mediaLoop; + + OutPacket(updatePacket, ThrottleOutPacketType.Task); + } + + #endregion + + #region Camera + + 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; + + camPropBlock[idx++] = block; + } + packet.CameraProperty = camPropBlock; + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendClearFollowCamProperties(UUID objectID) + { + ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); + packet.ObjectData.ObjectID = objectID; + OutPacket(packet, ThrottleOutPacketType.Task); + } + + #endregion + + public void SetClientOption(string option, string value) + { + switch (option) + { + default: + break; + } + } + + public string GetClientOption(string option) + { + switch (option) + { + default: + break; + } + return string.Empty; + } + + public void KillEndDone() + { + } + + #region IClientCore + + private readonly Dictionary m_clientInterfaces = new Dictionary(); + + /// + /// Register an interface on this client, should only be called in the constructor. + /// + /// + /// + protected void RegisterInterface(T iface) + { + lock (m_clientInterfaces) + { + if (!m_clientInterfaces.ContainsKey(typeof(T))) + { + m_clientInterfaces.Add(typeof(T), iface); + } + } + } + + public bool TryGet(out T iface) + { + if (m_clientInterfaces.ContainsKey(typeof(T))) + { + iface = (T)m_clientInterfaces[typeof(T)]; + return true; + } + iface = default(T); + return false; + } + + public T Get() + { + return (T)m_clientInterfaces[typeof(T)]; + } + + public void Disconnect(string reason) + { + Kick(reason); + Thread.Sleep(1000); + Close(); + } + + public void Disconnect() + { + Close(); + } + + #endregion + + public void RefreshGroupMembership() + { + if (m_GroupsModule != null) + { + GroupMembershipData[] GroupMembership = + m_GroupsModule.GetMembershipData(AgentId); + + m_groupPowers.Clear(); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + } + } + } + } + + public string Report() + { + return m_udpClient.GetStats(); + } + + public string XReport(string uptime, string version) + { + return String.Empty; + } + + /// + /// Make an asset request to the asset service in response to a client request. + /// + /// + /// + protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) + { + UUID requestID = UUID.Zero; + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) + { + requestID = new UUID(transferRequest.TransferInfo.Params, 0); + } + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + { + requestID = new UUID(transferRequest.TransferInfo.Params, 80); + } + +// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); + + m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); + } + + /// + /// When we get a reply back from the asset service in response to a client request, send back the data. + /// + /// + /// + /// + protected void AssetReceived(string id, Object sender, AssetBase asset) + { + if (asset == null) + return; + + TransferRequestPacket transferRequest = (TransferRequestPacket)sender; + + UUID requestID = UUID.Zero; + byte source = (byte)SourceType.Asset; + + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) + { + requestID = new UUID(transferRequest.TransferInfo.Params, 0); + } + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + { + requestID = new UUID(transferRequest.TransferInfo.Params, 80); + source = (byte)SourceType.SimInventoryItem; + //m_log.Debug("asset request " + requestID); + } + + // Scripts cannot be retrieved by direct request + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10) + return; + + // The asset is known to exist and is in our cache, so add it to the AssetRequests list + AssetRequestToClient req = new AssetRequestToClient(); + req.AssetInf = asset; + req.AssetRequestSource = source; + req.IsTextureRequest = false; + req.NumPackets = CalculateNumPackets(asset.Data); + req.Params = transferRequest.TransferInfo.Params; + req.RequestAssetID = requestID; + req.TransferRequestID = transferRequest.TransferInfo.TransferID; + + SendAsset(req); + } + + /// + /// Calculate the number of packets required to send the asset to the client. + /// + /// + /// + private static int CalculateNumPackets(byte[] data) + { + const uint m_maxPacketSize = 600; + int numPackets = 1; + + if (data == null) + return 0; + + if (data.LongLength > m_maxPacketSize) + { + // over max number of bytes so split up file + long restData = data.LongLength - m_maxPacketSize; + int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); + numPackets += restPackets; + } + + return numPackets; + } + + #region IClientIPEndpoint Members + + public IPAddress EndPoint + { + get + { + if (m_userEndPoint is IPEndPoint) + { + IPEndPoint ep = (IPEndPoint)m_userEndPoint; + + return ep.Address; + } + return null; + } + } + + #endregion + + public void SendRebakeAvatarTextures(UUID textureID) + { + RebakeAvatarTexturesPacket pack = + (RebakeAvatarTexturesPacket)PacketPool.Instance.GetPacket(PacketType.RebakeAvatarTextures); + + pack.TextureData = new RebakeAvatarTexturesPacket.TextureDataBlock(); + pack.TextureData.TextureID = textureID; + OutPacket(pack, ThrottleOutPacketType.Task); + } + + public struct PacketProcessor + { + public PacketMethod method; + public bool Async; + } + + public class AsyncPacketProcess + { + public bool result = false; + public readonly LLClientView ClientView = null; + public readonly Packet Pack = null; + public readonly PacketMethod Method = null; + public AsyncPacketProcess(LLClientView pClientview, PacketMethod pMethod, Packet pPack) + { + ClientView = pClientview; + Method = pMethod; + Pack = pPack; + } + } + + public static OSD BuildEvent(string eventName, OSD eventBody) + { + OSDMap osdEvent = new OSDMap(2); + osdEvent.Add("message", new OSDString(eventName)); + osdEvent.Add("body", eventBody); + + return osdEvent; + } + + public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages) + { + AvatarInterestsReplyPacket packet = (AvatarInterestsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarInterestsReply); + + packet.AgentData = new AvatarInterestsReplyPacket.AgentDataBlock(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.AvatarID = avatarID; + + packet.PropertiesData = new AvatarInterestsReplyPacket.PropertiesDataBlock(); + packet.PropertiesData.WantToMask = wantMask; + packet.PropertiesData.WantToText = Utils.StringToBytes(wantText); + packet.PropertiesData.SkillsMask = skillsMask; + packet.PropertiesData.SkillsText = Utils.StringToBytes(skillsText); + packet.PropertiesData.LanguagesText = Utils.StringToBytes(languages); + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendChangeUserRights(UUID agentID, UUID friendID, int rights) + { + ChangeUserRightsPacket packet = (ChangeUserRightsPacket)PacketPool.Instance.GetPacket(PacketType.ChangeUserRights); + + packet.AgentData = new ChangeUserRightsPacket.AgentDataBlock(); + packet.AgentData.AgentID = agentID; + + packet.Rights = new ChangeUserRightsPacket.RightsBlock[1]; + packet.Rights[0] = new ChangeUserRightsPacket.RightsBlock(); + packet.Rights[0].AgentRelated = friendID; + packet.Rights[0].RelatedRights = rights; + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) + { + ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); + dialog.Data.ObjectID = objectId; + dialog.Data.ChatChannel = chatChannel; + dialog.Data.ImageID = UUID.Zero; + dialog.Data.ObjectName = Util.StringToBytes256(objectname); + // this is the username of the *owner* + dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); + dialog.Data.LastName = Util.StringToBytes256(ownerLastName); + dialog.Data.Message = Util.StringToBytes256(message); + + ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1]; + buttons[0] = new ScriptDialogPacket.ButtonsBlock(); + buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!"); + dialog.Buttons = buttons; + OutPacket(dialog, ThrottleOutPacketType.Task); + } + + public void StopFlying(ISceneEntity p) + { + if (p is ScenePresence) + { + ScenePresence presence = p as ScenePresence; + // It turns out to get the agent to stop flying, you have to feed it stop flying velocities + // There's no explicit message to send the client to tell it to stop flying.. it relies on the + // velocity, collision plane and avatar height + + // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air + // when the avatar stands up + + Vector3 pos = presence.AbsolutePosition; + + if (presence.Appearance.AvatarHeight != 127.0f) + pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f)); + else + pos += new Vector3(0f, 0f, (1.56f/6f)); + + presence.AbsolutePosition = pos; + + // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. + // Collision plane below the avatar's position a 6th of the avatar's height is suitable. + // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a + // certain amount.. because the LLClient wouldn't land in that situation anyway. + + // why are we still testing for this really old height value default??? + if (presence.Appearance.AvatarHeight != 127.0f) + presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f); + else + presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f)); + + + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = + CreateImprovedTerseBlock(p, false); + + const float TIME_DILATION = 1.0f; + ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); + + + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + + packet.ObjectData[0] = block; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } + + //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, + // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); + } + + public void SendPlacesReply(UUID queryID, UUID transactionID, + PlacesReplyData[] data) + { + PlacesReplyPacket reply = null; + PlacesReplyPacket.QueryDataBlock[] dataBlocks = + new PlacesReplyPacket.QueryDataBlock[0]; + + for (int i = 0 ; i < data.Length ; i++) + { + PlacesReplyPacket.QueryDataBlock block = + new PlacesReplyPacket.QueryDataBlock(); + + block.OwnerID = data[i].OwnerID; + block.Name = Util.StringToBytes256(data[i].Name); + block.Desc = Util.StringToBytes1024(data[i].Desc); + block.ActualArea = data[i].ActualArea; + block.BillableArea = data[i].BillableArea; + block.Flags = data[i].Flags; + block.GlobalX = data[i].GlobalX; + block.GlobalY = data[i].GlobalY; + block.GlobalZ = data[i].GlobalZ; + block.SimName = Util.StringToBytes256(data[i].SimName); + block.SnapshotID = data[i].SnapshotID; + block.Dwell = data[i].Dwell; + block.Price = data[i].Price; + + if (reply != null && reply.Length + block.Length > 1400) + { + OutPacket(reply, ThrottleOutPacketType.Task); + + reply = null; + dataBlocks = new PlacesReplyPacket.QueryDataBlock[0]; + } + + if (reply == null) + { + reply = (PlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.PlacesReply); + reply.AgentData = new PlacesReplyPacket.AgentDataBlock(); + reply.AgentData.AgentID = AgentId; + reply.AgentData.QueryID = queryID; + + reply.TransactionData = new PlacesReplyPacket.TransactionDataBlock(); + reply.TransactionData.TransactionID = transactionID; + + reply.QueryData = dataBlocks; + } + + Array.Resize(ref dataBlocks, dataBlocks.Length + 1); + dataBlocks[dataBlocks.Length - 1] = block; + reply.QueryData = dataBlocks; + } + if (reply != null) + OutPacket(reply, ThrottleOutPacketType.Task); + } + } +} -- cgit v1.1 From 74e981e796d28f52458acf3ebfc40fbde54e22db Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 May 2011 09:56:27 -0700 Subject: One more bug fix concerning library items that weren't being copied to user's inventory. Also commented verbose debug message. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 43903ce..025c6e6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5982,7 +5982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); for (int i = 0; i < nowWearing.WearableData.Length; i++) { - m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID); + //m_log.DebugFormat("[XXX]: Wearable type {0} item {1}", nowWearing.WearableData[i].WearableType, nowWearing.WearableData[i].ItemID); AvatarWearingArgs.Wearable wearable = new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, nowWearing.WearableData[i].WearableType); -- cgit v1.1 From c0a69bfaab2f945f2f871ce6b93c81931ffc2f9a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 8 May 2011 22:50:04 -0700 Subject: The map is seriously broken. This doesn't fix it, but at least provides one more piece of data that seems to be required -- agent flags, which seem to be different in Viewer 2. WARNING: changes IClientAPI. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 025c6e6..1635a2d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8264,13 +8264,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } #endregion - string mapName = Util.UTF8.GetString(map.NameData.Name, 0, map.NameData.Name.Length - 1); RequestMapName handlerMapNameRequest = OnMapNameRequest; if (handlerMapNameRequest != null) { - handlerMapNameRequest(this, mapName); + handlerMapNameRequest(this, mapName, map.AgentData.Flags); } return true; } -- cgit v1.1 From 8a5f6dc7a534fcdcfc877a6eac2553b18532e760 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 9 May 2011 10:25:42 -0700 Subject: Fixes gray tiles on map search for viewers 1. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1635a2d..1da9d5e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1363,7 +1363,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendMapBlock(List mapBlocks, uint flag) { - MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); int maxsend = 10; -- cgit v1.1 From 5f9edd195c702fac57ab76bca1c0357bce224868 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 13 May 2011 03:24:19 +0100 Subject: Fix broken inventory links on viewer 2. It appears that if the viewer requests a folder containing links, we must also send the folders that contain the link targets first. This was tested with Kokua 0.1.0 WIP though I predict it will also work with other viewer 2s --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1da9d5e..5a2c45c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1612,14 +1612,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]); else { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending inventory folder details packet to {0} for folder {1}", Name, folderID); OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); currentPacket = null; } - } if (currentPacket != null) + { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending inventory folder details packet to {0} for folder {1}", Name, folderID); OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); + } } private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder) -- cgit v1.1 From 8129e64e2acea6509d5c3a80425f6aa68baa037c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 31 May 2011 19:25:01 +0100 Subject: Fill in the new OwnerData field in the LLUDP ScriptDialog message. If we don't do this then viewer 2.8 crashes. Resolves http://opensimulator.org/mantis/view.php?id=5510 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5a2c45c..821a370 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2213,7 +2213,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(loadURL, ThrottleOutPacketType.Task); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog( + string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, + UUID textureID, int ch, string[] buttonlabels) { ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); dialog.Data.ObjectID = objectID; @@ -2231,6 +2233,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); } dialog.Buttons = buttons; + + dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1]; + dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock(); + dialog.OwnerData[0].OwnerID = ownerID; + OutPacket(dialog, ThrottleOutPacketType.Task); } @@ -2293,8 +2300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff; } - - SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); viewertime.TimeInfo.SunDirection = Position; viewertime.TimeInfo.SunAngVelocity = Velocity; -- cgit v1.1 From c67fa72d5628725581b61b7a16c37955e154006d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 31 May 2011 19:57:08 +0100 Subject: When sending an LLUDP MoneyBalanceReply message, fill out the transaction item description even though there is none. This is to deal with a problem in libomv where calling ToBytes() without this crashes because of an ItemDescription.Lnegth dereference. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 821a370..d8fcb62 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1469,6 +1469,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP money.MoneyData.TransactionSuccess = success; money.MoneyData.Description = description; money.MoneyData.MoneyBalance = balance; + money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); OutPacket(money, ThrottleOutPacketType.Task); } -- cgit v1.1 From e33cedfd427779a3df844150869eb07b664849df Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 10:26:58 -0700 Subject: HG Landmarks now working. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d8fcb62..3a9e4b7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8301,6 +8301,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AssetLandmark lm; if (lmid != UUID.Zero) { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); AssetBase lma = m_assetService.Get(lmid.ToString()); @@ -8341,13 +8342,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; if (handlerTeleportLandmarkRequest != null) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + handlerTeleportLandmarkRequest(this, lm); } 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; -- cgit v1.1 From 623706d988d47c3c0f3d46b68e77f9c54038d3f5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 11:33:44 -0700 Subject: HG Landmarks bug fix: pull landmark asset data from user's asset server when user is traveling. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3a9e4b7..cefceb0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8308,10 +8308,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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); + + // Let's try to search in the user's home asset server + lma = FindAssetInUserAssetServer(lmid.ToString()); + + if (lma == null) + { + // Really doesn't exist + 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 @@ -8356,6 +8364,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private AssetBase FindAssetInUserAssetServer(string id) + { + AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode); + if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); + } + + return null; + } + private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack) { TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; -- cgit v1.1 From b5518dc90631014a4aa3dbb6c27fd5d4c9f612c9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 10 Jun 2011 20:40:14 +0100 Subject: minor: Add some commented out destructor logging messages for potential future use. At the moment, client and scene objects are being garbage collected as expected, at least in simple scenarios. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cefceb0..f53e236 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -428,6 +428,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Properties +// ~LLClientView() +// { +// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); +// } + /// /// Constructor /// -- cgit v1.1 From 5700c582ba3727678dfd87f80dab8d09da88df63 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jul 2011 22:28:17 +0100 Subject: refactor: rename bool returning GetAgentInventoryItem() to CanGetAgentInventoryItem() to improve code readability --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f53e236..c176c2b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -7548,13 +7548,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) { - if (!invAccess.GetAgentInventoryItem(this, itemID, requestID)) + if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) return false; - } else + { return false; - + } } } } @@ -7568,7 +7568,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { 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); -- cgit v1.1 From a9ba9d4a9ee2515d2541fc536525ebed3d101606 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 15 Jul 2011 23:51:55 +0100 Subject: change async parameter name in AddLocalPacketHandler since it becomes a reserved keyword in .net 5 Also adds some method doc. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 24 ++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c176c2b..8414f8b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -574,22 +574,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP return result; } + /// + /// Add a handler for the given packet type. + /// + /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// are received then please us ethe synchronous version of this method. + /// + /// + /// true if the handler was added. This is currently always the case. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler) { return AddLocalPacketHandler(packetType, handler, true); } - public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool async) + /// + /// Add a handler for the given packet type. + /// + /// + /// + /// + /// If true, when the packet is received it is handled on its own thread rather than on the main inward bound + /// packet handler thread. This vastly increases respnosiveness but some packets need to be handled + /// synchronously. + /// + /// true if the handler was added. This is currently always the case. + public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) { bool result = false; lock (m_packetHandlers) { if (!m_packetHandlers.ContainsKey(packetType)) { - m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = async }); + m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync }); result = true; } } + return result; } -- cgit v1.1 From 6fc74b36d1d0f7dcd6f013893c3189a3f989431c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 18 Jul 2011 04:54:21 +0100 Subject: Make various tweaks to undo code in an effort to get things working better. Undo rotation and position appear to be working. Resizing a single prim appears to be working, though the undo has to be done twice. Resizing a group of prims still does not work properly - possibly because in the UndoState we don't store a knowledge of when we're resizing a whole group rather than individual prims. This needs to be addressed. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8414f8b..fa35bd8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11242,6 +11242,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { + // Do this once since fetch parts creates a new array. + SceneObjectPart[] parts = part.ParentGroup.Parts; + for (int j = 0; j < parts.Length; j++) + { + part.StoreUndoState(); + parts[j].IgnoreUndoUpdate = true; + } + // UUID partId = part.UUID; UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; @@ -11257,6 +11265,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSinglePosition(localId, pos1, this); } break; + case 2: Quaternion rot1 = new Quaternion(block.Data, 0, true); @@ -11267,6 +11276,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSingleRotation(localId, rot1, this); } break; + case 3: Vector3 rotPos = new Vector3(block.Data, 0); Quaternion rot2 = new Quaternion(block.Data, 12, true); @@ -11279,6 +11289,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); } break; + case 4: case 20: Vector3 scale4 = new Vector3(block.Data, 0); @@ -11290,8 +11301,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimScale(localId, scale4, this); } break; - case 5: + case 5: Vector3 scale1 = new Vector3(block.Data, 12); Vector3 pos11 = new Vector3(block.Data, 0); @@ -11308,6 +11319,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + case 9: Vector3 pos2 = new Vector3(block.Data, 0); @@ -11315,10 +11327,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdateVector != null) { - handlerUpdateVector(localId, pos2, this); } break; + case 10: Quaternion rot3 = new Quaternion(block.Data, 0, true); @@ -11329,6 +11341,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimRotation(localId, rot3, this); } break; + case 11: Vector3 pos3 = new Vector3(block.Data, 0); Quaternion rot4 = new Quaternion(block.Data, 12, true); @@ -11352,6 +11365,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimGroupScale(localId, scale7, this); } break; + case 13: Vector3 scale2 = new Vector3(block.Data, 12); Vector3 pos4 = new Vector3(block.Data, 0); @@ -11371,6 +11385,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + case 29: Vector3 scale5 = new Vector3(block.Data, 12); Vector3 pos5 = new Vector3(block.Data, 0); @@ -11388,6 +11403,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + case 21: Vector3 scale6 = new Vector3(block.Data, 12); Vector3 pos6 = new Vector3(block.Data, 0); @@ -11404,13 +11420,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } break; + default: - m_log.Debug("[CLIENT] MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); break; } + + for (int j = 0; j < parts.Length; j++) + parts[j].IgnoreUndoUpdate = false; } } } + return true; } -- cgit v1.1 From 430a4aeba8e98b8285ea3ebdf264baf429a55e22 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Jul 2011 03:01:54 +0100 Subject: Fix undo for resizing linksets This involves implementing a boolean in UndoState to signal whether the undo needs to be done for an entire group/linkset or just a single prim Resizing individual components of linksets is still dodgy. Resizing still has to be down twice, since for some reason the client is sending two multiobjectupdate packets on every resize except the very first. This applies to single prims and linksets. Need to look into this. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fa35bd8..4c0b53c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11220,8 +11220,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) { MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + + if (multipleupdate.AgentData.SessionID != SessionId) + return false; + +// m_log.DebugFormat( +// "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); + Scene tScene = (Scene)m_scene; for (int i = 0; i < multipleupdate.ObjectData.Length; i++) @@ -11242,15 +11247,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - // Do this once since fetch parts creates a new array. - SceneObjectPart[] parts = part.ParentGroup.Parts; - for (int j = 0; j < parts.Length; j++) - { - part.StoreUndoState(); - parts[j].IgnoreUndoUpdate = true; - } +// m_log.DebugFormat( +// "[CLIENT]: Processing block {0} type {1} for {2} {3}", +// i, block.Type, part.Name, part.LocalId); + +// // Do this once since fetch parts creates a new array. +// SceneObjectPart[] parts = part.ParentGroup.Parts; +// for (int j = 0; j < parts.Length; j++) +// { +// part.StoreUndoState(); +// parts[j].IgnoreUndoUpdate = true; +// } - // UUID partId = part.UUID; UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; switch (block.Type) @@ -11394,6 +11402,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdatePrimGroupScale != null) { // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + part.StoreUndoState(true); + part.IgnoreUndoUpdate = true; handlerUpdatePrimGroupScale(localId, scale5, this); handlerUpdateVector = OnUpdatePrimGroupPosition; @@ -11401,7 +11411,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerUpdateVector(localId, pos5, this); } + + part.IgnoreUndoUpdate = false; } + break; case 21: @@ -11426,8 +11439,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP break; } - for (int j = 0; j < parts.Length; j++) - parts[j].IgnoreUndoUpdate = false; +// for (int j = 0; j < parts.Length; j++) +// parts[j].IgnoreUndoUpdate = false; } } } -- cgit v1.1 From c94dc95844c5a43483a30807353aaebf658b015e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Jul 2011 03:27:16 +0100 Subject: fix undo when resizing of non-root individual prims in a linkset undo resize, rotation and position still needs fixing when only editing root prim of a linkset --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4c0b53c..a34ad62 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11424,6 +11424,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUpdatePrimScale = OnUpdatePrimScale; if (handlerUpdatePrimScale != null) { + part.StoreUndoState(false); + part.IgnoreUndoUpdate = true; + // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); handlerUpdatePrimScale(localId, scale6, this); handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; @@ -11431,6 +11434,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerUpdatePrimSinglePosition(localId, pos6, this); } + + part.IgnoreUndoUpdate = false; } break; -- cgit v1.1 From 7c468cda360b9a9382986c3a029b799fd49bf898 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Jul 2011 03:38:22 +0100 Subject: Stop undo of just the root prim position in the linkset from shifting the whole linkset. However, what happens now is that undo just doesn't do anything when the root prim is selected on its own. This requires more code than just fiddling with undo states. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a34ad62..00115cc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11224,8 +11224,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (multipleupdate.AgentData.SessionID != SessionId) return false; -// m_log.DebugFormat( -// "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); + m_log.DebugFormat( + "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); Scene tScene = (Scene)m_scene; @@ -11247,9 +11247,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { -// m_log.DebugFormat( -// "[CLIENT]: Processing block {0} type {1} for {2} {3}", -// i, block.Type, part.Name, part.LocalId); + m_log.DebugFormat( + "[CLIENT]: Processing block {0} type {1} for {2} {3}", + i, block.Type, part.Name, part.LocalId); // // Do this once since fetch parts creates a new array. // SceneObjectPart[] parts = part.ParentGroup.Parts; -- cgit v1.1 From 62325829ecab7d956416ff0450faa3f90f267e6c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Jul 2011 05:14:58 +0100 Subject: comment out all kinds of debugging guff --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 00115cc..a34ad62 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11224,8 +11224,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (multipleupdate.AgentData.SessionID != SessionId) return false; - m_log.DebugFormat( - "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); +// m_log.DebugFormat( +// "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); Scene tScene = (Scene)m_scene; @@ -11247,9 +11247,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - m_log.DebugFormat( - "[CLIENT]: Processing block {0} type {1} for {2} {3}", - i, block.Type, part.Name, part.LocalId); +// m_log.DebugFormat( +// "[CLIENT]: Processing block {0} type {1} for {2} {3}", +// i, block.Type, part.Name, part.LocalId); // // Do this once since fetch parts creates a new array. // SceneObjectPart[] parts = part.ParentGroup.Parts; -- cgit v1.1 From 4cdc8806fbc0d0d9b0ff878b30a4491b347cf2dc Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 23 Jul 2011 11:39:32 +0100 Subject: Fix LLTextBox to work with the updated libOMV --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a34ad62..60f0075 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12083,7 +12083,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task); } - public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) + public void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId) { ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); dialog.Data.ObjectID = objectId; @@ -12099,6 +12099,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP buttons[0] = new ScriptDialogPacket.ButtonsBlock(); buttons[0].ButtonLabel = Util.StringToBytes256("!!llTextBox!!"); dialog.Buttons = buttons; + + dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1]; + dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock(); + dialog.OwnerData[0].OwnerID = ownerID; + OutPacket(dialog, ThrottleOutPacketType.Task); } -- cgit v1.1 From c122489e0947300753281e88771b7a74d49869c7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 2 Aug 2011 23:41:12 +0100 Subject: Partially fix autopilot/go here This now works again except that it requires a click or avatar mvmt to get going This is because the ScenePresence.HandleAgentUpdate() method doesn't trigger until the client does something significant, at which point autopilot takes over. Even clicking is enough to trigger. This will be improved presently. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 79 ++++++++++------------ 1 file changed, 34 insertions(+), 45 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 60f0075..bb491a1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5266,6 +5266,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); + + AddGenericPacketHandler("autopilot", HandleAutopilot); } #region Packet Handlers @@ -5308,7 +5310,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP ); } else + { update = true; + } // These should be ordered from most-likely to // least likely to change. I've made an initial @@ -5316,6 +5320,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (update) { +// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); + AgentUpdateArgs arg = new AgentUpdateArgs(); arg.AgentID = x.AgentID; arg.BodyRotation = x.BodyRotation; @@ -11609,54 +11615,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP return false; } - /// - /// Breaks down the genericMessagePacket into specific events - /// - /// - /// - /// - public void DecipherGenericMessage(string gmMethod, UUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams) + protected void HandleAutopilot(Object sender, string method, List args) { - switch (gmMethod) + try { - 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; - } - - UpdateVector 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); - - - 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; + float locx = 0f; + float locy = 0f; + float locz = 0f; + uint regionX = 0; + uint regionY = 0; + try + { + Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(args[0]) - (float)regionX; + locy = Convert.ToSingle(args[1]) - (float)regionY; + locz = Convert.ToSingle(args[2]); + } + catch (InvalidCastException) + { + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; + } + UpdateVector handlerAutoPilotGo = OnAutoPilotGo; + if (handlerAutoPilotGo != null) + { + handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[LLCLIENTVIEW]: HandleAutopilot exception {0} {1}", e.Message, e.StackTrace); } } -- cgit v1.1 From 2964467708871f5932c46ad04e002a5506dd7732 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Aug 2011 22:11:05 +0100 Subject: get rid of vestigal move to parameters --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 44 +++++++--------------- 1 file changed, 14 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bb491a1..4a36b5d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -231,7 +231,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event UpdateVector OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; @@ -11617,36 +11617,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected void HandleAutopilot(Object sender, string method, List args) { - try - { - float locx = 0f; - float locy = 0f; - float locz = 0f; - uint regionX = 0; - uint regionY = 0; - try - { - Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(args[0]) - (float)regionX; - locy = Convert.ToSingle(args[1]) - (float)regionY; - locz = Convert.ToSingle(args[2]); - } - catch (InvalidCastException) - { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; - } + float locx = 0; + float locy = 0; + float locz = 0; + uint regionX = 0; + uint regionY = 0; - UpdateVector handlerAutoPilotGo = OnAutoPilotGo; - if (handlerAutoPilotGo != null) - { - handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); - } - } - catch (Exception e) - { - m_log.ErrorFormat("[LLCLIENTVIEW]: HandleAutopilot exception {0} {1}", e.Message, e.StackTrace); - } + Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(args[0]) - (float)regionX; + locy = Convert.ToSingle(args[1]) - (float)regionY; + locz = Convert.ToSingle(args[2]); + + Action handlerAutoPilotGo = OnAutoPilotGo; + if (handlerAutoPilotGo != null) + handlerAutoPilotGo(new Vector3(locx, locy, locz)); } /// -- cgit v1.1 From 92e96d394a1712ed16b0a7835dd2ccfde01f3fee Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Aug 2011 23:11:07 +0100 Subject: When an NPC is created, stop telling neighbouring regions to expect a child agent --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4a36b5d..46d7f78 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectAttach OnObjectAttach; public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; - public event GenericCall1 OnCompleteMovementToRegion; + public event Action OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; @@ -6195,10 +6195,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) { - GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; + Action handlerCompleteMovementToRegion = OnCompleteMovementToRegion; if (handlerCompleteMovementToRegion != null) { - handlerCompleteMovementToRegion(sender); + handlerCompleteMovementToRegion(sender, true); } handlerCompleteMovementToRegion = null; -- cgit v1.1 From 4cb8d6379ddb39cfb8b30a63475e154a00a78110 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Aug 2011 00:59:31 +0100 Subject: Stop trying to deregister caps or close child agents when an NPC is removed --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 46d7f78..977918a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -512,7 +512,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer.Flush(m_udpClient); // Remove ourselves from the scene - m_scene.RemoveClient(AgentId); + m_scene.RemoveClient(AgentId, true); // We can't reach into other scenes and close the connection // We need to do this over grid communications -- cgit v1.1 From 5d6c9644faf6aeac38410af9cff97adfef88d7aa Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Aug 2011 01:47:37 +0100 Subject: early code to allow scripts to force npcs not to fly when moving to target this is to allow walking on prims. it will be up to the script writer to be sure that there is a continuous path. currently implemented in osNpcMoveToTarget(), but none of this is final. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 977918a..1d35973 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -231,7 +231,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; @@ -11628,9 +11628,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP locy = Convert.ToSingle(args[1]) - (float)regionY; locz = Convert.ToSingle(args[2]); - Action handlerAutoPilotGo = OnAutoPilotGo; + Action handlerAutoPilotGo = OnAutoPilotGo; if (handlerAutoPilotGo != null) - handlerAutoPilotGo(new Vector3(locx, locy, locz)); + handlerAutoPilotGo(new Vector3(locx, locy, locz), false); } /// -- cgit v1.1 From c1a34cd8da293e63d3cba70b5271c9a297789db2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Aug 2011 00:53:05 +0100 Subject: Don't try to save changed attachment states when an NPC with attachments is removed from the scene. This is done by introducing a PresenceType enum into ScenePresence which currently has two values, User and Npc. This seems better than a SaveAttachments flag in terms of code comprehension, though I'm still slightly uneasy about introducing these semantics to core objects --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1d35973..f71871e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -692,7 +692,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_scene.AddNewClient(this); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From 33a894f3d2cc95a7a512b86f39f3c6a6afabb015 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 27 Aug 2011 00:15:21 +0100 Subject: refactor: move SOP.IsAttachment and AttachmentPoint up into SOG to avoid pointless duplication of identical values --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f71871e..dc9a6ed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4756,7 +4756,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { SceneObjectPart part = (SceneObjectPart)entity; - attachPoint = part.AttachmentPoint; + if (part.ParentGroup != null) + attachPoint = part.ParentGroup.AttachmentPoint; + else + attachPoint = 0; + collisionPlane = Vector4.Zero; position = part.RelativePosition; velocity = part.Velocity; @@ -4913,10 +4917,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP //update.JointType = 0; update.Material = data.Material; update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim - if (data.IsAttachment) + if (data.ParentGroup != null && data.ParentGroup.IsAttachment) { update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); - update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16)); + update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); } else { -- cgit v1.1 From 083ba72b28fb424e1e3edbc90c6a79d49d2215bf Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Aug 2011 23:33:01 +0100 Subject: Fix a bug where the non-root parts of rezzed objects that had previously been attachments were sending their old attachment values to the client. The root part state is the canonical value, so always send that instead. Sending conflicting attachments states for non-root parts of a rezzed object is enough to crash the client. Fixes http://opensimulator.org/mantis/view.php?id=5664. Many thanks to mewtwo0641 for some fantastic qa work on this one. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dc9a6ed..661e9db 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4761,6 +4761,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP else attachPoint = 0; +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", +// attachPoint, part.Name, part.LocalId, Name); + collisionPlane = Vector4.Zero; position = part.RelativePosition; velocity = part.Velocity; @@ -4925,9 +4929,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { update.NameValue = Utils.EmptyBytes; - update.State = data.Shape.State; + + // The root part state is the canonical state for all parts of the object. The other part states in the + // case for attachments may contain conflicting values that can end up crashing the viewer. + update.State = data.ParentGroup.RootPart.Shape.State; } +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", +// update.State, data.Name, data.LocalId, Name); + update.ObjectData = objectData; update.ParentID = data.ParentID; update.PathBegin = data.Shape.PathBegin; -- cgit v1.1 From 095b3e5756bb3160b30c9c5670ba008fa13d2e66 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 1 Sep 2011 01:22:28 +0100 Subject: Remove pointless cluttering SOP.ParentGroup != null checks. The only times when ParentGroup might be null is during regression tests (which might not be a valid thing) and when scene objects are being constructed from the database. At all other times it's not possible for a SOP not to have a SOG parent. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 661e9db..e9ee7be 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4756,10 +4756,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { SceneObjectPart part = (SceneObjectPart)entity; - if (part.ParentGroup != null) - attachPoint = part.ParentGroup.AttachmentPoint; - else - attachPoint = 0; + attachPoint = part.ParentGroup.AttachmentPoint; // m_log.DebugFormat( // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", @@ -4921,7 +4918,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //update.JointType = 0; update.Material = data.Material; update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim - if (data.ParentGroup != null && data.ParentGroup.IsAttachment) + if (data.ParentGroup.IsAttachment) { update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); -- cgit v1.1 From de19dc3024e5359f594d0a32c593d905163c24ea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 18:58:58 +0100 Subject: refactor: rename SOG/SOP.GetProperties() to SendPropertiesToClient() to reflect what it actually does This also makes it consistent with some other methods that send data to the client. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e9ee7be..b5c6742 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4119,8 +4119,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP while (updatesThisCall < m_maxUpdates) { lock (m_entityProps.SyncRoot) - if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) - break; + if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) + break; ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; if (update.SendFamilyProps) -- cgit v1.1 From d358125cac4e01194dae4b1f0bc9afc87e463f76 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 22 Sep 2011 00:16:05 +0100 Subject: Reinstate option to land an npc when it reaches a target. This is moved into ScenePresence for now as a general facility --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b5c6742..ce2ff86 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -231,7 +231,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; @@ -11640,9 +11640,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP locy = Convert.ToSingle(args[1]) - (float)regionY; locz = Convert.ToSingle(args[2]); - Action handlerAutoPilotGo = OnAutoPilotGo; + Action handlerAutoPilotGo = OnAutoPilotGo; if (handlerAutoPilotGo != null) - handlerAutoPilotGo(new Vector3(locx, locy, locz), false); + handlerAutoPilotGo(new Vector3(locx, locy, locz), false, false); } /// -- cgit v1.1 From e77c919290e166f19e77f3ef040418dd39f2f5bd Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Mon, 3 Oct 2011 11:55:54 -0700 Subject: Remove usage of Linden packet types from inside Attachments Module and interface --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ce2ff86..29dce17 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6079,9 +6079,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; if (handlerRezMultipleAttachments != null) { - RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; - handlerRezMultipleAttachments(this, rez.HeaderData, - rez.ObjectData); + List> rezlist = new List>(); + foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in ((RezMultipleAttachmentsFromInvPacket)Pack).ObjectData) + rezlist.Add(new KeyValuePair(obj.ItemID, obj.AttachmentPt)); + handlerRezMultipleAttachments(this, rezlist); } return true; -- cgit v1.1 From c5826d589ab2f33a71105bc2d3015ffbb7dd2973 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 12 Oct 2011 19:35:40 +0100 Subject: minor: insert some commented out log lines which are a blunt but useful instrument to see packet expiry and received acks --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 29dce17..a4887ad 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3625,7 +3625,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) { - // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime); + // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber); // Remove the update packet from the list of packets waiting for acknowledgement // because we are requeuing the list of updates. They will be resent in new packets -- cgit v1.1 From 20da04fd0c909a00c0cdc2585f242e95c868801a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 13 Oct 2011 21:42:24 +0100 Subject: More method doc and formatting changes. Makes DestroyOdeStructures() private --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a4887ad..024ebce 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4744,6 +4744,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP position = presence.OffsetPosition; velocity = presence.Velocity; acceleration = Vector3.Zero; + + // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating + // in that direction, even though we don't model this on the server. Implementing this in the future + // may improve movement smoothness. +// acceleration = new Vector3(1, 0, 0); + angularVelocity = Vector3.Zero; rotation = presence.Rotation; -- cgit v1.1 From aa19ccf65c9cd235e0ba941e9832c5240df4412c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 14 Oct 2011 01:45:46 +0100 Subject: refactor: rename IClientAPI.SendPrimUpdate() to SendEntityUpdate() since it sends entity updates (including presence ones), not just prims. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 024ebce..c30e559 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3592,7 +3592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Generate one of the object update packets based on PrimUpdateFlags /// and broadcast the packet to clients /// - public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) + public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) { //double priority = m_prioritizer.GetUpdatePriority(this, entity); uint priority = m_prioritizer.GetUpdatePriority(this, entity); -- cgit v1.1 From 96ff2c63ed47e29a92cc79b6e8753d21e54da061 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 17 Oct 2011 20:37:01 +0100 Subject: Add avatar names to debug packet output --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c30e559..95532e8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11617,7 +11617,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (logPacket) - m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); + m_log.DebugFormat("[CLIENT]: Packet OUT {0} to {1}", packet.Type, Name); } m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); @@ -11672,7 +11672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP outputPacket = false; if (outputPacket) - m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type); + m_log.DebugFormat("[CLIENT]: Packet IN {0} from {1}", packet.Type, Name); } if (!ProcessPacketMethod(packet)) -- cgit v1.1 From 120114e96becc6fee1311300359dcefaf4013c0e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 17 Oct 2011 20:50:29 +0100 Subject: refactor: Make IClientAPI.DebugPacketFormat a property rather than a setter without a getter --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 25 +++++++++------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 95532e8..7affa45 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -64,7 +64,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. /// - protected int m_debugPacketLevel = 0; + public int DebugPacketLevel { get; set; } #region Events @@ -477,11 +477,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP RegisterLocalPacketHandlers(); } - public void SetDebugPacketLevel(int newDebug) - { - m_debugPacketLevel = newDebug; - } - #region Client Methods /// @@ -11595,25 +11590,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// provide your own method. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) { - if (m_debugPacketLevel > 0) + if (DebugPacketLevel > 0) { bool logPacket = true; - if (m_debugPacketLevel <= 255 + if (DebugPacketLevel <= 255 && (packet.Type == PacketType.SimStats || packet.Type == PacketType.SimulatorViewerTimeMessage)) logPacket = false; - if (m_debugPacketLevel <= 200 + if (DebugPacketLevel <= 200 && (packet.Type == PacketType.ImagePacket || packet.Type == PacketType.ImageData || packet.Type == PacketType.LayerData || packet.Type == PacketType.CoarseLocationUpdate)) logPacket = false; - if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) + if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) logPacket = false; - if (m_debugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) + if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) logPacket = false; if (logPacket) @@ -11658,17 +11653,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// OpenMetaverse.packet public void ProcessInPacket(Packet packet) { - if (m_debugPacketLevel > 0) + if (DebugPacketLevel > 0) { bool outputPacket = true; - if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate) + if (DebugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate) outputPacket = false; - if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage) + if (DebugPacketLevel <= 200 && packet.Type == PacketType.RequestImage) outputPacket = false; - if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) + if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) outputPacket = false; if (outputPacket) -- cgit v1.1 From e210d958219d0c400544f849202279c78feeea9d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 27 Oct 2011 02:50:58 +0100 Subject: Don't blow our brains out if LLClientView.BulkInventoryUpdate() is wrongly passed a null node reference. Addresses worst aspect of http://opensimulator.org/mantis/view.php?id=5752 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7affa45..9f24ee7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1958,8 +1958,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendBulkUpdateInventoryItem((InventoryItemBase)node); else if (node is InventoryFolderBase) SendBulkUpdateInventoryFolder((InventoryFolderBase)node); + else if (node != null) + m_log.ErrorFormat("[CLIENT]: {0} sent unknown inventory node named {1}", Name, node.Name); else - m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name); + m_log.ErrorFormat("[CLIENT]: {0} sent null inventory node", Name); } protected void SendBulkUpdateInventoryItem(InventoryItemBase item) -- cgit v1.1 From 5ae8de3c00cdf5d200b3158116a1e1fd9a404229 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 29 Oct 2011 01:39:48 +0100 Subject: Stop setting _position as well as m_taint_position in ODECharacter.Position setting position at the same time as taint appears to undermine the whole purpose of taint testing doesn't reveal any obvious regressions in doing this --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9f24ee7..a7f83f9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4857,8 +4857,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP data.CollisionPlane.ToBytes(objectData, 0); data.OffsetPosition.ToBytes(objectData, 16); - //data.Velocity.ToBytes(objectData, 28); - //data.Acceleration.ToBytes(objectData, 40); +// data.Velocity.ToBytes(objectData, 28); +// data.Acceleration.ToBytes(objectData, 40); data.Rotation.ToBytes(objectData, 52); //data.AngularVelocity.ToBytes(objectData, 64); -- cgit v1.1 From c7dd7b13a2058fa6855e2e78f1dbb83e9a806f95 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Nov 2011 20:38:07 +0000 Subject: Convert SendKillObject to take a list of uint rather than sending one packet per prim. More to come as we change to make use of this. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 53 +++++++++++++--------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a7f83f9..4a0b0c6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1531,38 +1531,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pc, ThrottleOutPacketType.Unknown); } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localIDs) { // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); // TODO: don't create new blocks if recycling an old packet - kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; - kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); - kill.ObjectData[0].ID = localID; + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; + for (int i = 0 ; i < localIDs.Count ; i++ ) + { + kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[i].ID = localIDs[i]; + } kill.Header.Reliable = true; kill.Header.Zerocoded = true; - if (m_scene.GetScenePresence(localID) == null) + lock (m_killRecord) { - // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race - // condition where a kill can be processed before an out-of-date update for the same object. - lock (m_killRecord) + if (localIDs.Count == 1) { - m_killRecord.Add(localID); - - // The throttle queue used here must match that being used for updates. Otherwise, there is a - // chance that a kill packet put on a separate queue will be sent to the client before an existing - // update packet on another queue. Receiving updates after kills results in unowned and undeletable - // scene objects in a viewer until that viewer is relogged in. - OutPacket(kill, ThrottleOutPacketType.Task); + if (m_scene.GetScenePresence(localIDs[0]) != null) + { + OutPacket(kill, ThrottleOutPacketType.State); + return; + } + m_killRecord.Add(localIDs[0]); + } + else + { + lock (m_entityUpdates.SyncRoot) + { + foreach (uint localID in localIDs) + m_killRecord.Add(localID); + } } } - else - { - // OutPacket(kill, ThrottleOutPacketType.State); - OutPacket(kill, ThrottleOutPacketType.Task); - } + + // The throttle queue used here must match that being used for + // updates. Otherwise, there is a chance that a kill packet put + // on a separate queue will be sent to the client before an + // existing update packet on another queue. Receiving updates + // after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); } /// @@ -11265,7 +11276,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // It's a ghost! tell the client to delete it from view. simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); + new List { localId }); } else { -- cgit v1.1 From ce8441132e43dc8e3579f413daf914d48b8f115e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 11 Nov 2011 22:37:57 +0000 Subject: Restore sending of OutPacket() for object kills removed in commit c7dd7b1. OutPacket() must be called within the m_killRecord lock. Otherwise the following event sequence is possible 1) LLClientView.ProcessEntityUpdates() passes the kill record check for a particular part suspends before OutPacket() 2) Another thread calls LLClientView.SendKillObject() to delete the same part and modifies the kill record 3) The same thread places the kill packet on the Task queue. 4) The earlier thread resumes and places the update packet on the Task queue after the kill packet. This results in a ghost part in the sim that only goes away after client relog. This commit also removes the unnecessary m_entityUpdates.SyncRoot locking in SendKillObject. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 46 ++++++++++------------ 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4a0b0c6..626ebb5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1546,41 +1546,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP kill.Header.Reliable = true; kill.Header.Zerocoded = true; - lock (m_killRecord) + if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) { - if (localIDs.Count == 1) - { - if (m_scene.GetScenePresence(localIDs[0]) != null) - { - OutPacket(kill, ThrottleOutPacketType.State); - return; - } - m_killRecord.Add(localIDs[0]); - } - else + OutPacket(kill, ThrottleOutPacketType.State); + } + else + { + // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race + // condition where a kill can be processed before an out-of-date update for the same object. + // ProcessEntityUpdates() also takes the m_killRecord lock. + lock (m_killRecord) { - lock (m_entityUpdates.SyncRoot) - { - foreach (uint localID in localIDs) - m_killRecord.Add(localID); - } + foreach (uint localID in localIDs) + m_killRecord.Add(localID); + + // The throttle queue used here must match that being used for updates. Otherwise, there is a + // chance that a kill packet put on a separate queue will be sent to the client before an existing + // update packet on another queue. Receiving updates after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); } } - - // The throttle queue used here must match that being used for - // updates. Otherwise, there is a chance that a kill packet put - // on a separate queue will be sent to the client before an - // existing update packet on another queue. Receiving updates - // after kills results in unowned and undeletable - // scene objects in a viewer until that viewer is relogged in. - OutPacket(kill, ThrottleOutPacketType.Task); } /// /// Send information about the items contained in a folder to the client. - /// - /// XXX This method needs some refactoring loving /// + /// + /// XXX This method needs some refactoring loving + /// /// The owner of the folder /// The id of the folder /// The items contained in the folder identified by folderID -- cgit v1.1 From ff36a1bc7bcd1d0fe5aecb4c5358dbb072c7ff6e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 14 Nov 2011 16:06:06 +0000 Subject: If a friends identifier which is too short is given to HGFriendsModule.GetOnlineFriends() then spit out a warning rather than failing on the String.Substring(). This is to progress http://opensimulator.org/mantis/view.php?id=5789 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 626ebb5..133da0f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11088,6 +11088,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText)); return true; } + private bool HandleGrantUserRights(IClientAPI sender, Packet Pack) { GrantUserRightsPacket GrantUserRights = @@ -11108,6 +11109,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP GrantUserRights.Rights[0].RelatedRights); return true; } + private bool HandlePlacesQuery(IClientAPI sender, Packet Pack) { PlacesQueryPacket placesQueryPacket = -- cgit v1.1 From a58f5b2f6679bfb8565741afaead7e6d8dc8c299 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 24 Nov 2011 22:08:34 +0000 Subject: When setting packet level logging via "debug packet", apply to all clients, not just root ones. Also adds scene name and client type (root|child) to logged information. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 133da0f..7d39ddc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11621,7 +11621,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (logPacket) - m_log.DebugFormat("[CLIENT]: Packet OUT {0} to {1}", packet.Type, Name); + m_log.DebugFormat( + "[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}", + Name, ChildAgentStatus() ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); } m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); @@ -11664,19 +11666,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (DebugPacketLevel > 0) { - bool outputPacket = true; + bool logPacket = true; if (DebugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate) - outputPacket = false; + logPacket = false; if (DebugPacketLevel <= 200 && packet.Type == PacketType.RequestImage) - outputPacket = false; + logPacket = false; if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) - outputPacket = false; + logPacket = false; - if (outputPacket) - m_log.DebugFormat("[CLIENT]: Packet IN {0} from {1}", packet.Type, Name); + if (logPacket) + m_log.DebugFormat( + "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", + Name, ChildAgentStatus() ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); } if (!ProcessPacketMethod(packet)) -- cgit v1.1 From f61e54892f2284b6f89bacf3069467c05b2eea11 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 8 Dec 2011 18:34:23 +0000 Subject: On a new client circuit, send the initial reply ack to let the client know it's live before sending other data. This means that avatar/appearance data of other avatars and scene objects for a client will be sent after the ack rather than possibly before. This may stop some avatars appearing grey on login. This introduces a new OpenSim.Framework.ISceneAgent to accompany the existing OpenSim.Framework.ISceneObject and ISceneEntity This allows IClientAPI to handle this as it can't reference OpenSim.Region.Framework.Interfaces --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7d39ddc..f246637 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -379,6 +379,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } + public ISceneAgent SceneAgent { get; private set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -508,6 +509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Remove ourselves from the scene m_scene.RemoveClient(AgentId, true); + SceneAgent = null; // We can't reach into other scenes and close the connection // We need to do this over grid communications @@ -687,7 +689,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_scene.AddNewClient(this, PresenceType.User); + SceneAgent = m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From af3cd00048fb6476eb5140bcfccda926627363f2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Dec 2011 23:07:53 +0000 Subject: Get rid of IScene.PresenceChildStatus() which always had to execute a lookup in favour of IClientAPI.ISceneAgent.IsChildAgent instead. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f246637..1d4be8a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -525,7 +525,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Kick(string message) { - if (!ChildAgentStatus()) + if (!SceneAgent.IsChildAgent) { KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser); kupack.UserInfo.AgentID = AgentId; @@ -2448,7 +2448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) { - if (!ChildAgentStatus()) + if (!SceneAgent.IsChildAgent) SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3())); //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); @@ -5054,14 +5054,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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); - } - #endregion /// @@ -11625,7 +11617,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (logPacket) m_log.DebugFormat( "[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}", - Name, ChildAgentStatus() ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); + Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); } m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); @@ -11682,7 +11674,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (logPacket) m_log.DebugFormat( "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", - Name, ChildAgentStatus() ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); + Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); } if (!ProcessPacketMethod(packet)) -- cgit v1.1 From 3a91085ac2364c80b53275886c8130a4b1f0e62f Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 10 Dec 2011 15:17:34 +0000 Subject: Implement handler for TeleportCancel inbound packet --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1d4be8a..7223438 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -140,6 +140,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event RequestMapName OnMapNameRequest; public event TeleportLocationRequest OnTeleportLocationRequest; public event TeleportLandmarkRequest OnTeleportLandmarkRequest; + public event TeleportCancel OnTeleportCancel; public event DisconnectUser OnDisconnectUser; public event RequestAvatarProperties OnRequestAvatarProperties; public event SetAlwaysRun OnSetAlwaysRun; @@ -5173,6 +5174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false); AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); + AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); @@ -8409,6 +8411,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private bool HandleTeleportCancel(IClientAPI sender, Packet Pack) + { + TeleportCancel handlerTeleportCancel = OnTeleportCancel; + if (handlerTeleportCancel != null) + { + handlerTeleportCancel(this); + } + return true; + } + private AssetBase FindAssetInUserAssetServer(string id) { AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode); -- cgit v1.1 From b242ceda1e7599a8e71150f3fcc9f27a64d18828 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Dec 2011 20:42:39 +0000 Subject: In AvatarFactoryModule.SetApperance(), perform ValidateBakedTextureCache() in the same thread rather than on another one. The caller is already an async thread from LLClientView so this doesn't hold up the client. However, launching on a separate thread does remove the effect of m_setAppearanceLock This was potentially allowing two different SetAppearance threads to interfere with each other, though this probably rarely happens, if at all. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7223438..9c86c74 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -575,8 +575,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Add a handler for the given packet type. /// - /// The packet is handled on its own thread. If packets must be handled in the order in which thye - /// are received then please us ethe synchronous version of this method. + /// + /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// are received then please use the synchronous version of this method. + /// /// /// /// true if the handler was added. This is currently always the case. -- cgit v1.1 From a3a17e929e7a39566a677672572433fe35d25849 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 16 Dec 2011 23:20:12 +0000 Subject: Stop generating client flags when we send out full object updates. These were entirely unused. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9c86c74..8b41c49 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -10345,6 +10345,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } return true; } + private bool HandleGroupRoleMembersRequest(IClientAPI sender, Packet Pack) { GroupRoleMembersRequestPacket groupRoleMembersRequest = -- cgit v1.1 From 0b91ec8dd2b78461cb0fcdec567a83e88a76ac87 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 19 Dec 2011 18:58:05 +0000 Subject: Migrate detailed "appearance show" report generation up to AvatarFactoryModule from AppearanceInfoModule so that it can be used in debug (inactive). Further filters "debug packet " to exclused [Request]ObjectPropertiesFamily if level is below 25. Adjust some method doc Minor changes to some logging messages. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8b41c49..f9a6643 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -441,6 +441,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode) { +// DebugPacketLevel = 1; + RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); @@ -6001,7 +6003,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // 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; @@ -11219,9 +11220,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// 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. /// + /// + /// At the moment, we always reply that there is no cached texture. + /// /// /// /// @@ -11231,7 +11233,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); - if (cachedtex.AgentData.SessionID != SessionId) return false; + if (cachedtex.AgentData.SessionID != SessionId) + return false; // TODO: don't create new blocks if recycling an old packet cachedresp.AgentData.AgentID = AgentId; @@ -11629,6 +11632,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) logPacket = false; + if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) + logPacket = false; + if (logPacket) m_log.DebugFormat( "[CLIENT]: PACKET OUT to {0} ({1}) in {2} - {3}", @@ -11686,6 +11692,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (DebugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation)) logPacket = false; + if (DebugPacketLevel <= 25 && packet.Type == PacketType.RequestObjectPropertiesFamily) + logPacket = false; + if (logPacket) m_log.DebugFormat( "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", -- cgit v1.1 From 2899de1a5c8060397e813ee853c525572a81db03 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 19 Dec 2011 19:19:05 +0000 Subject: Stop unnecessarily sending the TextureEntry in client avatar updates. As far as I know, viewers don't use this mechanism to recieve new TextureEntry data for avatars. This is done via the AvatarAppearance packet instead. Tested this back to viewer 1.23. Replacing with Utils.EmptyBytes since converting the texture entry to bytes on each AvatarUpdate (or which there are many) is not cost-free. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f9a6643..b37fd54 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4895,8 +4895,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.Scale = new Vector3(0.45f, 0.6f, 1.9f); update.Text = Utils.EmptyBytes; update.TextColor = new byte[4]; + + // Don't send texture anim for avatars - this has no meaning for them. update.TextureAnim = Utils.EmptyBytes; - update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; + + // Don't send texture entry for avatars here - this is accomplished via the AvatarAppearance packet + update.TextureEntry = Utils.EmptyBytes; +// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; + update.UpdateFlags = (uint)( PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | -- cgit v1.1 From 82df5de5cf91960ff5f50d0f0568ac6443516960 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 4 Jan 2012 16:15:05 +0000 Subject: Remove the pointless LLClientView.m_imageManager null check. Despite the code comments we never actually null it. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b37fd54..fe28ba3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -348,7 +348,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers protected Scene m_scene; - protected LLImageManager m_imageManager; + private LLImageManager m_imageManager; protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; @@ -499,8 +499,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IsActive = false; // Shutdown the image manager - if (m_imageManager != null) - m_imageManager.Close(); + m_imageManager.Close(); // Fire the callback for this connection closing if (OnConnectionClosed != null) @@ -3940,14 +3939,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) - { - ProcessTextureRequests(); - } - } - - void ProcessTextureRequests() - { - if (m_imageManager != null) m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); } @@ -7479,12 +7470,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((ImageType)block.Type == ImageType.Baked) args.Priority *= 2.0f; - // in the end, we null this, so we have to check if it's null - if (m_imageManager != null) - { - m_imageManager.EnqueueReq(args); - } + m_imageManager.EnqueueReq(args); } + return true; } -- cgit v1.1 From 3a64522267352d1c68ef99ac76c65bd3c4f9eaf1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 4 Jan 2012 21:40:15 +0000 Subject: Minor formatting changes and commented out log lines for future debugging of image manager (udp texture fetch). No significant functional changes. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fe28ba3..eb1a50e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -577,7 +577,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Add a handler for the given packet type. /// /// - /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// The packet is handled on its own thread. If packets must be handled in the order in which they /// are received then please use the synchronous version of this method. /// /// -- cgit v1.1 From ef074deb52de617743ad50ea29e286dd9c66722d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 10 Jan 2012 21:30:12 +0000 Subject: Add "show image queue " region console command This is so that we can inspect the image download queue (texture download via udp) for debugging purposes. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index eb1a50e..1e72aa2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -304,6 +304,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients + /// + /// Handles UDP texture download. + /// + public LLImageManager ImageManager { get; private set; } + private readonly LLUDPServer m_udpServer; private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; @@ -348,7 +353,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers protected Scene m_scene; - private LLImageManager m_imageManager; protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; @@ -459,7 +463,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_assetService = m_scene.RequestModuleInterface(); m_GroupsModule = scene.RequestModuleInterface(); - m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); + ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion()); m_agentId = agentId; m_sessionId = sessionId; @@ -499,7 +503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IsActive = false; // Shutdown the image manager - m_imageManager.Close(); + ImageManager.Close(); // Fire the callback for this connection closing if (OnConnectionClosed != null) @@ -3939,7 +3943,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) - m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); + ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); } public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) @@ -7470,7 +7474,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((ImageType)block.Type == ImageType.Baked) args.Priority *= 2.0f; - m_imageManager.EnqueueReq(args); + ImageManager.EnqueueReq(args); } return true; -- cgit v1.1 From 82ad9d4e04867b23b4c824c4eca7402bf476f0b7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 16 Jan 2012 22:58:58 +0000 Subject: Remove monocov and other obsolete nant build targets. monocov was a code coverage attempt 3 years ago which no longer works. other removed targets have been commented out or unused for a very long time --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1e72aa2..2553b3a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -762,9 +762,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(handshake, ThrottleOutPacketType.Task); } - /// - /// - /// public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) { AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); @@ -3480,6 +3477,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { + m_log.DebugFormat( + "[LLCLIENTVIEW]: Sending avatar appearance for {0} with {1} bytes to {2} {3}", + agentID, textureEntry.Length, Name, AgentId); + 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]; @@ -3501,7 +3502,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) { - //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); +// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); // TODO: don't create new blocks if recycling an old packet @@ -3536,6 +3537,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendAvatarDataImmediate(ISceneEntity avatar) { + m_log.DebugFormat( + "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", + avatar.Name, avatar.UUID, Name, AgentId); + ScenePresence presence = avatar as ScenePresence; if (presence == null) return; @@ -3545,7 +3550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.RegionData.RegionHandle = presence.RegionHandle; objupdate.RegionData.TimeDilation = ushort.MaxValue; - + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); -- cgit v1.1 From 59a0c50d48100527d00ea87935fdc24055249ba5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 16 Jan 2012 23:04:08 +0000 Subject: Comment out noisy log lines I accidentally included in the nant build target adjustment commit. Left in the method doc. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2553b3a..4ba441e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3477,9 +3477,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { - m_log.DebugFormat( - "[LLCLIENTVIEW]: Sending avatar appearance for {0} with {1} bytes to {2} {3}", - agentID, textureEntry.Length, Name, AgentId); +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending avatar appearance for {0} with {1} bytes to {2} {3}", +// agentID, textureEntry.Length, Name, AgentId); AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); // TODO: don't create new blocks if recycling an old packet @@ -3537,9 +3537,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendAvatarDataImmediate(ISceneEntity avatar) { - m_log.DebugFormat( - "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", - avatar.Name, avatar.UUID, Name, AgentId); +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", +// avatar.Name, avatar.UUID, Name, AgentId); ScenePresence presence = avatar as ScenePresence; if (presence == null) -- cgit v1.1 From b6f3de5028ab9a288f60b020a0dffda079dc550d Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 20 Jan 2012 23:50:37 -0500 Subject: Telehub Support: Support for viewer side of telehub management. Can manupulate Telehubs and SpawnPoints from the viewer estate managemnt tools. This is a work in progress and does not yet persist or affect teleport routing. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 39 ++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4ba441e..a94fb20 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -219,6 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event BakeTerrain OnBakeTerrain; public event RequestTerrain OnUploadTerrain; public event EstateChangeInfo OnEstateChangeInfo; + public event EstateManageTelehub OnEstateManageTelehub; public event EstateRestartSimRequest OnEstateRestartSimRequest; public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; @@ -4482,6 +4483,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task); } + public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) + { + TelehubInfoPacket packet = (TelehubInfoPacket)PacketPool.Instance.GetPacket(PacketType.TelehubInfo); + packet.TelehubBlock.ObjectID = ObjectID; + packet.TelehubBlock.ObjectName = Utils.StringToBytes(ObjectName); + packet.TelehubBlock.TelehubPos = ObjectPos; + packet.TelehubBlock.TelehubRot = ObjectRot; + + packet.SpawnPointBlock = new TelehubInfoPacket.SpawnPointBlockBlock[SpawnPoint.Count]; + for (int n = 0; n < SpawnPoint.Count; n++) + { + packet.SpawnPointBlock[n] = new TelehubInfoPacket.SpawnPointBlockBlock{SpawnPointPos = SpawnPoint[n]}; + } + + OutPacket(packet, ThrottleOutPacketType.Task); + } + #endregion #region Land Data Sending Methods @@ -8920,7 +8938,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleEstateOwnerMessage(IClientAPI sender, Packet Pack) { EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; - //m_log.Debug(messagePacket.ToString()); + // m_log.InfoFormat("[LLCLIENTVIEW]: Packet: {0}", Utils.BytesToString(messagePacket.MethodData.Method)); GodLandStatRequest handlerLandStatRequest; #region Packet Session and User Check @@ -9219,6 +9237,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP } return true; + case "telehub": + 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)); + + string command = (string)Utils.BytesToString(messagePacket.ParamList[0].Parameter); + + EstateManageTelehub handlerEstateManageTelehub = OnEstateManageTelehub; + if (handlerEstateManageTelehub != null) + { + handlerEstateManageTelehub(this, invoice, SenderID, command, param1); + } + } + return true; + default: m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); return true; @@ -9230,8 +9265,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts //lsrp.RequestData.RequestFlags; //lsrp.RequestData.Filter; - -// return true; } private bool HandleRequestRegionInfo(IClientAPI sender, Packet Pack) -- cgit v1.1 From 32d58d6e3e9a0ea1bfa808567d0f64c0652f8a85 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 21 Jan 2012 23:26:27 -0500 Subject: Telehub Support: Telehub settings now persist to the database and are saved across sim restarts. So-far this only works on MySQL. this is a work in progress, teleport routing is not yet implemented. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a94fb20..29ad966 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9242,10 +9242,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP { UUID invoice = messagePacket.MethodData.Invoice; UUID SenderID = messagePacket.AgentData.AgentID; - UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + UInt32 param1 = 0u; string command = (string)Utils.BytesToString(messagePacket.ParamList[0].Parameter); + if (command != "info ui") + { + try + { + param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + catch (Exception ex) + { + + } + } + EstateManageTelehub handlerEstateManageTelehub = OnEstateManageTelehub; if (handlerEstateManageTelehub != null) { -- cgit v1.1 From 2f84d5397bcce4c8de0c0cf70cb65307e9e37908 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 31 Jan 2012 21:14:09 +0000 Subject: minor: remove mono compiler warning --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 29ad966..a7bf06d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9252,9 +9252,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); } - catch (Exception ex) + catch { - } } -- cgit v1.1 From 447a66d66005c5ec54a786d1d0a532738729251c Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 2 Feb 2012 23:40:56 +0000 Subject: Replace ParcelAccessEntry with a new struct, LandAccessEntry, which more accurately reflects the data sent by the viewer. Add times bans and the expiration of timed bans. Warning: Contains a Migration (and nuts) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a7bf06d..cdd4957 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4623,7 +4623,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) + public void SendLandAccessListData(List accessList, uint accessFlag, int localLandID) { ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); replyPacket.Data.AgentID = AgentId; @@ -4632,12 +4632,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP replyPacket.Data.SequenceID = 0; List list = new List(); - foreach (UUID avatar in avatars) + foreach (LandAccessEntry entry in accessList) { ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock(); block.Flags = accessFlag; - block.ID = avatar; - block.Time = 0; + block.ID = entry.AgentID; + block.Time = entry.Expires; list.Add(block); } @@ -8577,13 +8577,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - List entries = new List(); + List entries = new List(); foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + LandAccessEntry entry = new LandAccessEntry(); entry.AgentID = block.ID; entry.Flags = (AccessList)block.Flags; - entry.Time = Util.ToDateTime(block.Time); + entry.Expires = block.Time; entries.Add(entry); } -- cgit v1.1 From 5c545d1d2e0a1862d063a1bdf80d2cd2fa311101 Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Fri, 3 Feb 2012 22:02:36 +0100 Subject: Fix: Covenant changed time not set http://opensimulator.org/mantis/view.php?id=5869 Signed-off-by: BlueWall --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cdd4957..8273c6f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4439,7 +4439,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); edata.CovenantID = covenant; - edata.CovenantTimestamp = 0; + edata.CovenantTimestamp = (uint) m_scene.RegionInfo.RegionSettings.CovenantChangedDateTime; edata.EstateOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; edata.EstateName = Utils.StringToBytes(m_scene.RegionInfo.EstateSettings.EstateName); einfopack.Data = edata; @@ -4447,8 +4447,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP } public void SendDetailedEstateData( - UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, - UUID covenant, string abuseEmail, UUID estateOwner) + UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, + UUID covenant, uint covenantChanged, string abuseEmail, UUID estateOwner) { // m_log.DebugFormat( // "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant); @@ -4473,7 +4473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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[7].Parameter = Utils.StringToBytes(covenantChanged.ToString()); returnblock[8].Parameter = Utils.StringToBytes("1"); // what is this? returnblock[9].Parameter = Utils.StringToBytes(abuseEmail); -- cgit v1.1 From 7273e05995671175d5175558ed72dd1cb331cacb Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Wed, 8 Feb 2012 21:45:00 +0100 Subject: Fix: Unable to remove AV from friend list (sqldb-bug) http://opensimulator.org/mantis/view.php?id=3731 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8273c6f..ff96f4d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5107,7 +5107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); - AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFrendship); + AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); @@ -5827,7 +5827,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } - private bool HandlerTerminateFrendship(IClientAPI sender, Packet Pack) + private bool HandlerTerminateFriendship(IClientAPI sender, Packet Pack) { TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; @@ -5842,13 +5842,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; UUID exFriendID = tfriendpack.ExBlock.OtherID; - - FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship; - if (handlerTerminateFriendship != null) + FriendshipTermination TerminateFriendshipHandler = OnTerminateFriendship; + if (TerminateFriendshipHandler != null) { - handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); + TerminateFriendshipHandler(this, listOwnerAgentID, exFriendID); + return true; } - return true; + return false; } private bool HandleFindAgent(IClientAPI client, Packet Packet) -- cgit v1.1 From a7dc7e636e3de9028668a6c570c6a713d4cd729b Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Fri, 10 Feb 2012 21:18:43 +0100 Subject: Fix: Covenant view fails after updates or cache-clean see mantis http://opensimulator.org/mantis/view.php?id=2879 Signed-off-by: BlueWall --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ff96f4d..d98ff68 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -7625,6 +7625,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } + else + if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) + { + //TransferRequestPacket does not include covenant uuid? + //get scene covenant uuid + taskID = m_scene.RegionInfo.RegionSettings.Covenant; + } MakeAssetRequest(transfer, taskID); @@ -11985,6 +11992,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { requestID = new UUID(transferRequest.TransferInfo.Params, 80); } + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate) + { + requestID = taskID; + } + // m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); -- cgit v1.1 From bdc968f1fcd4008e9f2a6099a7d30edb075ca0f1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Mar 2012 23:57:24 +0000 Subject: Factor out common default animations code into SLUtil. LLClientView now makes use of the SLUtil copy via a method rather than each LLClientView loading a separate copy. As per opensim-users mailing list discussion. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 +--------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d98ff68..b388b10 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -317,7 +317,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected 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 int m_cachedTextureSerial; @@ -452,10 +451,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP RegisterInterface(this); RegisterInterface(this); - InitDefaultAnimations(); - m_scene = scene; - m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); m_entityProps = new PriorityQueue(m_scene.Entities.Count); m_fullUpdateDataBlocksBuilder = new List(); @@ -11210,30 +11206,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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 (nod.Attributes["name"] != null) - { - string name = nod.Attributes["name"].Value.ToLower(); - string id = nod.InnerText; - m_defaultAnimations.Add(name, (UUID)id); - } - } - } - } - public UUID GetDefaultAnimation(string name) { - if (m_defaultAnimations.ContainsKey(name)) - return m_defaultAnimations[name]; - return UUID.Zero; + return SLUtil.GetDefaultAvatarAnimation(name); } /// -- cgit v1.1 From 1a8769e6eff0eab750a528f27d127637edbd292b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Mar 2012 23:57:39 +0000 Subject: Instead of loading default avatar animations in both SLUtil and AvatarAnimations, load just in AvatarAnimations instead. This lets us remove the dependency of OpenSim.Framework.dll on data/avataranimations.xml, which is not necessary for ROBUST. This commit also takes care of the odd situation where animations are stored and used internally with uppercase names (e.g. "STAND") but scripts refer to them with lowercase names (e.g. "sit"). --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b388b10..68aae14 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11202,15 +11202,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP scriptQuestion.Data.Questions = question; scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName); scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName); - + OutPacket(scriptQuestion, ThrottleOutPacketType.Task); } - public UUID GetDefaultAnimation(string name) - { - return SLUtil.GetDefaultAvatarAnimation(name); - } - /// /// Handler called when we receive a logout packet. /// -- cgit v1.1 From 710c14fb57ce2a8cd9a1d5c68ed7c3539a4148cc Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 28 Mar 2012 01:15:56 +0200 Subject: Add SendRemoveInventoryFolders which allows to remove one or more folders from the viewer's inventory view. For HG v2.0. More to come --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 41 +++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 68aae14..7ba9eaf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Handles new client connections /// Constructor takes a single Packet and authenticates everything /// - public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector + public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IClientIPEndpoint, IStatsCollector { /// /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. @@ -448,6 +448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // DebugPacketLevel = 1; RegisterInterface(this); + RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); @@ -12262,5 +12263,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (reply != null) OutPacket(reply, ThrottleOutPacketType.Task); } + + public void SendRemoveInventoryFolders(UUID[] folders) + { + IEventQueue eq = Scene.RequestModuleInterface(); + + if (eq == null) + { + m_log.DebugFormat("[LLCLIENT]: Null event queue"); + return; + } + + OSDMap llsd = new OSDMap(3); + + OSDMap AgentDataMap = new OSDMap(1); + AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + + OSDArray AgentData = new OSDArray(1); + AgentData.Add(AgentDataMap); + + llsd.Add("AgentData", AgentData); + + OSDArray FolderData = new OSDArray(); + + foreach (UUID folder in folders) + { + OSDMap FolderDataMap = new OSDMap(2); + FolderDataMap.Add("FolderID", OSD.FromUUID(folder)); + FolderDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + + FolderData.Add(FolderDataMap); + } + + llsd.Add("FolderData", FolderData); + + eq.Enqueue(BuildEvent("RemoveInventoryFolder", + llsd), AgentId); + } } } -- cgit v1.1 From 8c0f1e905814e93003dd8d78ee54ae947cb3af17 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 28 Mar 2012 02:10:07 +0100 Subject: Add a corresponding method for items. HG v2 --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7ba9eaf..0c1d7f2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12264,6 +12264,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(reply, ThrottleOutPacketType.Task); } + public void SendRemoveInventoryItems(UUID[] items) + { + IEventQueue eq = Scene.RequestModuleInterface(); + + if (eq == null) + { + m_log.DebugFormat("[LLCLIENT]: Null event queue"); + return; + } + + OSDMap llsd = new OSDMap(3); + + OSDMap AgentDataMap = new OSDMap(1); + AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + + OSDArray AgentData = new OSDArray(1); + AgentData.Add(AgentDataMap); + + llsd.Add("AgentData", AgentData); + + OSDArray ItemData = new OSDArray(); + + foreach (UUID item in items) + { + OSDMap ItemDataMap = new OSDMap(2); + ItemDataMap.Add("ItemID", OSD.FromUUID(item)); + ItemDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + + ItemData.Add(ItemDataMap); + } + + llsd.Add("ItemData", ItemData); + + eq.Enqueue(BuildEvent("RemoveInventoryItem", + llsd), AgentId); + } + public void SendRemoveInventoryFolders(UUID[] folders) { IEventQueue eq = Scene.RequestModuleInterface(); -- cgit v1.1 From 0463a00d34af4752936817e826d735e3f36d33f1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 28 Mar 2012 02:45:50 +0100 Subject: Start on Bulk inventory update via CAPS. Not functional yet. HG v2 --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0c1d7f2..4107209 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12339,5 +12339,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP eq.Enqueue(BuildEvent("RemoveInventoryFolder", llsd), AgentId); } + + public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) + { + IEventQueue eq = Scene.RequestModuleInterface(); + + if (eq == null) + { + m_log.DebugFormat("[LLCLIENT]: Null event queue"); + return; + } + + OSDMap llsd = new OSDMap(3); + + OSDMap AgentDataMap = new OSDMap(1); + AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + + OSDArray AgentData = new OSDArray(1); + AgentData.Add(AgentDataMap); + + llsd.Add("AgentData", AgentData); + + OSDArray FolderData = new OSDArray(); + + foreach (UUID InventoryFolderBase in folders) + { + OSDMap FolderDataMap = new OSDMap(5); + FolderDataMap.Add("FolderID", OSD.FromUUID(folder.ID)); + FolderDataMap.Add("AgentID", OSD.FromUUID(AgentId)); + FolderDataMap.Add("ParentID", OSD.FromUUID(folder.ParentID)); + FolderDataMap.Add("Type", OSD.FromInteger(folder.Type)); + FolderDataMap.Add("Name", OSD.FromString(folder.Name)); + + FolderData.Add(FolderDataMap); + } + + llsd.Add("FolderData", FolderData); + + OSDArray ItemData = new OSDArray(); + + foreach (UUID InventoryItemBase in items) + { + OSDMap ItemDataMap = new OSDMap(); + ItemData.Add(DataMap); + } + + llsd.Add("ItemData", ItemData); + } } } -- cgit v1.1 From b24605d5262cb4ff18436d8cff21063be83a39ef Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 28 Mar 2012 02:55:29 +0100 Subject: Fix typos --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4107209..82a76a2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12363,7 +12363,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDArray FolderData = new OSDArray(); - foreach (UUID InventoryFolderBase in folders) + foreach (InventoryFolderBase folder in folders) { OSDMap FolderDataMap = new OSDMap(5); FolderDataMap.Add("FolderID", OSD.FromUUID(folder.ID)); @@ -12379,7 +12379,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDArray ItemData = new OSDArray(); - foreach (UUID InventoryItemBase in items) + foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); ItemData.Add(DataMap); -- cgit v1.1 From 614c40492369778a9b13a31f1e052b2836f8e449 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 28 Mar 2012 02:33:15 +0200 Subject: Typo fix --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 82a76a2..cd81df5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12382,7 +12382,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); - ItemData.Add(DataMap); + ItemData.Add(ItemDataMap); } llsd.Add("ItemData", ItemData); -- cgit v1.1 From d9f7b8549b3cb9699eb8bd54242d31aac0f8241a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 28 Mar 2012 23:40:25 +0100 Subject: Simplify friends caching by only doing this for root agents - no functions require caching for child agents. This allows us to avoid unnecessary multiple calls to the friends service. All friends functions originate from the root agent and only go to other root agents in existing code. This also allows us to eliminate complex ref counting. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cd81df5..9899669 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From 93ac47f0d3968650bd7758ad0981e8e5d49b8138 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 29 Mar 2012 01:08:47 +0100 Subject: Revert "Simplify friends caching by only doing this for root agents - no functions require caching for child agents." We need to cache child agents so that friends object edit/delete permissions will work across boarders on regions hosted by different simulators. This reverts commit d9f7b8549b3cb9699eb8bd54242d31aac0f8241a. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9899669..cd81df5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; set; } + public ISceneAgent SceneAgent { get; private set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_scene.AddNewClient(this, PresenceType.User); + SceneAgent = m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From 22a85b947a16074525343a56203211806ce16834 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 29 Mar 2012 01:26:30 +0100 Subject: Add back parts of reverted changes that were not concerned with child agent caching. This adds ScenePresence to IClientAPI.SceneAgent earlier on in the add client process so that its information is available to EventManager.OnNewClient() and OnClientLogin() Also add a code comment as to why we're caching friend information for child agents. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cd81df5..9899669 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From bf09d6a22be5f8e7a2584eaa11ccbc1c61cc6753 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 29 Mar 2012 18:31:57 +0100 Subject: refactor: Stop passing both IClientAPI and agentID to friend event listeners, these are redundant. Replace a few magic numbers with FriendRights enum already used elsewhere. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9899669..f79597e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5784,7 +5784,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // 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++) @@ -5795,10 +5794,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; if (handlerApproveFriendRequest != null) { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + handlerApproveFriendRequest(this, transactionID, callingCardFolders); } - return true; + return true; } private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack) @@ -5817,7 +5816,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (OnDenyFriendRequest != null) { OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, dfriendpack.TransactionBlock.TransactionID, null); } @@ -5837,14 +5835,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; UUID exFriendID = tfriendpack.ExBlock.OtherID; FriendshipTermination TerminateFriendshipHandler = OnTerminateFriendship; if (TerminateFriendshipHandler != null) { - TerminateFriendshipHandler(this, listOwnerAgentID, exFriendID); + TerminateFriendshipHandler(this, exFriendID); return true; } + return false; } @@ -11162,12 +11160,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } #endregion + GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights; if (GrantUserRightsHandler != null) GrantUserRightsHandler(this, - GrantUserRights.AgentData.AgentID, GrantUserRights.Rights[0].AgentRelated, GrantUserRights.Rights[0].RelatedRights); + return true; } -- cgit v1.1 From 6e7f13a72d4e43f8ca564247e0b56bf5706bbdb1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 31 Mar 2012 01:34:39 +0200 Subject: Implement bulk inventory update over CAPS (not recursive by design, do NOT CHANGE THIS, needed for HG 2.0) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 48 +++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f79597e..3470fa9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12295,7 +12295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ItemData.Add(ItemDataMap); } - llsd.Add("ItemData", ItemData); + llsd.Add("InventoryData", ItemData); eq.Enqueue(BuildEvent("RemoveInventoryItem", llsd), AgentId); @@ -12339,6 +12339,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP llsd), AgentId); } + private byte[] EncodeU32(uint val) + { + byte[] ret = BitConverter.GetBytes(val); + if (BitConverter.IsLittleEndian) + Array.Reverse(ret); + return ret; + } + public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) { IEventQueue eq = Scene.RequestModuleInterface(); @@ -12354,6 +12362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + AgentDataMap.Add("TransactionID", OSD.FromUUID(UUID.Random())); OSDArray AgentData = new OSDArray(1); AgentData.Add(AgentDataMap); @@ -12381,10 +12390,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); + + ItemDataMap.Add("ItemID", OSD.FromUUID(item.ID)); + ItemDataMap.Add("FolderID", OSD.FromUUID(item.Folder)); + + ItemDataMap.Add("CreatorID", OSD.FromUUID(item.CreatorIdAsUuid)); + ItemDataMap.Add("OwnerID", OSD.FromUUID(item.Owner)); + ItemDataMap.Add("GroupID", OSD.FromUUID(item.GroupID)); + ItemDataMap.Add("BaseMask", OSD.FromBinary(EncodeU32((uint)item.BasePermissions))); + ItemDataMap.Add("OwnerMask", OSD.FromBinary(EncodeU32((uint)item.CurrentPermissions))); + ItemDataMap.Add("GroupMask", OSD.FromBinary(EncodeU32((uint)item.GroupPermissions))); + ItemDataMap.Add("EveryoneMask", OSD.FromBinary(EncodeU32((uint)item.EveryOnePermissions))); + ItemDataMap.Add("NextOwnerMask", OSD.FromBinary(EncodeU32((uint)item.NextPermissions))); + ItemDataMap.Add("GroupOwned", OSD.FromBoolean(item.GroupOwned)); + ItemDataMap.Add("AssetID", OSD.FromUUID(item.AssetID)); + ItemDataMap.Add("Type", OSD.FromInteger(item.AssetType)); + ItemDataMap.Add("InvType", OSD.FromInteger(item.InvType)); + ItemDataMap.Add("Flags", OSD.FromBinary(EncodeU32((uint)item.Flags))); + ItemDataMap.Add("SaleType", OSD.FromInteger((byte)item.SaleType)); + ItemDataMap.Add("SalePrice", OSD.FromInteger(item.SalePrice)); + ItemDataMap.Add("Name", OSD.FromString(item.Name)); + ItemDataMap.Add("Description", OSD.FromString(item.Description)); + ItemDataMap.Add("CreationDate", OSD.FromInteger(item.CreationDate)); + + ItemDataMap.Add("CRC", OSD.FromBinary(EncodeU32( + Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType, + (sbyte)item.AssetType, item.AssetID, + item.GroupID, 100, + item.Owner, item.CreatorIdAsUuid, + item.ID, item.Folder, + (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, + (uint)PermissionMask.All) + ))); + ItemDataMap.Add("CallbackID", 0); + ItemData.Add(ItemDataMap); } llsd.Add("ItemData", ItemData); + + eq.Enqueue(BuildEvent("BulkUpdateInventory", + llsd), AgentId); } } } -- cgit v1.1 From 8fd86c91561ade716a9179653e9ffb75ff1df438 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:24:34 -0700 Subject: Packing of folder in SendBulkUpdateInventory always set the folder type to -1. Not sure if there's a reason for it, but I'm changing it to the given folder type. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3470fa9..9395233 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1913,7 +1913,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; - folderBlock.Type = -1; + //folderBlock.Type = -1; + folderBlock.Type = (sbyte)folder.Type; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; -- cgit v1.1 From 7d8bb33c5b2420d4e744269f67a25dd2b9746a35 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 7 Apr 2012 00:33:02 +0100 Subject: Store FromItemID for attachments once on SOG instead of on every SOP and only ever using the root part entry. This eliminates some pointless memory use. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9395233..619ef14 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4957,7 +4957,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim if (data.ParentGroup.IsAttachment) { - update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); + update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); } else -- cgit v1.1 From cce760dbfcd375a700e38b8279b0c19c5624e720 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 7 Apr 2012 00:40:55 +0100 Subject: Rather than having a FromFolderID property on every single prim and only ever using the root prim one, store on SOG instead. This reduces pointless memory usage. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 619ef14..ae5cbff 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4271,7 +4271,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP block.OwnerID = sop.OwnerID; block.ItemID = sop.FromUserInventoryItemID; - block.FolderID = UUID.Zero; // sop.FromFolderID ?? + block.FolderID = UUID.Zero; // sog.FromFolderID ?? block.FromTaskID = UUID.Zero; // ??? block.InventorySerial = (short)sop.InventorySerial; -- cgit v1.1 From a90b0e302c110068cec0ee7109e796d2d5fdab4d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Apr 2012 23:46:33 +0100 Subject: Revert "Implement bulk inventory update over CAPS (not recursive by design," This reverts commit 6e7f13a72d4e43f8ca564247e0b56bf5706bbdb1. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 48 +--------------------- 1 file changed, 1 insertion(+), 47 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ae5cbff..36ef281 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12296,7 +12296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ItemData.Add(ItemDataMap); } - llsd.Add("InventoryData", ItemData); + llsd.Add("ItemData", ItemData); eq.Enqueue(BuildEvent("RemoveInventoryItem", llsd), AgentId); @@ -12340,14 +12340,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP llsd), AgentId); } - private byte[] EncodeU32(uint val) - { - byte[] ret = BitConverter.GetBytes(val); - if (BitConverter.IsLittleEndian) - Array.Reverse(ret); - return ret; - } - public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) { IEventQueue eq = Scene.RequestModuleInterface(); @@ -12363,7 +12355,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); - AgentDataMap.Add("TransactionID", OSD.FromUUID(UUID.Random())); OSDArray AgentData = new OSDArray(1); AgentData.Add(AgentDataMap); @@ -12391,47 +12382,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); - - ItemDataMap.Add("ItemID", OSD.FromUUID(item.ID)); - ItemDataMap.Add("FolderID", OSD.FromUUID(item.Folder)); - - ItemDataMap.Add("CreatorID", OSD.FromUUID(item.CreatorIdAsUuid)); - ItemDataMap.Add("OwnerID", OSD.FromUUID(item.Owner)); - ItemDataMap.Add("GroupID", OSD.FromUUID(item.GroupID)); - ItemDataMap.Add("BaseMask", OSD.FromBinary(EncodeU32((uint)item.BasePermissions))); - ItemDataMap.Add("OwnerMask", OSD.FromBinary(EncodeU32((uint)item.CurrentPermissions))); - ItemDataMap.Add("GroupMask", OSD.FromBinary(EncodeU32((uint)item.GroupPermissions))); - ItemDataMap.Add("EveryoneMask", OSD.FromBinary(EncodeU32((uint)item.EveryOnePermissions))); - ItemDataMap.Add("NextOwnerMask", OSD.FromBinary(EncodeU32((uint)item.NextPermissions))); - ItemDataMap.Add("GroupOwned", OSD.FromBoolean(item.GroupOwned)); - ItemDataMap.Add("AssetID", OSD.FromUUID(item.AssetID)); - ItemDataMap.Add("Type", OSD.FromInteger(item.AssetType)); - ItemDataMap.Add("InvType", OSD.FromInteger(item.InvType)); - ItemDataMap.Add("Flags", OSD.FromBinary(EncodeU32((uint)item.Flags))); - ItemDataMap.Add("SaleType", OSD.FromInteger((byte)item.SaleType)); - ItemDataMap.Add("SalePrice", OSD.FromInteger(item.SalePrice)); - ItemDataMap.Add("Name", OSD.FromString(item.Name)); - ItemDataMap.Add("Description", OSD.FromString(item.Description)); - ItemDataMap.Add("CreationDate", OSD.FromInteger(item.CreationDate)); - - ItemDataMap.Add("CRC", OSD.FromBinary(EncodeU32( - Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType, - (sbyte)item.AssetType, item.AssetID, - item.GroupID, 100, - item.Owner, item.CreatorIdAsUuid, - item.ID, item.Folder, - (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, - (uint)PermissionMask.All) - ))); - ItemDataMap.Add("CallbackID", 0); - ItemData.Add(ItemDataMap); } llsd.Add("ItemData", ItemData); - - eq.Enqueue(BuildEvent("BulkUpdateInventory", - llsd), AgentId); } } } -- cgit v1.1 From ab71779221d580410e8b1c07e94f89ca933f9855 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Apr 2012 23:54:45 +0100 Subject: Revert "Revert "Implement bulk inventory update over CAPS (not recursive by design,"" This reverts commit a90b0e302c110068cec0ee7109e796d2d5fdab4d. Sorry, accidentally reverted this completely by mistake, reverting the revert. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 48 +++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 36ef281..ae5cbff 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12296,7 +12296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ItemData.Add(ItemDataMap); } - llsd.Add("ItemData", ItemData); + llsd.Add("InventoryData", ItemData); eq.Enqueue(BuildEvent("RemoveInventoryItem", llsd), AgentId); @@ -12340,6 +12340,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP llsd), AgentId); } + private byte[] EncodeU32(uint val) + { + byte[] ret = BitConverter.GetBytes(val); + if (BitConverter.IsLittleEndian) + Array.Reverse(ret); + return ret; + } + public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) { IEventQueue eq = Scene.RequestModuleInterface(); @@ -12355,6 +12363,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + AgentDataMap.Add("TransactionID", OSD.FromUUID(UUID.Random())); OSDArray AgentData = new OSDArray(1); AgentData.Add(AgentDataMap); @@ -12382,10 +12391,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); + + ItemDataMap.Add("ItemID", OSD.FromUUID(item.ID)); + ItemDataMap.Add("FolderID", OSD.FromUUID(item.Folder)); + + ItemDataMap.Add("CreatorID", OSD.FromUUID(item.CreatorIdAsUuid)); + ItemDataMap.Add("OwnerID", OSD.FromUUID(item.Owner)); + ItemDataMap.Add("GroupID", OSD.FromUUID(item.GroupID)); + ItemDataMap.Add("BaseMask", OSD.FromBinary(EncodeU32((uint)item.BasePermissions))); + ItemDataMap.Add("OwnerMask", OSD.FromBinary(EncodeU32((uint)item.CurrentPermissions))); + ItemDataMap.Add("GroupMask", OSD.FromBinary(EncodeU32((uint)item.GroupPermissions))); + ItemDataMap.Add("EveryoneMask", OSD.FromBinary(EncodeU32((uint)item.EveryOnePermissions))); + ItemDataMap.Add("NextOwnerMask", OSD.FromBinary(EncodeU32((uint)item.NextPermissions))); + ItemDataMap.Add("GroupOwned", OSD.FromBoolean(item.GroupOwned)); + ItemDataMap.Add("AssetID", OSD.FromUUID(item.AssetID)); + ItemDataMap.Add("Type", OSD.FromInteger(item.AssetType)); + ItemDataMap.Add("InvType", OSD.FromInteger(item.InvType)); + ItemDataMap.Add("Flags", OSD.FromBinary(EncodeU32((uint)item.Flags))); + ItemDataMap.Add("SaleType", OSD.FromInteger((byte)item.SaleType)); + ItemDataMap.Add("SalePrice", OSD.FromInteger(item.SalePrice)); + ItemDataMap.Add("Name", OSD.FromString(item.Name)); + ItemDataMap.Add("Description", OSD.FromString(item.Description)); + ItemDataMap.Add("CreationDate", OSD.FromInteger(item.CreationDate)); + + ItemDataMap.Add("CRC", OSD.FromBinary(EncodeU32( + Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType, + (sbyte)item.AssetType, item.AssetID, + item.GroupID, 100, + item.Owner, item.CreatorIdAsUuid, + item.ID, item.Folder, + (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, + (uint)PermissionMask.All) + ))); + ItemDataMap.Add("CallbackID", 0); + ItemData.Add(ItemDataMap); } llsd.Add("ItemData", ItemData); + + eq.Enqueue(BuildEvent("BulkUpdateInventory", + llsd), AgentId); } } } -- cgit v1.1 From 6987aef38dbc4f5c24b6e2cc73601f9a7c5f4431 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 9 May 2012 23:12:30 +0100 Subject: Improve logging on the prim inventory script asset request path for future use. This adds name and description of the request handler to http request logging when DebugLevel >= 1 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ae5cbff..4d6081c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11955,21 +11955,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected void MakeAssetRequest(TransferRequestPacket transferRequest, UUID taskID) { UUID requestID = UUID.Zero; - if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) + int sourceType = transferRequest.TransferInfo.SourceType; + + if (sourceType == (int)SourceType.Asset) { requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) + else if (sourceType == (int)SourceType.SimInventoryItem) { requestID = new UUID(transferRequest.TransferInfo.Params, 80); } - else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimEstate) + else if (sourceType == (int)SourceType.SimEstate) { requestID = taskID; } - -// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", +// requestID, taskID, (SourceType)sourceType, Name); m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); } -- cgit v1.1 From 794d184c253d1967535e4040682a70b729dc3ccb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 8 Jun 2012 04:32:51 +0100 Subject: Stop sending a DisableSimulator packet in LLClientView.Close(), which is a duplicate for child agents and unnecessary for root agents. Close() already calls Scene.RemoveClient() which sends the right eq or udp DisableSimulator message to child agents. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4d6081c..74b9c6d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -494,10 +494,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP "[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 -- cgit v1.1 From 8c7149063bce41cac6543757c7b917583f21ea90 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 12 Jun 2012 01:23:40 +0100 Subject: In PresenceDetector.OnConnectionClose(), use the IsChildAgent check already available on IClientAPI.SceneAgent rather than retrieving it again by scanning all scenes. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 74b9c6d..c4f167e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -490,12 +490,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void Close() { + IsActive = false; + m_log.DebugFormat( "[CLIENT]: Close has been called for {0} attached to scene {1}", Name, m_scene.RegionInfo.RegionName); - IsActive = false; - // Shutdown the image manager ImageManager.Close(); -- cgit v1.1 From f726150afdf3fd85f3ec08585fd84f75b5852e79 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 13 Jun 2012 23:39:23 +0100 Subject: Add ObjectUpdate as one of the packets that can be screened out when setting debug packet level --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c4f167e..ad39b50 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11650,7 +11650,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (DebugPacketLevel <= 100 && (packet.Type == PacketType.AvatarAnimation || packet.Type == PacketType.ViewerEffect)) logPacket = false; - if (DebugPacketLevel <= 50 && packet.Type == PacketType.ImprovedTerseObjectUpdate) + if (DebugPacketLevel <= 50 + & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) -- cgit v1.1 From cf080a68d657e082dd61dacc24ffd17240154e90 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 13 Jun 2012 23:42:22 +0100 Subject: Remove long obsolete and unused IClientAPI.KillEndDone() --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ad39b50..4e0dadb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11861,10 +11861,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return string.Empty; } - public void KillEndDone() - { - } - #region IClientCore private readonly Dictionary m_clientInterfaces = new Dictionary(); -- cgit v1.1 From 16ffc764bf57dcc85461f2e5c6457ee8237e78c9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 13 Jun 2012 23:54:32 +0100 Subject: minor: refactor part of LLClientView.ProcessEntityUpdates() to remove duplicate code --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4e0dadb..85d83f8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3780,16 +3780,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!canUseImproved && !canUseCompressed) { + ObjectUpdatePacket.ObjectDataBlock updateBlock; + if (update.Entity is ScenePresence) { - objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); - objectUpdates.Value.Add(update); + updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); } else { - objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); - objectUpdates.Value.Add(update); + updateBlock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, AgentId); } + + objectUpdateBlocks.Value.Add(updateBlock); + objectUpdates.Value.Add(update); } else if (!canUseImproved) { @@ -3814,7 +3817,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Block Construction } - #region Packet Sending ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); -- cgit v1.1 From cba8b4f8b8c2566426216e395561cdf4ae49c72e Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 6 Jun 2012 20:35:00 +0200 Subject: Fix not sending TransferInfo when an asset is not found. This clogs up the sound pipeline in the viewer. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 33 +++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 85d83f8..8f55208 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2719,6 +2719,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void SendAssetNotFound(AssetRequestToClient req) + { + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = -2; + Transfer.TransferInfo.TargetType = 0; + Transfer.TransferInfo.Params = req.Params; + Transfer.TransferInfo.Size = 0; + Transfer.TransferInfo.TransferID = req.TransferRequestID; + Transfer.Header.Zerocoded = true; + OutPacket(Transfer, ThrottleOutPacketType.Asset); + } + public void SendTexture(AssetBase TextureAsset) { @@ -11980,14 +11993,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected void AssetReceived(string id, Object sender, AssetBase asset) { - if (asset == null) - return; - TransferRequestPacket transferRequest = (TransferRequestPacket)sender; UUID requestID = UUID.Zero; byte source = (byte)SourceType.Asset; + AssetRequestToClient req = new AssetRequestToClient(); + + if (asset == null) + { + req.AssetInf = null; + req.AssetRequestSource = source; + req.IsTextureRequest = false; + req.NumPackets = 0; + req.Params = transferRequest.TransferInfo.Params; + req.RequestAssetID = requestID; + req.TransferRequestID = transferRequest.TransferInfo.TransferID; + + SendAssetNotFound(req); + return; + } + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) { requestID = new UUID(transferRequest.TransferInfo.Params, 0); @@ -12004,7 +12030,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; // The asset is known to exist and is in our cache, so add it to the AssetRequests list - AssetRequestToClient req = new AssetRequestToClient(); req.AssetInf = asset; req.AssetRequestSource = source; req.IsTextureRequest = false; -- cgit v1.1 From 917d753f1c1474b4ed3f905d8dd95db2e0e2fc9e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 14 Jun 2012 01:36:37 +0100 Subject: Fix a race condition where an object update for a hud could be sent to non-owner avatars if the hud was attached directly from within the region. If this happens, then the non-owners would see unremovable huds that they did not own until relog, and sometimes even beyond that. This was due to a race between the entity update and the attachment code when moving an object from within scene to a hud. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 85d83f8..83e49f3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3722,8 +3722,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - ++updatesThisCall; - #region UpdateFlags to packet type conversion PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; @@ -3788,7 +3786,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - updateBlock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, AgentId); + SceneObjectPart part = (SceneObjectPart)update.Entity; + updateBlock = CreatePrimUpdateBlock(part, AgentId); + + // If the part has become a private hud since the update was scheduled then we do not + // want to send it to other avatars. + if (part.ParentGroup.IsAttachment + && part.ParentGroup.HasPrivateAttachmentPoint + && part.ParentGroup.AttachedAvatar != AgentId) + continue; } objectUpdateBlocks.Value.Add(updateBlock); @@ -3811,6 +3817,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // Everything else goes here terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + + if (update.Entity is SceneObjectPart) + { + SceneObjectPart part = (SceneObjectPart)update.Entity; + + // If the part has become a private hud since the update was scheduled then we do not + // want to send it to other avatars. + if (part.ParentGroup.IsAttachment + && part.ParentGroup.HasPrivateAttachmentPoint + && part.ParentGroup.AttachedAvatar != AgentId) + continue; + } + terseUpdates.Value.Add(update); } } @@ -3880,6 +3899,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If any of the packets created from this call go unacknowledged, all of the updates will be resent OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } + + ++updatesThisCall; } #endregion Packet Sending -- cgit v1.1 From 3888b9a670656cbcdcb5e6cd46365927a1888f27 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 14 Jun 2012 03:32:44 +0100 Subject: If we're going to discard a terse update block because it's now someone else's hud, then don't still add it to the list of blocks for the update message. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9f32c33..4ea977e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3828,9 +3828,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - // Everything else goes here - terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock + = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); + // Everything else goes here if (update.Entity is SceneObjectPart) { SceneObjectPart part = (SceneObjectPart)update.Entity; @@ -3843,6 +3844,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP continue; } + terseUpdateBlocks.Value.Add(terseUpdateBlock); terseUpdates.Value.Add(update); } } -- cgit v1.1 From 2c6555021fdcf5dcd08a19d41412acf20f514b14 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 14 Jun 2012 03:49:54 +0100 Subject: Fix very recent regression in 917d753 where I put the ++updatesThisCall outside the batching part of ProcessEntityUpdates() This stopped any batching happening and since this method is called periodically updates were sent very slowly --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4ea977e..4cb7a3a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3848,6 +3848,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP terseUpdates.Value.Add(update); } } + + ++updatesThisCall; #endregion Block Construction } @@ -3914,8 +3916,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If any of the packets created from this call go unacknowledged, all of the updates will be resent OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } - - ++updatesThisCall; } #endregion Packet Sending -- cgit v1.1 From 5301648cff6b451fef4cca0baf8cda1bdb1455a6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 25 Jun 2012 21:08:19 +0100 Subject: In AttachmentsModule.DetachSingleAttachmentToInvInternal(), remove attachment before changing properties for correct inventory serialization. Serialization of attachments requires IsAttachment = false so that correct positions are serialized instead of avatar position. However, doing this when a hud is still attached allows race conditions with update threads, resulting in hud artifacts on other viewers. This change sets SOG.IsDeleted before serialization changes take place (IsDeleted itself is not a serialized property). LLClientView then screens out any deleted SOGs before sending updates to viewers. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4cb7a3a..8874585 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3808,6 +3808,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP && part.ParentGroup.HasPrivateAttachmentPoint && part.ParentGroup.AttachedAvatar != AgentId) continue; + + // If the part has since been deleted, then drop the update. In the case of attachments, + // this is to avoid spurious updates to other viewers since post-processing of attachments + // has to change the IsAttachment flag for various reasons (which will end up in a pass + // of the test above). + // + // Actual deletions (kills) happen in another method. + if (part.ParentGroup.IsDeleted) + continue; } objectUpdateBlocks.Value.Add(updateBlock); @@ -3815,7 +3824,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else if (!canUseImproved) { - compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); + SceneObjectPart part = (SceneObjectPart)update.Entity; + ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock + = CreateCompressedUpdateBlock(part, updateFlags); + + // If the part has since been deleted, then drop the update. In the case of attachments, + // this is to avoid spurious updates to other viewers since post-processing of attachments + // has to change the IsAttachment flag for various reasons (which will end up in a pass + // of the test above). + // + // Actual deletions (kills) happen in another method. + if (part.ParentGroup.IsDeleted) + continue; + + compressedUpdateBlocks.Value.Add(compressedBlock); compressedUpdates.Value.Add(update); } else @@ -3842,6 +3864,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP && part.ParentGroup.HasPrivateAttachmentPoint && part.ParentGroup.AttachedAvatar != AgentId) continue; + + // If the part has since been deleted, then drop the update. In the case of attachments, + // this is to avoid spurious updates to other viewers since post-processing of attachments + // has to change the IsAttachment flag for various reasons (which will end up in a pass + // of the test above). + // + // Actual deletions (kills) happen in another method. + if (part.ParentGroup.IsDeleted) + continue; } terseUpdateBlocks.Value.Add(terseUpdateBlock); -- cgit v1.1 From 3b3d9967b18335c28ce2dfc269e47bac0ede075a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 12 Jul 2012 23:29:57 +0100 Subject: Remove IClientAPI.GetClientEP() in favour of existing identical IClientAPI.RemoteEndpoint. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8874585..0457fe6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11845,11 +11845,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpClient.SetClientInfo(info); } - public EndPoint GetClientEP() - { - return m_userEndPoint; - } - #region Media Parcel Members public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) -- cgit v1.1 From dda999a22c5f36d1d413f2f5f29ce8782af85b0b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 12 Jul 2012 23:43:02 +0100 Subject: Remove IClientIPEndpoint client interface for now. This may well come back in the future when this subinterface is actually used but it currently isn't and I feel the name was poor. Everything uses IClientAPI.RemoveEndPoint which also returned the full endpoint rather than just the ip address. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0457fe6..bc5315b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Handles new client connections /// Constructor takes a single Packet and authenticates everything /// - public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IClientIPEndpoint, IStatsCollector + public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector { /// /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. @@ -450,7 +450,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); - RegisterInterface(this); m_scene = scene; m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); @@ -12114,24 +12113,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return numPackets; } - #region IClientIPEndpoint Members - - public IPAddress EndPoint - { - get - { - if (m_userEndPoint is IPEndPoint) - { - IPEndPoint ep = (IPEndPoint)m_userEndPoint; - - return ep.Address; - } - return null; - } - } - - #endregion - public void SendRebakeAvatarTextures(UUID textureID) { RebakeAvatarTexturesPacket pack = -- cgit v1.1 From d6f54b25cd8e3d7a465e9875d2e00dd414a1b019 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 12 Jul 2012 23:48:42 +0100 Subject: Stop redundantly passing in the endpoint to the LLClientView constructor. This can always be retrieved via the LLUDPClient and is so done in various places already. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bc5315b..73cdec3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -357,7 +357,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; @@ -442,7 +441,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Constructor /// - public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, + public LLClientView(Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode) { // DebugPacketLevel = 1; @@ -466,7 +465,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; @@ -11832,7 +11830,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { ClientInfo info = m_udpClient.GetClientInfo(); - info.userEP = m_userEndPoint; info.proxyEP = null; info.agentcircuit = RequestClientInfo(); -- cgit v1.1 From ba80f137b58cfacf46fadb3ec8b63af6896c5b43 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 22:32:27 +0100 Subject: Prevent race conditions between two threads that call LLClientView.Close() simultaneously (e.g. ack timeout and an attempt to reconnect) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 58 ++++++++++++++++------ 1 file changed, 43 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 73cdec3..ae5207b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -347,8 +347,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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 m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -412,16 +410,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; } - } + + /// + /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to + /// prevent race conditions by different threads calling Close(). + /// + public bool IsActive { get; set; } + + /// + /// Used to synchronise threads when client is being closed. + /// + public Object CloseSyncLock { get; private set; } + + public bool IsLoggingOut { get; set; } public bool DisableFacelights { @@ -446,6 +447,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // DebugPacketLevel = 1; + CloseSyncLock = new Object(); + RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); @@ -478,17 +481,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_prioritizer = new Prioritizer(m_scene); RegisterLocalPacketHandlers(); + + IsActive = true; } #region Client Methods /// - /// Shut down the client view + /// Close down the client view /// public void Close() { - IsActive = false; + // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. + // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. + lock (CloseSyncLock) + { + if (!IsActive) + return; + + IsActive = false; + CloseWithoutChecks(); + } + } + /// + /// Closes down the client view without first checking whether it is active. + /// + /// + /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling + /// CloseWithoutIsActiveCheck asynchronously. + /// + /// Callers must lock ClosingSyncLock before calling. + /// + public void CloseWithoutChecks() + { m_log.DebugFormat( "[CLIENT]: Close has been called for {0} attached to scene {1}", Name, m_scene.RegionInfo.RegionName); @@ -3567,7 +3593,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendCoarseLocationUpdate(List users, List CoarseLocations) { - if (!IsActive) return; // We don't need to update inactive clients. + // We don't need to update inactive clients. + if (!IsActive) + return; CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); loc.Header.Reliable = false; -- cgit v1.1 From d1d331a4c02243c8bb4ada60566fa48417c95a5a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 23:20:03 +0100 Subject: Make LLClientView instant message handling asynchronous rather than synchronous to prevent long operations from holding up all inbound packet processing. Giving a large folder from one avatar to another was causing a long delay when handled synchronously, since it took some time to retrieve the necessary data from the inventory service. Handling this asynchronously instead stops this delay from disrupting all avatars in the scene. This has been shown in OSGrid. I see no reason for not handling all IM messages asynchronously, just as incoming chat is handled asynchronously, so this has been switched for all instant messages. Thanks to Nebadon for testing this change out. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ae5207b..f7864b8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5192,7 +5192,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); - AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); + AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); -- cgit v1.1 From 35efa88c26d249d315837fdca0faf643511e1a4e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 23:11:50 +0100 Subject: Rename OpenSim.Framework.Statistics to OpenSim.Framework.Monitoring. This better reflects the long-term purpose of that project and matches Monitoring modules. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f7864b8..01ceeed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Client; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -- cgit v1.1 From dd0556abc9a88121ac91cd86c60a51aac9c726e5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 19 Aug 2012 22:05:38 +0100 Subject: Fix llDialog responses so that they can be heard throughout the region. This now conforms to the behaviour in SL. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 01ceeed..22b3d35 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5810,7 +5810,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP args.Channel = ch; args.From = String.Empty; args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; + args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance args.Position = new Vector3(); args.Scene = Scene; args.Sender = this; -- cgit v1.1 From bcbd450fe441e94d6c0f547055b4e95f75a5b0d0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 20 Aug 2012 20:24:54 +0100 Subject: Add --force flag to "kick user" console command to allow bypassing of recent race condition checks. This is to allow a second attempt to remove an avatar even if "show connections" shows them as already inactive (i.e. close has already been attempted once). You should only attempt --force if a normal kick fails. This is partly for diagnostics as we have seen some connections occasionally remain on lbsa plaza even if they are registered as inactive. This is not a permanent solution and may not work anyway - the ultimate solution is to stop this problem from happening in the first place. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 22b3d35..148d0e0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Client Methods - /// - /// Close down the client view - /// public void Close() { + Close(false); + } + + public void Close(bool force) + { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - if (!IsActive) + // We still perform a force close inside the sync lock since this is intended to attempt close where + // there is some unidentified connection problem, not where we have issues due to deadlock + if (!IsActive && !force) return; IsActive = false; @@ -11989,7 +11993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Close(); + Disconnect(); } public void Disconnect() -- cgit v1.1 From 68814f904e1f0c5be961791f3f475dcda4a88248 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 31 Aug 2012 00:37:27 +0100 Subject: Replace SendBannedUserList with Avination's version. Untested in core. Not even test compiled. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 57 ++++++++++++---------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 148d0e0..d05ffea 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4451,37 +4451,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (bl[i].BannedUserID == UUID.Zero) continue; BannedUsers.Add(bl[i].BannedUserID); - } - 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 (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 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"); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; - for (int i = 0; i < (6 + BannedUsers.Count); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + int j; + for (j = 0; j < (6 + BannedUsers.Count); j++) + { + returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); + } + 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++; + 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++; - foreach (UUID banned in BannedUsers) - { - returnblock[j].Parameter = banned.GetBytes(); j++; + foreach (UUID banned in BannedUsers) + { + returnblock[j].Parameter = banned.GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = true; + OutPacket(packet, ThrottleOutPacketType.Task); + + BannedUsers.Clear(); + } } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + } public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) -- cgit v1.1 From 16c9c1dff7bbf299efddd44e4f9aeeb7db38fff6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 6 Oct 2012 02:34:49 +0100 Subject: On receiving TaskInventoryAccepted with a destination folder in the binary bucket slot for RLV, notify the viewer about inventory folder updates. The viewer would not see the folder move without this, either on accept or decline. This commit also updates the TaskInventoryOffered message to better conform with the data LL uses Changes are, agentID is prim owner rather than prim id, agent name is now simply object name rather than name with owner detail, message is just folder name in single quotes, message is not timestamped. However, folder is not renamed "still #RLV/~". Long term solution is probably not to do these operations server-side. Notes will be added to http://opensimulator.org/mantis/view.php?id=6311 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d05ffea..0869bd5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5862,7 +5862,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + msgpack.MessageBlock.BinaryBucket, + true); handlerInstantMessage(this, im); } -- cgit v1.1 From 73c9abf5f2e2017bf924d6183502e337d28a7232 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Oct 2012 01:35:27 +0100 Subject: Move OpenSim.Data.RegionFlags -> OpenSim.Framework.RegionFlags to make it easier for other code to use (e.g. LSL_Api) without having to reference OpenSim.Data just for this. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0869bd5..62f51d9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Timer = System.Timers.Timer; using AssetLandmark = OpenSim.Framework.AssetLandmark; +using RegionFlags = OpenMetaverse.RegionFlags; using Nini.Config; using System.IO; -- cgit v1.1 From 2e9ef015f7b73a3942011a36a9f94ce59d848dc0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 23:58:37 +0100 Subject: Fix packetpool for ImprovedTerseObjectUpdate packets. These were neither being returned or in many places reused. Getting packets from a pool rather than deallocating and reallocating reduces memory churn which in turn reduces garbage collection time and frequency. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 62f51d9..dc88686 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3922,7 +3922,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseAgentUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -3967,7 +3969,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -12286,7 +12291,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; -- cgit v1.1 From 8a402850ddbdd9497998774b646c8e0ae6ef1eb8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 00:21:45 +0100 Subject: Enable reuse of data blocks for ImprovedTerseObjectUpdate using existing Packetpool code. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dc88686..5f9face 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4964,7 +4964,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block + = PacketPool.Instance.GetDataBlock(); + block.Data = data; if (textureEntry != null && textureEntry.Length > 0) -- cgit v1.1 From b7e75d467c2edf052b0cf5216043937ebf583ef4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 02:10:30 +0100 Subject: minor: Use && instead of & when deciding whether to print Improve/ObjectUpdate packet out messages when debug is turned on. Practical effect is probably none. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5f9face..2db8df2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11765,7 +11765,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (DebugPacketLevel <= 50 - & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) + && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) -- cgit v1.1 From dc460579fd94b2017e334e71ffd20d94a3dec425 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 13 Oct 2012 01:47:10 +0100 Subject: minor: Fix and elaborate on log information printed when an unrecognized estate method is received from the client. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2db8df2..0d4f09d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9063,7 +9063,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + string method = Utils.BytesToString(messagePacket.MethodData.Method); + + switch (method) { case "getinfo": if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) @@ -9379,7 +9381,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + m_log.WarnFormat( + "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", + method, Name, Scene.Name); + + for (int i = 0; i < messagePacket.ParamList.Length; i++) + { + EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; + string data = (string)Utils.BytesToString(block.Parameter); + m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); + } + return true; } -- cgit v1.1 From faf6b568393d8edfed103e0a656c98322c195e95 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:08:14 +0100 Subject: Explicitly return only the incoming AgentUpdate packet as this is the only one we pool atm, rather than attempting to return all incoming packets. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0d4f09d..1e93b84 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5425,16 +5425,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) + private bool HandleAgentUpdate(IClientAPI sener, Packet packet) { if (OnAgentUpdate != null) { bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + { + PacketPool.Instance.ReturnPacket(packet); return false; + } #endregion AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; @@ -5499,6 +5502,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + PacketPool.Instance.ReturnPacket(packet); + return true; } @@ -11851,8 +11856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!ProcessPacketMethod(packet)) m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); - - PacketPool.Instance.ReturnPacket(packet); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) -- cgit v1.1 From 3ec2923022dbc3e0b5411b17c6495dab6d641f0b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:54:05 +0100 Subject: Reuse the same AgentUpdateArgs object for each AgentUpdate UDP packet (of which there are 10 a second) rather than constructing a new one every time. We can do this because AgentUpdate packets are handled synchronously. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 109 +++++++++++++-------- 1 file changed, 68 insertions(+), 41 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1e93b84..65daca0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,8 +92,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; + + /// + /// Called when an AgentUpdate message is received and before OnAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnPreAgentUpdate; + + /// + /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; @@ -347,7 +362,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - private AgentUpdateArgs lastarg; + + /// + /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for + /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it + /// is doing absolutely nothing. + /// + /// + /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods + /// cannot retain a reference to it outside of that method. + /// + private AgentUpdateArgs m_lastAgentUpdateArgs; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5198,7 +5223,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected virtual void RegisterLocalPacketHandlers() { AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); + + // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs + // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); @@ -5429,73 +5458,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (OnAgentUpdate != null) { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; + AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check - if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) { PacketPool.Instance.ReturnPacket(packet); return false; } #endregion - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - - // We can only check when we have something to check - // against. + bool update = false; + AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; - if (lastarg != null) + if (m_lastAgentUpdateArgs != null) { + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. 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) + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) ); } else { + m_lastAgentUpdateArgs = new AgentUpdateArgs(); update = true; } - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - 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; + m_lastAgentUpdateArgs.AgentID = x.AgentID; + m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_lastAgentUpdateArgs.Far = x.Far; + m_lastAgentUpdateArgs.Flags = x.Flags; + m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_lastAgentUpdateArgs.SessionID = x.SessionID; + m_lastAgentUpdateArgs.State = x.State; + UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime + if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, arg); + OnPreAgentUpdate(this, m_lastAgentUpdateArgs); + if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + OnAgentUpdate(this, m_lastAgentUpdateArgs); handlerAgentUpdate = null; handlerPreAgentUpdate = null; -- cgit v1.1 From 0811f3d28d70432e4657df735b5337726eb2f53f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 00:34:10 +0100 Subject: minor: Remove event method doc from LLClientView that I forgot in the last commit (1de80c) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 65daca0..7427c59 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,23 +92,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; - - /// - /// Called when an AgentUpdate message is received and before OnAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnPreAgentUpdate; - - /// - /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnAgentUpdate; - public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; -- cgit v1.1 From c13a99dc5cc82efac5497dab27dcb6b0d9865cea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 03:26:12 +0100 Subject: Fix script error messages not showing up in viewer 3 and associated viewers. Viewer 3 will discard such a message if the chat message owner does not match the avatar. We were filling the ownerID with the primID, so this never matched, hence viewer 3 did not see any script error messages. This commit fills the ownerID in with the prim ownerID so the script owner will receive script error messages. This does not affect viewer 1 and associated viewers which continue to process script errors as normal. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7427c59..8e5a6d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -817,8 +817,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(mov, ThrottleOutPacketType.Unknown); } - public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; @@ -827,7 +828,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.SourceType = source; reply.ChatData.Position = fromPos; reply.ChatData.FromName = Util.StringToBytes256(fromName); - reply.ChatData.OwnerID = fromAgentID; + reply.ChatData.OwnerID = ownerID; reply.ChatData.SourceID = fromAgentID; OutPacket(reply, ThrottleOutPacketType.Task); -- cgit v1.1 From 4ba48151b232716ebb473bc320793a9610a96e5b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Oct 2012 00:39:45 +0000 Subject: Handle UUIDGroupName and ObjectGroup viewer UDP requests asynchronously rather than synchronously. This is to avoid the entire scene loop being held up when the group service is slow to respond. There's no obvious reason for these queries to be sync rather than async. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8e5a6d2..7382e09 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5219,8 +5219,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); -- cgit v1.1 From df4da51f04ea2900032a6bd2749039bee5338f54 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Nov 2012 03:04:46 +0000 Subject: Following on from 4f982596, launch map name requests on an async thread from LLClientView directly. This releases the inbound packet handling thread marginally quicker and is more consistent with the other async packet handling --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7382e09..c93dbfc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5322,7 +5322,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false); AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); - AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false); + AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest); AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); -- cgit v1.1 From 57273ef7b24c5ae466ebb6051a5c614a3c07fe2d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Nov 2012 03:07:45 +0000 Subject: Do HandleMapLayerRequest on its own thread rather than on the main inbound udp packet handling thread. There's no obvious race condition reason for doing this on the main packet handling thread. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c93dbfc..92a630f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5320,7 +5320,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory); AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory); AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); - AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false); + AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest); AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest); AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); -- cgit v1.1 From daf03bfb567a7a93a9259945386325fd924f8bd1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Nov 2012 03:09:20 +0000 Subject: Handle Map block requests on a separate thread rather than the main packet handling thread. This prevents a slow grid information network call from holding up the main packet handling thread. There's no obvious race condition reason for not doing this asynchronously. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 92a630f..4fd81fa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5321,7 +5321,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory); AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest); - AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); + AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest); AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest); AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); -- cgit v1.1 From 0b93a68030cb498896c296654004d3dc2270bc4b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 13 Dec 2012 23:32:28 +0000 Subject: minor: add some more detail to the logging if an LLClientView fails to process a packet --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4fd81fa..504df40 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11864,11 +11864,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (logPacket) m_log.DebugFormat( "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", - Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); + Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name, packet.Type); } if (!ProcessPacketMethod(packet)) - m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); + m_log.WarnFormat( + "[CLIENT]: Unhandled packet {0} from {1} ({2}) in {3}. Ignoring.", + packet.Type, Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) -- cgit v1.1 From 72cc94cfbc16515515d33e4f130d3ee5f2802866 Mon Sep 17 00:00:00 2001 From: dahlia Date: Thu, 10 Jan 2013 20:21:18 -0800 Subject: add some sanity checking to HandleAgentRequestSit handler --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 504df40..a8517e6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6428,8 +6428,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; if (handlerAgentRequestSit != null) - handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, - agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + if (!(agentRequestSit.AgentData == null + || agentRequestSit.TargetObject == null + || agentRequestSit.TargetObject.TargetID == null + || agentRequestSit.TargetObject.Offset == null)) + { + var sp = m_scene.GetScenePresence(agentRequestSit.AgentData.AgentID); + if (sp == null || sp.ParentID != 0) // ignore packet if agent is already sitting + return true; + + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + } } return true; } -- cgit v1.1 From 055b8a2d58a17d5dbc6cdb7f22077e6268578905 Mon Sep 17 00:00:00 2001 From: dahlia Date: Mon, 14 Jan 2013 22:24:24 -0800 Subject: move resit fix to ScenePresence.cs and allow for requesting sit on objects other than the object currently sat on --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a8517e6..967fa44 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6427,19 +6427,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; - if (handlerAgentRequestSit != null) - if (!(agentRequestSit.AgentData == null - || agentRequestSit.TargetObject == null - || agentRequestSit.TargetObject.TargetID == null - || agentRequestSit.TargetObject.Offset == null)) - { - var sp = m_scene.GetScenePresence(agentRequestSit.AgentData.AgentID); - if (sp == null || sp.ParentID != 0) // ignore packet if agent is already sitting - return true; - handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, - agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); - } + if (handlerAgentRequestSit != null) + handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); } return true; } -- cgit v1.1 From 5563a8916ed5c78f91dccb668453f5782ab19532 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 16:45:18 +0000 Subject: Complete removal of the now unused state queue --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a8517e6..77acacf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1588,7 +1588,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) { - OutPacket(kill, ThrottleOutPacketType.State); + OutPacket(kill, ThrottleOutPacketType.Task); } else { -- cgit v1.1 From 7c4e0ff03c5ba9331feb777247594e94fc0f7ac1 Mon Sep 17 00:00:00 2001 From: teravus Date: Wed, 30 Jan 2013 06:22:05 -0500 Subject: * Adds a satisfying angular roll when an avatar is flying and turning. (General, not physics). Makes flying not feel as stiff. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0ccd69a..88b64f5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4893,7 +4893,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // may improve movement smoothness. // acceleration = new Vector3(1, 0, 0); - angularVelocity = Vector3.Zero; + angularVelocity = presence.AngularVelocity; rotation = presence.Rotation; if (sendTexture) -- cgit v1.1 From 7bf33d333af6e7393a05940d1ab436f5dce73814 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 7 Feb 2013 22:25:28 +0000 Subject: Plumb the path from the client to the extra physics params and back --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 59 ++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 88b64f5..bd4a2d1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2627,6 +2627,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + public void SendPartPhysicsProprieties(ISceneEntity entity) + { + SceneObjectPart part = (SceneObjectPart)entity; + if (part != null && AgentId != UUID.Zero) + { + try + { + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq != null) + { + uint localid = part.LocalId; + byte physshapetype = part.PhysicsShapeType; + float density = part.Density; + float friction = part.Friction; + float bounce = part.Restitution; + float gravmod = part.GravityModifier; + eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId); + } + } + catch (Exception ex) + { + m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString()); + } + part.UpdatePhysRequired = false; + } + } + + public void SendGroupNameReply(UUID groupLLUID, string GroupName) { @@ -7035,10 +7063,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP // 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); + /* + 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); + */ + bool UsePhysics = flags.AgentData.UsePhysics; + bool IsPhantom = flags.AgentData.IsPhantom; + bool IsTemporary = flags.AgentData.IsTemporary; + ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics; + ExtraPhysicsData physdata = new ExtraPhysicsData(); + + if (blocks == null || blocks.Length == 0) + { + physdata.PhysShapeType = PhysShapeType.invalid; + } + else + { + ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0]; + physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType; + physdata.Bounce = phsblock.Restitution; + physdata.Density = phsblock.Density; + physdata.Friction = phsblock.Friction; + physdata.GravitationModifier = phsblock.GravityMultiplier; + } + + handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this); } return true; } -- cgit v1.1 From 3108d18ffb2fc4d2b10eac696842335b25aaf088 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 16 Feb 2013 05:09:27 +0100 Subject: Fix shape parameters sent for meshes tosupport the full number of faces --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bd4a2d1..a187190 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3802,6 +3802,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP part.Shape.LightEntry = false; } } + + if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) + { + // Ensure that mesh has at least 8 valid faces + part.Shape.ProfileBegin = 12500; + part.Shape.ProfileEnd = 0; + part.Shape.ProfileHollow = 27500; + } } #region UpdateFlags to packet type conversion -- cgit v1.1 From 681653ca130eaf15c62aae6fd1a7c5276036a0e9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 20 Feb 2013 14:11:02 -0800 Subject: Add a method to IStatsCollector for returning stats as an OSDMap. Extend implementors of IStatsCollector to return an OSDMap of stats. Update UserStatsCollector and AssetStatsCollector to return both string and OSDMap data (as well as console format). --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a187190..5675870 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12138,6 +12138,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return String.Empty; } + public OSDMap OReport(string uptime, string version) + { + return new OSDMap(); + } + /// /// Make an asset request to the asset service in response to a client request. /// -- cgit v1.1 From 7556b42d7a208e3e7dfc23550293bad243533328 Mon Sep 17 00:00:00 2001 From: teravus Date: Mon, 4 Mar 2013 21:26:26 -0500 Subject: * Update LibOMV to f8f8e616b37a7ea22b7922b2331999bc06725bf9 * Add zero length blocks to the new packet blocks to remain compatible with older viewers and avoid a NullRef when _packets_.cs calls the Length parameter.. which adds up the Length property all of the blocks. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5675870..6742d99 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -790,7 +790,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP handshake.RegionInfo3.ColoName = Utils.EmptyBytes; handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; - + handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; + OutPacket(handshake, ThrottleOutPacketType.Task); } @@ -3571,6 +3572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; + avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } @@ -4192,7 +4194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP pack.Stat = stats.StatsBlock; pack.Header.Reliable = false; - + pack.RegionInfo = new SimStatsPacket.RegionInfoBlock[0]; OutPacket(pack, ThrottleOutPacketType.Task); } -- cgit v1.1 From 33dab49d22002b9d24b2c286d662dca1755ace30 Mon Sep 17 00:00:00 2001 From: teravus Date: Thu, 7 Mar 2013 19:19:36 -0500 Subject: * Just another one of those new packet blocks causing a null ref. Defaulting to zero length array..... --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6742d99..bae7952 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4581,7 +4581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); rinfopack.AgentData.AgentID = AgentId; rinfopack.AgentData.SessionID = SessionId; - + rinfopack.RegionInfo3 = new RegionInfoPacket.RegionInfo3Block[0]; OutPacket(rinfopack, ThrottleOutPacketType.Task); } -- cgit v1.1 From f8a4d95bdd2bff70a428d386edad1ca91e15c6c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 13 Mar 2013 00:22:07 +0000 Subject: minor: Remove mono compiler warning in LLClientView --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bae7952..7ea538c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -7069,7 +7069,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdatePrimFlags != null) { - byte[] data = Pack.ToBytes(); +// 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?) -- cgit v1.1 From 5f4c4df227025c6b6156ce8238b56553dca4b5ae Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 26 Mar 2013 03:40:06 +0000 Subject: Phase 1 of implementing a transfer permission. Overwrite libOMV's PermissionMask with our own and add export permissions as well as a new definition for "All" as meaning "all conventional permissions" rather than "all possible permissions" --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7ea538c..110e50e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -51,6 +51,7 @@ using RegionFlags = OpenMetaverse.RegionFlags; using Nini.Config; using System.IO; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -1808,7 +1809,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) { - const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + // Fudge this value. It's only needed to make the CRC anyway + const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply); // TODO: don't create new blocks if recycling an old packet @@ -2013,7 +2015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected void SendBulkUpdateInventoryItem(InventoryItemBase item) { - const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + const uint FULL_MASK_PERMISSIONS = (uint)0x7ffffff; BulkUpdateInventoryPacket bulkUpdate = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory); @@ -2067,7 +2069,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase) public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) { - const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; UpdateCreateInventoryItemPacket InventoryReply = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket( -- cgit v1.1 From 53122fad400e2d5bac5f02a3e153b6e76c9112b3 Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 17 Apr 2013 23:10:02 -0700 Subject: Thanks lkalif for a fix to SendRegionHandshake() which fixes a potential crash with Server-side baking enabled viewers --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 110e50e..02b326e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -791,11 +791,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP handshake.RegionInfo3.ColoName = Utils.EmptyBytes; handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; - handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; - + + handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1]; + handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags; + handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported + OutPacket(handshake, ThrottleOutPacketType.Task); } + public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) { AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); -- cgit v1.1 From 7c839f176fab8166d4787ddbdffdda5f8d9e55ca Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 17 Apr 2013 23:14:28 -0700 Subject: amend previous commit, a line was left out --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 02b326e..1609012 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -793,6 +793,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1]; + handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block(); handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags; handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported -- cgit v1.1 From 293a024c141d3567d42169f625bc449b89a1b59d Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 22 Apr 2013 22:24:41 +0200 Subject: Allow callers to set the invoice parameter for GenericMessage --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1609012..1eb953c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -900,9 +900,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, UUID invoice, List message) { GenericMessagePacket gmp = new GenericMessagePacket(); + + gmp.AgentData.AgentID = AgentId; + gmp.AgentData.SessionID = m_sessionId; + gmp.AgentData.TransactionID = invoice; + gmp.MethodData.Method = Util.StringToBytes256(method); gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; int i = 0; @@ -915,9 +920,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(gmp, ThrottleOutPacketType.Task); } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, UUID invoice, List message) { GenericMessagePacket gmp = new GenericMessagePacket(); + + gmp.AgentData.AgentID = AgentId; + gmp.AgentData.SessionID = m_sessionId; + gmp.AgentData.TransactionID = invoice; + gmp.MethodData.Method = Util.StringToBytes256(method); gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; int i = 0; -- cgit v1.1 From 03c9d8ae4fa9a47cda66814177071c258f5b4437 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 25 Apr 2013 21:35:18 +0100 Subject: Change EconomyDataRequest signature to use an IClientAPI rather than UUID. This is needed because recent LL viewer codebases call this earlier in login when the client is not yet established in the sim and can't be found by UUID. Sending the reply requires having the IClientAPI. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1eb953c..bede379 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9682,7 +9682,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; if (handlerEconomoyDataRequest != null) { - handlerEconomoyDataRequest(AgentId); + handlerEconomoyDataRequest(this); } return true; } -- cgit v1.1 From 33aaa40bee37ca4d8a3afa10fbbea7c1be3a1d58 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 8 May 2013 13:13:51 -0700 Subject: Adds an event and a method so that handling of the CachedTexture packet can be pulled out of LLClientView and moved to AvatarFactory. The first pass at reusing textures (turned off by default) is included. When reusing textures, if the baked textures from a previous login are still in the asset service (which generally means that they are in the simulator's cache) then the avatar will not need to rebake. This is both a performance improvement (specifically that an avatars baked textures do not need to be sent to other users who have the old textures cached) and a resource improvement (don't have to deal with duplicate bakes in the asset service cache). --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 58 ++++++++++++++++------ 1 file changed, 43 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bede379..47dd842 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -84,6 +84,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ModifyTerrain OnModifyTerrain; public event Action OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; + public event CachedTextureRequest OnCachedTextureRequest; public event SetAppearance OnSetAppearance; public event AvatarNowWearing OnAvatarNowWearing; public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; @@ -321,7 +322,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP private readonly byte[] m_channelVersion = Utils.EmptyBytes; private readonly IGroupsModule m_GroupsModule; - private int m_cachedTextureSerial; private PriorityQueue m_entityUpdates; private PriorityQueue m_entityProps; private Prioritizer m_prioritizer; @@ -11462,8 +11462,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } /// - /// 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. @@ -11473,33 +11471,63 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) { - //m_log.Debug("texture cached: " + packet.ToString()); AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; - AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); if (cachedtex.AgentData.SessionID != SessionId) return false; + List requestArgs = new List(); + + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + CachedTextureRequestArg arg = new CachedTextureRequestArg(); + arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex; + arg.WearableHashID = cachedtex.WearableData[i].ID; + + requestArgs.Add(arg); + } + + CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; + if (handlerCachedTextureRequest != null) + { + handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); + } + + return true; + } + + /// + /// Send a response back to a client when it asks the asset server (via the region server) if it has + /// its appearance texture cached. + /// + /// + /// + /// + /// + public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List cachedTextures) + { + ScenePresence presence = avatar as ScenePresence; + if (presence == null) + return; + + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + // TODO: don't create new blocks if recycling an old packet - cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.AgentID = m_agentId; cachedresp.AgentData.SessionID = m_sessionId; - cachedresp.AgentData.SerialNum = m_cachedTextureSerial; - m_cachedTextureSerial++; - cachedresp.WearableData = - new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; + cachedresp.AgentData.SerialNum = serial; + cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count]; - for (int i = 0; i < cachedtex.WearableData.Length; i++) + for (int i = 0; i < cachedTextures.Count; i++) { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].TextureIndex = (byte)cachedTextures[i].BakedTextureIndex; + cachedresp.WearableData[i].TextureID = cachedTextures[i].BakedTextureID; cachedresp.WearableData[i].HostName = new byte[0]; } cachedresp.Header.Zerocoded = true; OutPacket(cachedresp, ThrottleOutPacketType.Task); - - return true; } protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) -- cgit v1.1 From 3290cd09d3ecd45c52bd131ada2a793c48fd99dc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 9 May 2013 18:12:17 +0100 Subject: remove pointless region handle paramter from IClientAPI.SendKillObject() --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 47dd842..e014471 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1588,7 +1588,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pc, ThrottleOutPacketType.Unknown); } - public void SendKillObject(ulong regionHandle, List localIDs) + public void SendKillObject(List localIDs) { // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); @@ -11555,8 +11555,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (part == null) { // It's a ghost! tell the client to delete it from view. - simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - new List { localId }); + simClient.SendKillObject(new List { localId }); } else { -- cgit v1.1 From 681fbda4b6b9700421b82dc639f954c60871542e Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 24 May 2013 13:18:16 -0700 Subject: This is an experimental patch that adds support for comparing texture hashes for the purpose of accurately responding to AgentTextureCached packets. There is a change to IClientAPI to report the wearbles hashes that come in through the SetAppearance packet. Added storage of the texture hashes in the appearance. While these are added to the Pack/Unpack (with support for missing values) routines (which means Simian will store them properly), they are not currently persisted in Robust. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e014471..dd8ef9c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6214,7 +6214,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - handlerSetAppearance(sender, te, visualparams); + List hashes = new List(); + for (int i = 0; i < appear.WearableData.Length; i++) + { + CachedTextureRequestArg arg = new CachedTextureRequestArg(); + arg.BakedTextureIndex = appear.WearableData[i].TextureIndex; + arg.WearableHashID = appear.WearableData[i].CacheID; + hashes.Add(arg); + } + + handlerSetAppearance(sender, te, visualparams, hashes); } catch (Exception e) { @@ -11487,12 +11496,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP requestArgs.Add(arg); } - CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; - if (handlerCachedTextureRequest != null) + try + { + CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; + if (handlerCachedTextureRequest != null) + { + handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); + } + } + catch (Exception e) { - handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); + m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e); + return false; } - + return true; } -- cgit v1.1 From 533bbf033df88fd231eb0e7d2b0aa5a0058163ea Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 May 2013 02:08:54 +0100 Subject: Update the money framework to allow sending the new style linden "serverside is now viewerside" messages regarding currency This will require all money modules to be refactored! --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dd8ef9c..e47397d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -345,7 +345,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // protected HashSet m_attachmentsSent; - private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; @@ -420,7 +419,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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++; } } /// @@ -483,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_firstName = sessionInfo.LoginInfo.First; m_lastName = sessionInfo.LoginInfo.Last; m_startpos = sessionInfo.LoginInfo.StartPos; - m_moneyBalance = 1000; m_udpServer = udpServer; m_udpClient = udpClient; @@ -1538,7 +1535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(tpProgress, ThrottleOutPacketType.Unknown); } - public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) + public void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item) { MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); money.MoneyData.AgentID = AgentId; @@ -1546,7 +1543,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP money.MoneyData.TransactionSuccess = success; money.MoneyData.Description = description; money.MoneyData.MoneyBalance = balance; - money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); + money.TransactionInfo.TransactionType = transactionType; + money.TransactionInfo.SourceID = sourceID; + money.TransactionInfo.IsSourceGroup = sourceIsGroup; + money.TransactionInfo.DestID = destID; + money.TransactionInfo.IsDestGroup = destIsGroup; + money.TransactionInfo.Amount = amount; + money.TransactionInfo.ItemDescription = Util.StringToBytes256(item); + OutPacket(money, ThrottleOutPacketType.Task); } @@ -2279,6 +2283,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) { + // Prepend a slash to make the message come up in the top right + // again. + // Allow special formats to be sent from aware modules. + if (!modal && !message.StartsWith("ALERT: ") && !message.StartsWith("NOTIFY: ") && message != "Home position set." && message != "You died and have been teleported to your home location") + message = "/" + message; AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); alertPack.AgentData.AgentID = AgentId; alertPack.AlertData.Message = Util.StringToBytes256(message); @@ -11933,17 +11942,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting, method); } - public bool AddMoney(int debit) - { - if (m_moneyBalance + debit >= 0) - { - m_moneyBalance += debit; - SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance); - return true; - } - return false; - } - protected void HandleAutopilot(Object sender, string method, List args) { float locx = 0; -- cgit v1.1 From 454499ff60bf45f77f6f25e9164fcbbfff967bba Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 7 Jun 2013 23:38:23 +0100 Subject: minor: Comment out debug logging (at warn level) about number of objects force selected and turn down to debug level --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e47397d..9784d15 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4828,7 +4828,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendForceClientSelectObjects(List ObjectIDs) { - m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); +// m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); bool firstCall = true; const int MAX_OBJECTS_PER_PACKET = 251; -- cgit v1.1 From 095066b1cefa7e25ba5983ead1818727c2d64ccc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Jul 2013 23:39:29 +0100 Subject: Handle UUIDNameRequest UDP packet processing async instead of within the main inbound UDP processing loop, to avoid any chance that this is delaying the main udp in loop. The potential impact of this should be lower now that these requests are being placed on a queue. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9784d15..bd61c3f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5390,7 +5390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); - AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); + AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest); AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); -- cgit v1.1 From 1b265b213b65076ee346d85f62d2d61a72ea3ca6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 10 Jul 2013 16:09:45 -0700 Subject: Added show client-stats [first last] command to expose what viewers are requesting. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bd61c3f..3d92705 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -678,12 +678,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP //there is a local handler for this packet type if (pprocessor.Async) { + ClientInfo cinfo = UDPClient.GetClientInfo(); + if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) + cinfo.AsyncRequests[packet.Type.ToString()] = 0; + cinfo.AsyncRequests[packet.Type.ToString()]++; + object obj = new AsyncPacketProcess(this, pprocessor.method, packet); Util.FireAndForget(ProcessSpecificPacketAsync, obj); result = true; } else { + ClientInfo cinfo = UDPClient.GetClientInfo(); + if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) + cinfo.SyncRequests[packet.Type.ToString()] = 0; + cinfo.SyncRequests[packet.Type.ToString()]++; + result = pprocessor.method(this, packet); } } @@ -698,6 +708,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (found) { + ClientInfo cinfo = UDPClient.GetClientInfo(); + if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString())) + cinfo.GenericRequests[packet.Type.ToString()] = 0; + cinfo.GenericRequests[packet.Type.ToString()]++; + result = method(this, packet); } } @@ -12030,7 +12045,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP ClientInfo info = m_udpClient.GetClientInfo(); info.proxyEP = null; - info.agentcircuit = RequestClientInfo(); + if (info.agentcircuit == null) + info.agentcircuit = RequestClientInfo(); return info; } -- cgit v1.1 From fe5da43d15506d029be260b2e60a69787686d062 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 10 Jul 2013 19:29:14 -0700 Subject: EXPERIMENTAL: make RequestImage (UDP packet handler) sync instead of async. This _shouldn't_ screw things up, given that all this does is to dump the request in a queue. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3d92705..16e7207 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5373,7 +5373,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); - AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); + AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false); AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); -- cgit v1.1 From 9173130fde7dd93d6d9ad5dea317e5f1f0e66b40 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 10 Jul 2013 20:48:13 -0700 Subject: Switched RegionHandshakeReply to Sync, because it's not doing anything blocking. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 16e7207..c5b6ac6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5312,7 +5312,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); - AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); + AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false); AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); -- cgit v1.1 From 3b48b6a7927796c3d830a83afe8c8ad558ddf1f8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 11 Jul 2013 09:44:48 -0700 Subject: Switched TransferRequest (UDP packet handler) to sync. The permissions checks may block, so they get a FireAndForget. Everything else is non-blocking. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 214 +++++++++++---------- 1 file changed, 115 insertions(+), 99 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c5b6ac6..ef4f190 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5374,7 +5374,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false); - AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); + AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest, false); AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); @@ -7751,129 +7751,145 @@ namespace OpenSim.Region.ClientStack.LindenUDP //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 - // UUID taskID = UUID.Zero; if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { - taskID = new UUID(transfer.TransferInfo.Params, 48); - UUID itemID = new UUID(transfer.TransferInfo.Params, 64); - UUID requestID = new UUID(transfer.TransferInfo.Params, 80); - -// m_log.DebugFormat( -// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}", -// requestID, itemID, taskID, Name); - if (!(((Scene)m_scene).Permissions.BypassPermissions())) { - if (taskID != UUID.Zero) // Prim + // We're spawning a thread because the permissions check can block this thread + Util.FireAndForget(delegate { - SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); + // This requests the asset if needed + HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer); + }); + return true; + } + } + else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) + { + //TransferRequestPacket does not include covenant uuid? + //get scene covenant uuid + taskID = m_scene.RegionInfo.RegionSettings.Covenant; + } - if (part == null) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist", - Name, requestID, itemID, taskID); - return true; - } + // This is non-blocking + MakeAssetRequest(transfer, taskID); - TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); - if (tii == null) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist", - Name, requestID, itemID, taskID); - return true; - } + return true; + } - if (tii.Type == (int)AssetType.LSLText) - { - if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) - return true; - } - else if (tii.Type == (int)AssetType.Notecard) - { - if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId)) - return true; - } - else - { - // TODO: Change this code to allow items other than notecards and scripts to be successfully - // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule - if (part.OwnerID != AgentId) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}", - Name, requestID, itemID, taskID, part.OwnerID); - return true; - } + private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer) + { + 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 ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set", - Name, requestID, itemID, taskID); - return true; - } + //m_log.DebugFormat( + // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}", + // requestID, itemID, taskID, Name); - if (tii.OwnerID != AgentId) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", - Name, requestID, itemID, taskID, tii.OwnerID); - return true; - } + //m_log.Debug("Transfer Request: " + transfer.ToString()); + // Validate inventory transfers + // Has to be done here, because AssetCache can't do it + // + if (taskID != UUID.Zero) // Prim + { + SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); - if (( - tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", - Name, requestID, itemID, taskID); - return true; - } + if (part == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist", + Name, requestID, itemID, taskID); + return; + } - if (tii.AssetID != requestID) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", - Name, requestID, itemID, taskID, tii.AssetID); - return true; - } - } + TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); + if (tii == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist", + Name, requestID, itemID, taskID); + return; + } + + if (tii.Type == (int)AssetType.LSLText) + { + if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) + return; + } + else if (tii.Type == (int)AssetType.Notecard) + { + if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId)) + return; + } + else + { + // TODO: Change this code to allow items other than notecards and scripts to be successfully + // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule + if (part.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}", + Name, requestID, itemID, taskID, part.OwnerID); + return; } - else // Agent + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) { - IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); - if (invAccess != null) - { - if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) - return false; - } - else - { - return false; - } + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set", + Name, requestID, itemID, taskID); + return; + } + + if (tii.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", + Name, requestID, itemID, taskID, tii.OwnerID); + return; + } + + if (( + tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", + Name, requestID, itemID, taskID); + return; + } + + if (tii.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", + Name, requestID, itemID, taskID, tii.AssetID); + return; } } } - else - if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) + else // Agent + { + IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); + if (invAccess != null) + { + if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) + return; + } + else { - //TransferRequestPacket does not include covenant uuid? - //get scene covenant uuid - taskID = m_scene.RegionInfo.RegionSettings.Covenant; + return; } + } + // Permissions out of the way, let's request the asset MakeAssetRequest(transfer, taskID); - return true; } + private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) { AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; -- cgit v1.1 From 604967b31e0ce4500587d0b88b81e6eecc4efdae Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 11 Jul 2013 09:47:46 -0700 Subject: Switched UUIDNameRequest and RegionHandleRequest to Sync, because now they are also non-blocking handlers. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ef4f190..79c80a7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5405,8 +5405,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); - AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest); - AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); + AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); + AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest, false); AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); -- cgit v1.1 From d9d995914c5fba00d4ccaf66b899384c8ea3d5eb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Jul 2013 01:17:46 +0100 Subject: try Hacking in an AutoResetEvent to control the outgoing UDP loop instead of a continuous loop with sleeps. Does appear to have a cpu impact but may need further tweaking --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 79c80a7..7229d7c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3776,6 +3776,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResendPrimUpdate(update); } +// OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> compressedUpdateBlocks = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> terseUpdateBlocks = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy>(); +// +// OpenSim.Framework.Lazy> objectUpdates = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> compressedUpdates = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> terseUpdates = new OpenSim.Framework.Lazy>(); +// OpenSim.Framework.Lazy> terseAgentUpdates = new OpenSim.Framework.Lazy>(); + + private void ProcessEntityUpdates(int maxUpdates) { OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); @@ -3788,6 +3799,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP OpenSim.Framework.Lazy> terseUpdates = new OpenSim.Framework.Lazy>(); OpenSim.Framework.Lazy> terseAgentUpdates = new OpenSim.Framework.Lazy>(); +// objectUpdateBlocks.Value.Clear(); +// compressedUpdateBlocks.Value.Clear(); +// terseUpdateBlocks.Value.Clear(); +// terseAgentUpdateBlocks.Value.Clear(); +// objectUpdates.Value.Clear(); +// compressedUpdates.Value.Clear(); +// terseUpdates.Value.Clear(); +// terseAgentUpdates.Value.Clear(); + // Check to see if this is a flush if (maxUpdates <= 0) { -- cgit v1.1 From 63c42d66022ea7f1c2805b8f77980af5d4ba1fb4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Jul 2013 21:28:36 +0100 Subject: Do some simple queue empty checks in the main outgoing udp loop instead of always performing these on a separate fired thread. This appears to improve cpu usage since launching a new thread is more expensive than performing a small amount of inline logic. However, needs testing at scale. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7229d7c..711a574 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -485,6 +485,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer = udpServer; m_udpClient = udpClient; m_udpClient.OnQueueEmpty += HandleQueueEmpty; + m_udpClient.HasUpdates += HandleHasUpdates; m_udpClient.OnPacketStats += PopulateStats; m_prioritizer = new Prioritizer(m_scene); @@ -4133,8 +4134,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) { +// if (!m_udpServer.IsRunningOutbound) +// return; + if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) { +// if (!m_udpServer.IsRunningOutbound) +// return; + if (m_maxUpdates == 0 || m_LastQueueFill == 0) { m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; @@ -4160,6 +4167,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); } + internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories) + { + bool hasUpdates = false; + + if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) + { + if (m_entityUpdates.Count > 0) + hasUpdates = true; + else if (m_entityProps.Count > 0) + hasUpdates = true; + } + + if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) + { + if (ImageManager.HasUpdates()) + hasUpdates = true; + } + + return hasUpdates; + } + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) { AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); -- cgit v1.1 From e5c677779b8501c245e5399240ffe3ca2519ec72 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Jul 2013 00:16:09 +0100 Subject: Add measure of number of inbound AgentUpdates that were seen as significant to "show client stats" (i.e. sent on for further processing instead of being discarded) Added here since it was the most convenient place Number is in the last column, "Sig. AgentUpdates" along with percentage of all AgentUpdates Percentage largely falls over time, most cpu for processing AgentUpdates may be in UDP processing as turning this off even earlier (with "debug lludp toggle agentupdate" results in a big cpu fall Also tidies up display. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 711a574..3145275 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5565,6 +5565,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Packet Handlers + public int TotalSignificantAgentUpdates { get; private set; } + #region Scene/Avatar private bool HandleAgentUpdate(IClientAPI sener, Packet packet) @@ -5614,6 +5616,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); + TotalSignificantAgentUpdates++; m_lastAgentUpdateArgs.AgentID = x.AgentID; m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; -- cgit v1.1 From 61eda1f441092eb12936472de2dc73898e40aa16 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Jul 2013 00:51:13 +0100 Subject: Make the check as to whether any particular inbound AgentUpdate packet is significant much earlier in UDP processing (i.e. before we pointlessly place such packets on internal queues, etc.) Appears to have some impact on cpu but needs testing. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 170 ++++++++++++++------- 1 file changed, 114 insertions(+), 56 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3145275..7e5511f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -357,7 +357,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods /// cannot retain a reference to it outside of that method. /// - private AgentUpdateArgs m_lastAgentUpdateArgs; + private AgentUpdateArgs m_lastAgentUpdateArgs = new AgentUpdateArgs(); + + private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs(); protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5569,80 +5571,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar + /// + /// This checks the update significance against the last update made. + /// + /// Can only be called by one thread at a time, and not at the same time as + /// + /// /returns> + /// + public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + { + bool update = false; + + if (m_lastAgentUpdateArgs != null) + { + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + update = + ( + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) + ); + } + else + { + m_lastAgentUpdateArgs = new AgentUpdateArgs(); + update = true; + } + + if (update) + { +// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); + TotalSignificantAgentUpdates++; + + m_lastAgentUpdateArgs.AgentID = x.AgentID; + m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_lastAgentUpdateArgs.Far = x.Far; + m_lastAgentUpdateArgs.Flags = x.Flags; + m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_lastAgentUpdateArgs.SessionID = x.SessionID; + m_lastAgentUpdateArgs.State = x.State; + } + + return update; + } + private bool HandleAgentUpdate(IClientAPI sener, Packet packet) { if (OnAgentUpdate != null) { AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; - #region Packet Session and User Check - if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) - { - PacketPool.Instance.ReturnPacket(packet); - return false; - } - #endregion - - bool update = false; + // Now done earlier +// #region Packet Session and User Check +// if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) +// { +// PacketPool.Instance.ReturnPacket(packet); +// return false; +// } +// #endregion +// +// bool update = false; AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; - - if (m_lastAgentUpdateArgs != null) - { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - update = - ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) - ); - } - else - { - m_lastAgentUpdateArgs = new AgentUpdateArgs(); - update = true; - } - - if (update) - { -// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); +// +// if (m_lastAgentUpdateArgs != null) +// { +// // These should be ordered from most-likely to +// // least likely to change. I've made an initial +// // guess at that. +// update = +// ( +// (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || +// (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || +// (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || +// (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || +// (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || +// (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || +// (x.Far != m_lastAgentUpdateArgs.Far) || +// (x.Flags != m_lastAgentUpdateArgs.Flags) || +// (x.State != m_lastAgentUpdateArgs.State) || +// (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || +// (x.SessionID != m_lastAgentUpdateArgs.SessionID) || +// (x.AgentID != m_lastAgentUpdateArgs.AgentID) +// ); +// } +// +// if (update) +// { +//// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); TotalSignificantAgentUpdates++; - m_lastAgentUpdateArgs.AgentID = x.AgentID; - m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_lastAgentUpdateArgs.Far = x.Far; - m_lastAgentUpdateArgs.Flags = x.Flags; - m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_lastAgentUpdateArgs.SessionID = x.SessionID; - m_lastAgentUpdateArgs.State = x.State; + m_thisAgentUpdateArgs.AgentID = x.AgentID; + m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_thisAgentUpdateArgs.Far = x.Far; + m_thisAgentUpdateArgs.Flags = x.Flags; + m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_thisAgentUpdateArgs.SessionID = x.SessionID; + m_thisAgentUpdateArgs.State = x.State; UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, m_lastAgentUpdateArgs); + OnPreAgentUpdate(this, m_thisAgentUpdateArgs); if (handlerAgentUpdate != null) - OnAgentUpdate(this, m_lastAgentUpdateArgs); + OnAgentUpdate(this, m_thisAgentUpdateArgs); handlerAgentUpdate = null; handlerPreAgentUpdate = null; - } +// } } PacketPool.Instance.ReturnPacket(packet); -- cgit v1.1 From 866de5397890edbc0355b1925bf8537b40bab6a3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Jul 2013 00:56:45 +0100 Subject: Remove some pointless code in CheckAgentUpdateSignificance() --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 50 +++++++++------------- 1 file changed, 20 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7e5511f..c5bb697 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5574,40 +5574,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// This checks the update significance against the last update made. /// - /// Can only be called by one thread at a time, and not at the same time as - /// + /// Can only be called by one thread at a time /// /returns> /// public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - bool update = false; - - if (m_lastAgentUpdateArgs != null) - { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - update = - ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) - ); - } - else - { - m_lastAgentUpdateArgs = new AgentUpdateArgs(); - update = true; - } + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + bool update = + ( + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) + ); + if (update) { -- cgit v1.1 From 3a6acbcc149fb359c2be2ee2c646c9b15809c01e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Jul 2013 01:00:38 +0100 Subject: furhter shorten CheckAgentUpdateSignificance(). No real perf impact. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c5bb697..3d085c3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5582,8 +5582,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // These should be ordered from most-likely to // least likely to change. I've made an initial // guess at that. - bool update = - ( + if ( (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || @@ -5596,10 +5595,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || (x.SessionID != m_lastAgentUpdateArgs.SessionID) || (x.AgentID != m_lastAgentUpdateArgs.AgentID) - ); - - - if (update) + ) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); TotalSignificantAgentUpdates++; @@ -5616,9 +5612,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; m_lastAgentUpdateArgs.SessionID = x.SessionID; m_lastAgentUpdateArgs.State = x.State; + + return true; } - return update; + return false; } private bool HandleAgentUpdate(IClientAPI sener, Packet packet) -- cgit v1.1 From 174105ad028c5ed318850238d97aa7c3b1d7f207 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 19 Jul 2013 22:11:32 -0700 Subject: Fixed the stats in show client stats. Also left some comments with observations about AgentUpdates. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3d085c3..66a8ea7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5567,7 +5567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Packet Handlers - public int TotalSignificantAgentUpdates { get; private set; } + public int TotalAgentUpdates { get; set; } #region Scene/Avatar @@ -5583,11 +5583,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP // least likely to change. I've made an initial // guess at that. if ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + /* These 4 are the worst offenders! We should consider ignoring most of them. + * With Singularity, there is a bug where sometimes the spam on these doesn't stop */ (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + /* */ + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || (x.Far != m_lastAgentUpdateArgs.Far) || (x.Flags != m_lastAgentUpdateArgs.Flags) || @@ -5597,8 +5600,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP (x.AgentID != m_lastAgentUpdateArgs.AgentID) ) { -// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - TotalSignificantAgentUpdates++; + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", + // x.CameraAtAxis, x.CameraCenter); + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", + // x.CameraLeftAxis, x.CameraUpAxis); + //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", + // x.BodyRotation, x.HeadRotation); + //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", + // x.ControlFlags, x.Flags, x.Far, x.State); m_lastAgentUpdateArgs.AgentID = x.AgentID; m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; @@ -5662,7 +5671,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // if (update) // { //// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - TotalSignificantAgentUpdates++; m_thisAgentUpdateArgs.AgentID = x.AgentID; m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; -- cgit v1.1 From d5a1779465b6d875ebe5822ce6f15df3378b759f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 20 Jul 2013 12:20:35 -0700 Subject: Manage AgentUpdates more sanely: - The existing event to scene has been split into 2: OnAgentUpdate and OnAgentCameraUpdate, to better reflect the two types of updates that the viewer sends. We can run one without the other, which is what happens when the avie is still but the user is camming around - Added thresholds (as opposed to equality) to determine whether the update is significant or not. I thin these thresholds are ok, but we can play with them later - Ignore updates of HeadRotation, which were problematic and aren't being used up stream --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 214 +++++++++++---------- 1 file changed, 108 insertions(+), 106 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 66a8ea7..6c58aac 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -96,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event Action OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; + public event UpdateAgent OnAgentCameraUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; @@ -357,9 +358,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods /// cannot retain a reference to it outside of that method. /// - private AgentUpdateArgs m_lastAgentUpdateArgs = new AgentUpdateArgs(); - private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs(); + private float qdelta1; + private float qdelta2; + private float vdelta1; + private float vdelta2; + private float vdelta3; + private float vdelta4; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5571,57 +5576,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar + private const float QDELTA = 0.01f; + private const float VDELTA = 0.01f; + /// /// This checks the update significance against the last update made. /// /// Can only be called by one thread at a time - /// /returns> + /// /// public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. + return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); + } + + /// + /// This checks the movement/state update significance against the last update made. + /// + /// Can only be called by one thread at a time + /// + /// + public bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + { + qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); + qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); + if ( + (qdelta1 > QDELTA) || + // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack + //(qdelta2 > QDELTA * 10) || + (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) || + (x.Far != m_thisAgentUpdateArgs.Far) || + (x.Flags != m_thisAgentUpdateArgs.Flags) || + (x.State != m_thisAgentUpdateArgs.State) + ) + { + //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", + // qdelta1, qdelta2); + //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3} (Thread {4})", + // x.ControlFlags, x.Flags, x.Far, x.State, Thread.CurrentThread.Name); + return true; + } + + return false; + } + + /// + /// This checks the camera update significance against the last update made. + /// + /// Can only be called by one thread at a time + /// + /// + public bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + { + vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); + vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); + vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); + vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); if ( - /* These 4 are the worst offenders! We should consider ignoring most of them. + /* These 4 are the worst offenders! * With Singularity, there is a bug where sometimes the spam on these doesn't stop */ - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - /* */ - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) + (vdelta1 > VDELTA) || + (vdelta2 > VDELTA) || + (vdelta3 > VDELTA) || + (vdelta4 > VDELTA) ) { //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", // x.CameraAtAxis, x.CameraCenter); //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", // x.CameraLeftAxis, x.CameraUpAxis); - //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", - // x.BodyRotation, x.HeadRotation); - //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", - // x.ControlFlags, x.Flags, x.Far, x.State); - - m_lastAgentUpdateArgs.AgentID = x.AgentID; - m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_lastAgentUpdateArgs.Far = x.Far; - m_lastAgentUpdateArgs.Flags = x.Flags; - m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_lastAgentUpdateArgs.SessionID = x.SessionID; - m_lastAgentUpdateArgs.State = x.State; - return true; } @@ -5629,75 +5652,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP } private bool HandleAgentUpdate(IClientAPI sener, Packet packet) - { - if (OnAgentUpdate != null) - { - AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; + { + // We got here, which means that something in agent update was significant - // Now done earlier -// #region Packet Session and User Check -// if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) -// { -// PacketPool.Instance.ReturnPacket(packet); -// return false; -// } -// #endregion -// -// bool update = false; - AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; -// -// if (m_lastAgentUpdateArgs != null) -// { -// // These should be ordered from most-likely to -// // least likely to change. I've made an initial -// // guess at that. -// update = -// ( -// (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || -// (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || -// (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || -// (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || -// (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || -// (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || -// (x.Far != m_lastAgentUpdateArgs.Far) || -// (x.Flags != m_lastAgentUpdateArgs.Flags) || -// (x.State != m_lastAgentUpdateArgs.State) || -// (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || -// (x.SessionID != m_lastAgentUpdateArgs.SessionID) || -// (x.AgentID != m_lastAgentUpdateArgs.AgentID) -// ); -// } -// -// if (update) -// { -//// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - - m_thisAgentUpdateArgs.AgentID = x.AgentID; - m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_thisAgentUpdateArgs.Far = x.Far; - m_thisAgentUpdateArgs.Flags = x.Flags; - m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_thisAgentUpdateArgs.SessionID = x.SessionID; - m_thisAgentUpdateArgs.State = x.State; - - UpdateAgent handlerAgentUpdate = OnAgentUpdate; - UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - - if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, m_thisAgentUpdateArgs); - - if (handlerAgentUpdate != null) - OnAgentUpdate(this, m_thisAgentUpdateArgs); - - handlerAgentUpdate = null; - handlerPreAgentUpdate = null; -// } - } + AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; + AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; + + if (x.AgentID != AgentId || x.SessionID != SessionId) + return false; + + // Before we update the current m_thisAgentUpdateArgs, let's check this again + // to see what exactly changed + bool movement = CheckAgentMovementUpdateSignificance(x); + bool camera = CheckAgentCameraUpdateSignificance(x); + + m_thisAgentUpdateArgs.AgentID = x.AgentID; + m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_thisAgentUpdateArgs.Far = x.Far; + m_thisAgentUpdateArgs.Flags = x.Flags; + m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_thisAgentUpdateArgs.SessionID = x.SessionID; + m_thisAgentUpdateArgs.State = x.State; + + UpdateAgent handlerAgentUpdate = OnAgentUpdate; + UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; + UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate; + + // Was there a significant movement/state change? + if (movement) + { + if (handlerPreAgentUpdate != null) + OnPreAgentUpdate(this, m_thisAgentUpdateArgs); + + if (handlerAgentUpdate != null) + OnAgentUpdate(this, m_thisAgentUpdateArgs); + } + // Was there a significant camera(s) change? + if (camera) + if (handlerAgentCameraUpdate != null) + handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs); + + handlerAgentUpdate = null; + handlerPreAgentUpdate = null; + handlerAgentCameraUpdate = null; PacketPool.Instance.ReturnPacket(packet); -- cgit v1.1 From 3919c805054e6ce240c72436414ecee18a6c2947 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 20 Jul 2013 13:42:39 -0700 Subject: A couple of small optimizations over the previous commit --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6c58aac..2907580 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5587,6 +5587,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { + // Compute these only once, when this function is called from down below + qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); + //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); + vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); + vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); + vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); + vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); + return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); } @@ -5596,10 +5604,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Can only be called by one thread at a time /// /// - public bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); - qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); if ( (qdelta1 > QDELTA) || // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack @@ -5626,12 +5632,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Can only be called by one thread at a time /// /// - public bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); - vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); - vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); - vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); if ( /* These 4 are the worst offenders! * With Singularity, there is a bug where sometimes the spam on these doesn't stop */ -- cgit v1.1 From b5ab0698d6328c90d779c2af29914da840335233 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 20 Jul 2013 17:58:32 -0700 Subject: EDIT BEAMS!!! They had been missing from OpenSim since ever. Thanks to lkalif for telling me how to route the information. The viewer effect is under the distance filter, so only avatars with cameras < 10m away see the beams. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 ++++------------------ 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2907580..a8759ab 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5016,7 +5016,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { ScenePresence presence = (ScenePresence)entity; - attachPoint = 0; + attachPoint = presence.State; collisionPlane = presence.CollisionPlane; position = presence.OffsetPosition; velocity = presence.Velocity; @@ -5040,7 +5040,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP SceneObjectPart part = (SceneObjectPart)entity; attachPoint = part.ParentGroup.AttachmentPoint; - + attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16)); // m_log.DebugFormat( // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", // attachPoint, part.Name, part.LocalId, Name); @@ -5068,7 +5068,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP pos += 4; // Avatar/CollisionPlane - data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; + data[pos++] = (byte) attachPoint; if (avatar) { data[pos++] = 1; @@ -12550,7 +12550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(dialog, ThrottleOutPacketType.Task); } - public void StopFlying(ISceneEntity p) + public void SendAgentTerseUpdate(ISceneEntity p) { if (p is ScenePresence) { @@ -12564,25 +12564,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP Vector3 pos = presence.AbsolutePosition; - if (presence.Appearance.AvatarHeight != 127.0f) - pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f)); - else - pos += new Vector3(0f, 0f, (1.56f/6f)); - - presence.AbsolutePosition = pos; - - // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. - // Collision plane below the avatar's position a 6th of the avatar's height is suitable. - // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a - // certain amount.. because the LLClient wouldn't land in that situation anyway. - - // why are we still testing for this really old height value default??? - if (presence.Appearance.AvatarHeight != 127.0f) - presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f); - else - presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f)); - - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = CreateImprovedTerseBlock(p, false); -- cgit v1.1 From 116a449d8945d1d04013860f952841a71df80be7 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 20 Jul 2013 19:20:20 -0700 Subject: The quaternion delta was a bit to high, now that the head rotation is out of the equation. (head rotation was the problematic one) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a8759ab..021b7c1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5576,7 +5576,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private const float QDELTA = 0.01f; + private const float QDELTA = 0.000001f; private const float VDELTA = 0.01f; /// -- cgit v1.1 From 99a727600b938383224285d9dad79e2b564cb1fe Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 21 Jul 2013 10:07:35 -0700 Subject: Minor cosmetic changes. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 50 ++++++++++------------ 1 file changed, 23 insertions(+), 27 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 021b7c1..e23e55b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5595,7 +5595,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); - return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); + bool significant = CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); + + // Emergency debugging + //if (significant) + //{ + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", + // x.CameraAtAxis, x.CameraCenter); + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", + // x.CameraLeftAxis, x.CameraUpAxis); + //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", + // qdelta1, qdelta2); + //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", + // x.ControlFlags, x.Flags, x.Far, x.State); + //} + + return significant; + } /// @@ -5606,24 +5622,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - if ( + return ( (qdelta1 > QDELTA) || // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack //(qdelta2 > QDELTA * 10) || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) || (x.Far != m_thisAgentUpdateArgs.Far) || (x.Flags != m_thisAgentUpdateArgs.Flags) || - (x.State != m_thisAgentUpdateArgs.State) - ) - { - //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", - // qdelta1, qdelta2); - //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3} (Thread {4})", - // x.ControlFlags, x.Flags, x.Far, x.State, Thread.CurrentThread.Name); - return true; - } - - return false; + (x.State != m_thisAgentUpdateArgs.State) + ); } /// @@ -5634,23 +5641,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - if ( - /* These 4 are the worst offenders! - * With Singularity, there is a bug where sometimes the spam on these doesn't stop */ + return ( (vdelta1 > VDELTA) || (vdelta2 > VDELTA) || (vdelta3 > VDELTA) || - (vdelta4 > VDELTA) - ) - { - //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", - // x.CameraAtAxis, x.CameraCenter); - //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", - // x.CameraLeftAxis, x.CameraUpAxis); - return true; - } - - return false; + (vdelta4 > VDELTA) + ); } private bool HandleAgentUpdate(IClientAPI sener, Packet packet) -- cgit v1.1 From e6b6af62dd677077664fdc8801b3a7e894a2b8da Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Jul 2013 15:41:14 -0700 Subject: Added check for user movement specification before discarding an incoming AgentUpdate packet. This fixes the problem with vehicles not moving forward after the first up-arrow. Code to fix a potential exception when using different IClientAPIs. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 81 +++++++++++----------- 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e23e55b..32549c8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -359,12 +359,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// cannot retain a reference to it outside of that method. /// private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs(); - private float qdelta1; - private float qdelta2; - private float vdelta1; - private float vdelta2; - private float vdelta3; - private float vdelta4; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5576,7 +5570,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar + // Threshold for body rotation to be a significant agent update private const float QDELTA = 0.000001f; + // Threshold for camera rotation to be a significant agent update private const float VDELTA = 0.01f; /// @@ -5587,31 +5583,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - // Compute these only once, when this function is called from down below - qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); - //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); - vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); - vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); - vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); - vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); - - bool significant = CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); - - // Emergency debugging - //if (significant) - //{ - //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", - // x.CameraAtAxis, x.CameraCenter); - //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", - // x.CameraLeftAxis, x.CameraUpAxis); - //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", - // qdelta1, qdelta2); - //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", - // x.ControlFlags, x.Flags, x.Far, x.State); - //} - - return significant; - + return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); } /// @@ -5622,15 +5594,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - return ( - (qdelta1 > QDELTA) || + float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); + //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); + + bool movementSignificant = + (qdelta1 > QDELTA) // significant if body rotation above threshold // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack - //(qdelta2 > QDELTA * 10) || - (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) || - (x.Far != m_thisAgentUpdateArgs.Far) || - (x.Flags != m_thisAgentUpdateArgs.Flags) || - (x.State != m_thisAgentUpdateArgs.State) - ); + // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold + || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed + || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands + || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed + || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed + || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed + ; + //if (movementSignificant) + //{ + //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", + // qdelta1, qdelta2); + //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", + // x.ControlFlags, x.Flags, x.Far, x.State); + //} + return movementSignificant; } /// @@ -5641,12 +5625,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - return ( + float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); + float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); + float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); + float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); + + bool cameraSignificant = (vdelta1 > VDELTA) || (vdelta2 > VDELTA) || (vdelta3 > VDELTA) || (vdelta4 > VDELTA) - ); + ; + + //if (cameraSignificant) + //{ + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", + // x.CameraAtAxis, x.CameraCenter); + //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", + // x.CameraLeftAxis, x.CameraUpAxis); + //} + + return cameraSignificant; } private bool HandleAgentUpdate(IClientAPI sener, Packet packet) -- cgit v1.1 From c0433d5e4c8170de10e16dd09d85bf620a1530ae Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 22 Jul 2013 18:46:51 -0700 Subject: Changed the RegionHandshake packet to the Unknown queue, so that it is sent with high priority and hopefully gets to the client before AgentMovementComplete --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 32549c8..8b2440a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -811,7 +811,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags; handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported - OutPacket(handshake, ThrottleOutPacketType.Task); + OutPacket(handshake, ThrottleOutPacketType.Unknown); } -- cgit v1.1 From 99a4a914887c16483074b0145b9b6da765ac024a Mon Sep 17 00:00:00 2001 From: teravus Date: Wed, 7 Aug 2013 21:22:04 -0500 Subject: * This makes in-world terrain editing smoother, even in MegaRegions. This change only affects the editing user's experience. Non-editing users will see nothing different from the current 'slow' result. See comments for the thought process and how the issues surrounding terrain editing, cache, bandwidth, threading, terrain patch reliability and throttling were balanced. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 33 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8b2440a..0dbce2f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -327,7 +327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PriorityQueue m_entityProps; private Prioritizer m_prioritizer; private bool m_disableFacelights = false; - + private volatile bool m_justEditedTerrain = false; /// /// List used in construction of data blocks for an object update packet. This is to stop us having to /// continually recreate it. @@ -1239,9 +1239,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLHeightFieldMoronize(map); LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); - layerpack.Header.Reliable = true; + + // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. + // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. + // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area + // invalidating previous packets for that area. - OutPacket(layerpack, ThrottleOutPacketType.Land); + // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a + // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower. + + // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will + // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain + // patches. + + // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss. + if (m_justEditedTerrain) + { + layerpack.Header.Reliable = false; + OutPacket(layerpack, + ThrottleOutPacketType.Unknown ); + } + else + { + layerpack.Header.Reliable = true; + OutPacket(layerpack, + ThrottleOutPacketType.Land); + } } catch (Exception e) { @@ -6263,6 +6286,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP //m_log.Info("[LAND]: LAND:" + modify.ToString()); if (modify.ParcelData.Length > 0) { + // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore, + // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit. + m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable if (OnModifyTerrain != null) { for (int i = 0; i < modify.ParcelData.Length; i++) @@ -6278,6 +6304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } + m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again } return true; -- cgit v1.1 From b1c26a56b3d615f3709363e3a2f91b5423f5891f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 8 Aug 2013 23:29:30 +0100 Subject: Fix an issue where under teleport v2 protocol, teleporting from regions in an line from A->B->C would not close region A when reaching C The root cause was that v2 was only closing neighbour agents if the root connection also needed a close. However, fixing this requires the neighbour regions also detect when they should not close due to re-teleports re-establishing the child connection. This involves restructuring the code to introduce a scene presence state machine that can serialize the different add and remove client calls that are now possible with the late close of the This commit appears to fix these issues and improve teleport, but still has holes on at least quick reteleporting (and possibly occasionally on ordinary teleports). Also, has not been completely tested yet in scenarios where regions are running on different simulators --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8b2440a..e775a81 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -512,7 +512,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP // We still perform a force close inside the sync lock since this is intended to attempt close where // there is some unidentified connection problem, not where we have issues due to deadlock if (!IsActive && !force) + { + m_log.DebugFormat( + "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", + Name, m_scene.Name); + return; + } IsActive = false; CloseWithoutChecks(); -- cgit v1.1 From 1f39a763a5186c7c51e10b5b055394672cc6c54e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Aug 2013 21:35:03 +0100 Subject: Don't allow users to attempt to sit on objects in a child region without going to that region first. If this is attempted, they get a "Try moving closer. Can't sit on object because it is not in the same region as you." message instead, which is the same as current ll grid. Sitting on ground is okay, since viewer navigates avatar to required region first before sitting. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f0d8181..8c51077 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6651,6 +6651,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion + if (SceneAgent.IsChildAgent) + { + SendCantSitBecauseChildAgentResponse(); + return true; + } + AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; if (handlerAgentRequestSit != null) @@ -6675,6 +6681,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion + if (SceneAgent.IsChildAgent) + { + SendCantSitBecauseChildAgentResponse(); + return true; + } + AgentSit handlerAgentSit = OnAgentSit; if (handlerAgentSit != null) { @@ -6684,6 +6696,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + /// + /// Used when a child agent gets a sit response which should not be fulfilled. + /// + private void SendCantSitBecauseChildAgentResponse() + { + SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you."); + } + private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) { SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; -- cgit v1.1 From a0c99a7dccbc625fc2c721da480521019260fc7b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Aug 2013 00:03:47 +0100 Subject: minor: remove mono compiler warning from LLClientView --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8c51077..1b091bf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12602,7 +12602,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (p is ScenePresence) { - ScenePresence presence = p as ScenePresence; // It turns out to get the agent to stop flying, you have to feed it stop flying velocities // There's no explicit message to send the client to tell it to stop flying.. it relies on the // velocity, collision plane and avatar height @@ -12610,15 +12609,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air // when the avatar stands up - Vector3 pos = presence.AbsolutePosition; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = CreateImprovedTerseBlock(p, false); const float TIME_DILATION = 1.0f; ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( PacketType.ImprovedTerseObjectUpdate); -- cgit v1.1 From 2dc92e7de11086c7649d3ee0f8adc974efce6805 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 4 Aug 2013 19:19:11 +0200 Subject: Preserve attachment point & position when attachment is rezzed in world Patch taken from http://opensimulator.org/mantis/view.php?id=4905 originally by Greg C. Fixed to apply to r/23314 commit ba9daf849e7c8db48e7c03e7cdedb77776b2052f (cherry picked from commit 4ff9fbca441110cc2b93edc7286e0e9339e61cbe) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1b091bf..3609ec1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12188,6 +12188,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP shape.PCode = addPacket.ObjectData.PCode; shape.State = addPacket.ObjectData.State; + shape.LastAttachPoint = addPacket.ObjectData.State; shape.PathBegin = addPacket.ObjectData.PathBegin; shape.PathEnd = addPacket.ObjectData.PathEnd; shape.PathScaleX = addPacket.ObjectData.PathScaleX; -- cgit v1.1 From 2cd95fac736cc99b1a2ad661e4a03810225ffaca Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Sep 2013 22:27:39 +0100 Subject: refactor: Rename Scene.AddNewClient() to AddNewAgent() to make it obvious in the code that this is symmetric with CloseAgent() --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3609ec1..6b58fb7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -750,7 +750,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewAgent(this, PresenceType.User); RefreshGroupMembership(); } -- cgit v1.1 From 317c04fe1714631d851684e3bb294f02056bcd07 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 19 Sep 2013 12:14:21 -0700 Subject: VarRegion: change RegionInfo storage of region coordinates from region count number to integer world coordinates. Added new methods RegionWorldLoc[XY]. Refactored name of 'RegionLoc*' to 'LegacyRegionLoc*' throughout OpenSim. Kept old 'RegionLoc*' entrypoint to RegionInfo for downward compatability of external region management packages. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6b58fb7..22bff9f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2910,8 +2910,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { pos = (land.AABBMax + land.AABBMin) * 0.5f; } - reply.Data.GlobalX = info.RegionLocX + x; - reply.Data.GlobalY = info.RegionLocY + y; + reply.Data.GlobalX = info.LegacyRegionLocX + x; + reply.Data.GlobalY = info.LegacyRegionLocY + y; reply.Data.GlobalZ = pos.Z; reply.Data.SimName = Utils.StringToBytes(info.RegionName); reply.Data.SnapshotID = land.SnapshotID; -- cgit v1.1 From 8c1d80fdfd104b94cb7a4fd247b3baa2a9988ea1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Sep 2013 17:21:20 -0700 Subject: varregion: serious rework of TerrainChannel: -- addition of varaible region size in X and Y -- internal storage of heightmap changed from double[] to short[] -- helper routines for handling internal structure while keeping existing API -- to and from XML that adds region size information (for downward compatibility, output in the legacy XML format if X and Y are 256) Updated and commented Constants.RegionSize but didn't change the name for compatibility. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 22bff9f..fea9ddf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1240,9 +1240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { int[] patches = new int[] { py * 16 + px }; - float[] heightmap = (map.Length == 65536) ? - map : - LLHeightFieldMoronize(map); + float[] heightmap = (map.Length == 65536) ? map : LLHeightFieldMoronize(map); LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); -- cgit v1.1 From 7416809077227f35ab70ed44060e51f2bcf66937 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 2 Oct 2013 16:59:37 -0700 Subject: varregion: plug in TerrainData class and modify TerrainModule and LLClientView to use same. This passes a terrain info class around rather than passing a one dimensional array thus allowing variable regions. Update the database storage for variable region sizes. This should be downward compatible (same format for 256x256 regions). --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 69 +++++++--------------- 1 file changed, 20 insertions(+), 49 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fea9ddf..7984acc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -34,11 +34,13 @@ 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.Monitoring; @@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces; using Timer = System.Timers.Timer; using AssetLandmark = OpenSim.Framework.AssetLandmark; using RegionFlags = OpenMetaverse.RegionFlags; -using Nini.Config; using System.IO; using PermissionMask = OpenSim.Framework.PermissionMask; @@ -307,6 +308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static string LogHeader = "[LLCLIENTVIEW]"; protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients /// @@ -447,7 +449,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // ~LLClientView() // { -// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); +// m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode); // } /// @@ -513,9 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // there is some unidentified connection problem, not where we have issues due to deadlock if (!IsActive && !force) { - m_log.DebugFormat( - "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", - Name, m_scene.Name); + m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set", + LogHeader, Name, m_scene.Name); return; } @@ -1162,10 +1163,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private void DoSendLayerData(object o) { - float[] map = LLHeightFieldMoronize((float[])o); + float[] map = (float[])o; try { + // Send LayerData in typerwriter pattern //for (int y = 0; y < 16; y++) //{ // for (int x = 0; x < 16; x++) @@ -1230,7 +1232,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // } /// - /// Sends a specified patch to a client + /// Sends a terrain packet for the point specified. + /// This is a legacy call that has refarbed the terrain into a flat map of floats. + /// We just use the terrain from the region we know about. /// /// Patch coordinate (x) 0..15 /// Patch coordinate (y) 0..15 @@ -1239,10 +1243,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { try { - int[] patches = new int[] { py * 16 + px }; - float[] heightmap = (map.Length == 65536) ? map : LLHeightFieldMoronize(map); - - LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); + // For unknown reasons, after this point, patch numbers are swapped X for y. + // That means, that for - /// Munges heightfield into the LLUDP backed in restricted heightfield. - /// - /// float array in the base; Constants.RegionSize - /// float array in the base 256 - internal float[] LLHeightFieldMoronize(float[] map) - { - if (map.Length == 65536) - return map; - else - { - float[] returnmap = new float[65536]; - - if (map.Length < 65535) - { - // rebase the vector stride to 256 - for (int i = 0; i < Constants.RegionSize; i++) - Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize); - } - else - { - for (int i = 0; i < 256; i++) - Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256); - } - - //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536); - - return returnmap; - } - - } - - /// /// Send the wind matrix to the client /// /// 16x16 array of wind speeds @@ -2780,8 +2751,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (req.AssetInf.Data == null) { - m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", - req.AssetInf.ID, req.AssetInf.Metadata.ContentType); + m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null", + LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType); return; } -- cgit v1.1 From df76e5231035c8d45b4e8a28c1f21a18b4974b67 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 24 Oct 2013 23:00:02 +0100 Subject: minor: Add commented out code for apparent passing of texture IDs in ObjectProperties UDP replies to viewer Not yet shown that this is used or resolves a bug where not all textures appear on objects with an "XML with textures" upload from singularity 1.8.3 Proper texture entries are actually present and appear properly on relog, but not on select from viewer until at least one face texture is changed. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6b58fb7..03cd2b4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4546,6 +4546,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP SceneObjectPart root = sop.ParentGroup.RootPart; block.TouchName = Util.StringToBytes256(root.TouchName); + + // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but + // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached + // copy is really needed since it's less efficient to be constantly recreating this byte array. +// using (MemoryStream memStream = new MemoryStream()) +// { +// using (BinaryWriter binWriter = new BinaryWriter(memStream)) +// { +// for (int i = 0; i < sop.GetNumberOfSides(); i++) +// { +// Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i]; +// +// UUID textureID; +// +// if (teFace != null) +// textureID = teFace.TextureID; +// else +// textureID = sop.Shape.Textures.DefaultTexture.TextureID; +// +// binWriter.Write(textureID.GetBytes()); +// } +// +// block.TextureID = memStream.ToArray(); +// } +// } + block.TextureID = new byte[0]; // TextureID ??? block.SitName = Util.StringToBytes256(root.SitName); block.OwnerMask = root.OwnerMask; -- cgit v1.1 From 39777db8ef0604ad228854ce226bb530c2d27239 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 31 Oct 2013 09:24:06 -0700 Subject: varregion: fix problem of X/Y dimensions swapped and incorrect terrain compression base computation. Complete replacement of float[] for terrain heightmap with TerrainData instance. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2b8a04f..c8e7eb5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1154,7 +1154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// heightmap public virtual void SendLayerData(float[] map) { - Util.FireAndForget(DoSendLayerData, map); + Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData()); } /// @@ -1163,7 +1163,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private void DoSendLayerData(object o) { - float[] map = (float[])o; + TerrainData map = (TerrainData)o; try { @@ -1177,7 +1177,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //} // Send LayerData in a spiral pattern. Fun! - SendLayerTopRight(map, 0, 0, 15, 15); + SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1); } catch (Exception e) { @@ -1185,7 +1185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2) + private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2) { // Row for (int i = x1; i <= x2; i++) @@ -1199,7 +1199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); } - void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2) + void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2) { // Row in reverse for (int i = x2; i >= x1; i--) @@ -1231,6 +1231,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP // OutPacket(layerpack, ThrottleOutPacketType.Land); // } + // Legacy form of invocation that passes around a bare data array. + // Just ignore what was passed and use the real terrain info that is part of the scene. + public void SendLayerData(int px, int py, float[] map) + { + SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); + } + /// /// Sends a terrain packet for the point specified. /// This is a legacy call that has refarbed the terrain into a flat map of floats. @@ -1239,15 +1246,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Patch coordinate (x) 0..15 /// Patch coordinate (y) 0..15 /// heightmap - public void SendLayerData(int px, int py, float[] map) + public void SendLayerData(int px, int py, TerrainData terrData) { try { - // For unknown reasons, after this point, patch numbers are swapped X for y. - // That means, that for 0) + if (x2 - x1 > 0 && y2 - y1 > 0) SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); } @@ -1209,7 +1209,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int j = y2 - 1; j >= y1; j--) SendLayerData(x1, j, map); - if (x2 - x1 > 0) + if (x2 - x1 > 0 && y2 - y1 > 0) SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); } -- cgit v1.1 From 26fd29622d602cbd63743f4f2fa0b681b00826ed Mon Sep 17 00:00:00 2001 From: Latif Khalifa Date: Wed, 6 Nov 2013 03:48:48 +0100 Subject: Added sending (for now hard-coded) sim isze in SendMapBlockSplit() --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1a2d4de..20bc59c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1463,6 +1463,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP mapReply.AgentData.AgentID = AgentId; mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; + mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length]; mapReply.AgentData.Flags = flag; for (int i = 0; i < mapBlocks2.Length; i++) @@ -1477,6 +1478,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; mapReply.Data[i].Access = mapBlocks2[i].Access; mapReply.Data[i].Agents = mapBlocks2[i].Agents; + + // TODO: hookup varregion sim size here + mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock(); + mapReply.Size[i].SizeX = 256; + mapReply.Size[i].SizeY = 256; } OutPacket(mapReply, ThrottleOutPacketType.Land); } -- cgit v1.1 From ff4e7de7769b7eaa1b4fd3917e59f362b708226a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 23 Nov 2013 00:53:09 +0000 Subject: Fix issue where sitting on non-root linked prims would send camera to wrong position in third-person and mouselook We now specify sits as offsets from the root prim, as the viewer expects. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 20bc59c..29751ff 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5218,7 +5218,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); update.ObjectData = objectData; - update.ParentID = data.ParentID; + + SceneObjectPart parentPart = data.ParentPart; + if (parentPart != null) + update.ParentID = parentPart.ParentGroup.LocalId; + else + update.ParentID = 0; + update.PathCurve = 16; update.PathScaleX = 100; update.PathScaleY = 100; -- cgit v1.1 From 9bdd3dc7de46507b490a2eae5160123a28133d63 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 23 Nov 2013 01:12:20 +0000 Subject: Still send CameraEyeOffset in UDP SendSitReponse even if at offset is Vector3.Zero As far as I can see it's valid to change the eye offset even if you aren't changing the at target. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 29751ff..1ac9d7f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2635,11 +2635,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); avatarSitResponse.SitObject.ID = TargetID; - if (CameraAtOffset != Vector3.Zero) - { - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; - } + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; avatarSitResponse.SitTransform.AutoPilot = autopilot; avatarSitResponse.SitTransform.SitPosition = OffsetPos; -- cgit v1.1 From a68d1fad73f1b11ef5c1be84da0689586a2c7870 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 23 Nov 2013 02:29:14 +0000 Subject: Revert "Still send CameraEyeOffset in UDP SendSitReponse even if at offset is Vector3.Zero" This reverts commit 9bdd3dc7de46507b490a2eae5160123a28133d63. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1ac9d7f..29751ff 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2635,8 +2635,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); avatarSitResponse.SitObject.ID = TargetID; - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; + if (CameraAtOffset != Vector3.Zero) + { + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; + } avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; avatarSitResponse.SitTransform.AutoPilot = autopilot; avatarSitResponse.SitTransform.SitPosition = OffsetPos; -- cgit v1.1 From 60e049ea39f9b347ac1395c2373d17a983ab7ff3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 23 Nov 2013 02:31:39 +0000 Subject: Revert "Fix issue where sitting on non-root linked prims would send camera to wrong position in third-person and mouselook" Reverting to place on separate branch This reverts commit ff4e7de7769b7eaa1b4fd3917e59f362b708226a. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 29751ff..20bc59c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5218,13 +5218,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); update.ObjectData = objectData; - - SceneObjectPart parentPart = data.ParentPart; - if (parentPart != null) - update.ParentID = parentPart.ParentGroup.LocalId; - else - update.ParentID = 0; - + update.ParentID = data.ParentID; update.PathCurve = 16; update.PathScaleX = 100; update.PathScaleY = 100; -- cgit v1.1 From 0785210e29c75b09084321dca0569c9e4b73f858 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 27 Nov 2013 02:08:22 +0000 Subject: Fix stand positions rather than having the stand jump to the root prim. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1ac9d7f..c1aae3f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5076,6 +5076,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { ScenePresence presence = (ScenePresence)entity; +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); + attachPoint = presence.State; collisionPlane = presence.CollisionPlane; position = presence.OffsetPosition; @@ -5195,6 +5198,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name); + byte[] objectData = new byte[76]; data.CollisionPlane.ToBytes(objectData, 0); @@ -12646,6 +12652,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (p is ScenePresence) { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}", +// p.Name, Name, Scene.Name); + // It turns out to get the agent to stop flying, you have to feed it stop flying velocities // There's no explicit message to send the client to tell it to stop flying.. it relies on the // velocity, collision plane and avatar height -- cgit v1.1 From 8b3a4367ea8d7a0a8b6fbbf261b61f28b5cbab51 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 29 Nov 2013 02:51:35 +0000 Subject: Still send CameraEyeOffset in UDP SendSitReponse even if at offset is Vector3.Zero --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8592650..c1aae3f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2635,11 +2635,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); avatarSitResponse.SitObject.ID = TargetID; - if (CameraAtOffset != Vector3.Zero) - { - avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; - avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; - } + avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset; + avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset; avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; avatarSitResponse.SitTransform.AutoPilot = autopilot; avatarSitResponse.SitTransform.SitPosition = OffsetPos; -- cgit v1.1 From 17b32b764acd815400d9eb903aaec6dcebd60ac7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 5 Dec 2013 02:10:46 +0000 Subject: Fix regression where mouse look flight direction no longer worked by zeroing x/y rot before sending agent updates, instead of before any agent update processing It turns out that the x/y rot data in mouselook is needed to implement this and to push the avatar against the ground if walking in mouselook. Doing this in the terse send so that we preserve mouselook rotation information --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c1aae3f..a04ded5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5091,7 +5091,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP // acceleration = new Vector3(1, 0, 0); angularVelocity = presence.AngularVelocity; + + // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis + // it rotates around. + // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted + // excessive up and down movements of the camera when looking up and down. + // See http://opensimulator.org/mantis/view.php?id=3274 + // This does not affect head movement, since this is controlled entirely by camera movement rather than + // body rotation. It does not affect sitting avatar since it's the sitting part rotation that takes + // effect, not the avatar rotation. rotation = presence.Rotation; + rotation.X = 0; + rotation.Y = 0; if (sendTexture) textureEntry = presence.Appearance.Texture.GetBytes(); @@ -5207,7 +5218,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP data.OffsetPosition.ToBytes(objectData, 16); // data.Velocity.ToBytes(objectData, 28); // data.Acceleration.ToBytes(objectData, 40); - data.Rotation.ToBytes(objectData, 52); + + // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis + // it rotates around. + // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted + // excessive up and down movements of the camera when looking up and down. + // See http://opensimulator.org/mantis/view.php?id=3274 + // This does not affect head movement, since this is controlled entirely by camera movement rather than + // body rotation. It does not affect sitting avatar since it's the sitting part rotation that takes + // effect, not the avatar rotation. + Quaternion rot = data.Rotation; + rot.X = 0; + rot.Y = 0; + rot.ToBytes(objectData, 52); //data.AngularVelocity.ToBytes(objectData, 64); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); -- cgit v1.1 From 5b73b9c4a85335ba837280688b903fef44be8f35 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 11 Dec 2013 01:39:56 +0000 Subject: Committing the Avination Scene Presence and related texture code - Parts of region crossing code - New bakes handling code - Bakes now sent from sim to sim without central storage - Appearance handling changes - Some changes to sitting - A number of unrelated fixes and improvements --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a04ded5..6cb7332 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6437,26 +6437,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP // 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 + Vector3 avSize = appear.AgentData.Size; try { byte[] visualparams = new byte[appear.VisualParam.Length]; for (int i = 0; i < appear.VisualParam.Length; i++) visualparams[i] = appear.VisualParam[i].ParamValue; + //var b = appear.WearableData[0]; Primitive.TextureEntry te = null; if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - List hashes = new List(); - for (int i = 0; i < appear.WearableData.Length; i++) - { - CachedTextureRequestArg arg = new CachedTextureRequestArg(); - arg.BakedTextureIndex = appear.WearableData[i].TextureIndex; - arg.WearableHashID = appear.WearableData[i].CacheID; - hashes.Add(arg); - } + WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; + for (int i=0; i= m_scene.RegionInfo.WorldLocX) + && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) + && (locY >= m_scene.RegionInfo.WorldLocY) + && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) + { + tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; + tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; + tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY; + } + handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, tpLocReq.Info.LookAt, 16); } -- cgit v1.1 From 49c2213a0115663b7a0e57206c91f2270709b69a Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 4 Feb 2014 01:54:16 +0000 Subject: Dropping the rest of Avination's modified appearance code for core. Module to follow. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 159 ++++++++++++++++++--- 1 file changed, 141 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 585cdc4..1f522e8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -325,6 +325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private readonly byte[] m_channelVersion = Utils.EmptyBytes; private readonly IGroupsModule m_GroupsModule; + private int m_cachedTextureSerial; private PriorityQueue m_entityUpdates; private PriorityQueue m_entityProps; private Prioritizer m_prioritizer; @@ -11742,36 +11743,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) { + //m_log.Debug("texture cached: " + packet.ToString()); AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); if (cachedtex.AgentData.SessionID != SessionId) return false; - List requestArgs = new List(); - for (int i = 0; i < cachedtex.WearableData.Length; i++) - { - CachedTextureRequestArg arg = new CachedTextureRequestArg(); - arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex; - arg.WearableHashID = cachedtex.WearableData[i].ID; - - requestArgs.Add(arg); - } + // 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]; + + //IAvatarFactoryModule fac = m_scene.RequestModuleInterface(); + // var item = fac.GetBakedTextureFaces(AgentId); + //WearableCacheItem[] items = fac.GetCachedItems(AgentId); + + IAssetService cache = m_scene.AssetService; + IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); + //bakedTextureModule = null; + int maxWearablesLoop = cachedtex.WearableData.Length; + if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) + maxWearablesLoop = AvatarWearable.MAX_WEARABLES; + + if (bakedTextureModule != null && cache != null) + { + // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid + + WearableCacheItem[] cacheItems = null; + ScenePresence p = m_scene.GetScenePresence(AgentId); + if (p.Appearance != null) + if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty) + { + try + { + cacheItems = bakedTextureModule.Get(AgentId); + p.Appearance.WearableCacheItems = cacheItems; + p.Appearance.WearableCacheItemsDirty = false; + } - try - { - CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; - if (handlerCachedTextureRequest != null) + /* + * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception! + * + catch (System.Net.Sockets.SocketException) + { + cacheItems = null; + } + catch (WebException) + { + cacheItems = null; + } + catch (InvalidOperationException) + { + cacheItems = null; + } */ + catch (Exception) + { + cacheItems = null; + } + + } + else if (p.Appearance.WearableCacheItems != null) + { + cacheItems = p.Appearance.WearableCacheItems; + } + + if (cache != null && cacheItems != null) { - handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); + foreach (WearableCacheItem item in cacheItems) + { + + if (cache.GetCached(item.TextureID.ToString()) == null) + { + item.TextureAsset.Temporary = true; + cache.Store(item.TextureAsset); + } + + + } + } + if (cacheItems != null) + { + + for (int i = 0; i < maxWearablesLoop; i++) + { + WearableCacheItem item = + WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems); + + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].HostName = new byte[0]; + if (item != null && cachedtex.WearableData[i].ID == item.CacheId) + { + + cachedresp.WearableData[i].TextureID = item.TextureID; + } + else + { + cachedresp.WearableData[i].TextureID = UUID.Zero; + } + } + } + else + { + for (int i = 0; i < maxWearablesLoop; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } } } - catch (Exception e) + else { - m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e); - return false; + if (cache == null) + { + for (int i = 0; i < maxWearablesLoop; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } + } + else + { + for (int i = 0; i < maxWearablesLoop; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + + + + if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null) + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + else + cachedresp.WearableData[i].TextureID = UUID.Zero; + // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } + } } - + cachedresp.Header.Zerocoded = true; + OutPacket(cachedresp, ThrottleOutPacketType.Task); + return true; } -- cgit v1.1 From c0cc5e0fa4b8d469fdbb1c33a4b9e35ec768dee5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 8 Feb 2014 08:35:06 -0800 Subject: varregion: Send large region patches for wind and clouds. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1f522e8..9d39daa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1323,7 +1323,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind); + byte layerType = (byte)TerrainPatch.LayerType.Wind; + if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) + layerType = (byte)TerrainPatch.LayerType.WindExtended; + + LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, + (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); layerpack.Header.Zerocoded = true; OutPacket(layerpack, ThrottleOutPacketType.Wind); } @@ -1347,7 +1352,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud); + byte layerType = (byte)TerrainPatch.LayerType.Cloud; + if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) + layerType = (byte)TerrainPatch.LayerType.CloudExtended; + + LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, + (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); layerpack.Header.Zerocoded = true; OutPacket(layerpack, ThrottleOutPacketType.Cloud); } -- cgit v1.1 From 0b213af675d6859b4bdace98b249ea18e9ca32f2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 22 Feb 2014 15:04:28 -0800 Subject: Fix problem of hurricane speed winds. Thanks Vegaslon. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9d39daa..05dd764 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1309,18 +1309,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Vector2[] windSpeeds = (Vector2[])o; TerrainPatch[] patches = new TerrainPatch[2]; - patches[0] = new TerrainPatch(); - patches[0].Data = new float[16 * 16]; - patches[1] = new TerrainPatch(); - patches[1].Data = new float[16 * 16]; + patches[0] = new TerrainPatch { Data = new float[16 * 16] }; + patches[1] = new TerrainPatch { Data = new float[16 * 16] }; - for (int y = 0; y < 16; y++) + for (int x = 0; x < 16 * 16; x++) { - for (int x = 0; x < 16; x++) - { - patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X; - patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y; - } + patches[0].Data[x] = windSpeeds[x].X; + patches[1].Data[x] = windSpeeds[x].Y; } byte layerType = (byte)TerrainPatch.LayerType.Wind; -- cgit v1.1 From a2dd8f31dea20d43c942aeee7aae8b208989bbe7 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 30 Oct 2013 12:46:03 +0200 Subject: Trim search queries (for users, groups, etc.). I have found that sometimes the viewer adds a space at the end, which causes searches to fail. Resolves http://opensimulator.org/mantis/view.php?id=6935 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 05dd764..86161c9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -10387,7 +10387,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerDirFindQuery(this, dirFindQueryPacket.QueryData.QueryID, Utils.BytesToString( - dirFindQueryPacket.QueryData.QueryText), + dirFindQueryPacket.QueryData.QueryText).Trim(), dirFindQueryPacket.QueryData.QueryFlags, dirFindQueryPacket.QueryData.QueryStart); } -- cgit v1.1 From e735f765539dc2f9a6b5d072b114a5b0116dba9f Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 19 Dec 2013 10:51:10 +0200 Subject: LogThreadPool: when the thread is for ProcessPacketMethod, also log the packet type Resolves http://opensimulator.org/mantis/view.php?id=6945 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 86161c9..d9fe4e2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -694,7 +694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP cinfo.AsyncRequests[packet.Type.ToString()]++; object obj = new AsyncPacketProcess(this, pprocessor.method, packet); - Util.FireAndForget(ProcessSpecificPacketAsync, obj); + Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); result = true; } else -- cgit v1.1 From c8914d22ebb66fd9601161c9826d8b29ff6cb561 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 12 Apr 2014 17:37:57 -0700 Subject: BulletSim: reduce the terrain collison margin to be the same as other objects in the world. This was originally changed in an attempt to make vehicles work better but the effect was not that large and it causes avatars to float above the terrain. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d9fe4e2..f80f5a0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1251,6 +1251,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { try { + /* test code using the terrain compressor in libOpenMetaverse + int[] patchInd = new int[1]; + patchInd[0] = px + (py * Constants.TerrainPatchSize); + LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); + */ LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py); // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. @@ -1322,6 +1327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) layerType = (byte)TerrainPatch.LayerType.WindExtended; + // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); layerpack.Header.Zerocoded = true; @@ -1351,6 +1357,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) layerType = (byte)TerrainPatch.LayerType.CloudExtended; + // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); layerpack.Header.Zerocoded = true; -- cgit v1.1 From 853c0fccc88e78500364abb25b822a0d9f1337b1 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 16 Apr 2014 14:53:19 +0300 Subject: Fixed: when any avatar changed his Active Group, it was set as the active group for *all* the avatars in the scene (not permanently) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f80f5a0..c905f20 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -397,9 +397,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } public UUID AgentId { get { return m_agentId; } } public ISceneAgent SceneAgent { get; set; } - public UUID ActiveGroupId { get { return m_activeGroupID; } } - public string ActiveGroupName { get { return m_activeGroupName; } } - public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } + public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } } + public string ActiveGroupName { get { return m_activeGroupName; } private set { m_activeGroupName = value; } } + public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } } public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } /// @@ -2271,9 +2271,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) { - m_activeGroupID = activegroupid; - m_activeGroupName = groupname; - m_activeGroupPowers = grouppowers; + if (agentid == AgentId) + { + ActiveGroupId = activegroupid; + ActiveGroupName = groupname; + ActiveGroupPowers = grouppowers; + } AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; @@ -5415,8 +5418,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public ulong GetGroupPowers(UUID groupID) { - if (groupID == m_activeGroupID) - return m_activeGroupPowers; + if (groupID == ActiveGroupId) + return ActiveGroupPowers; if (m_groupPowers.ContainsKey(groupID)) return m_groupPowers[groupID]; @@ -7166,7 +7169,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, dupe.SharedData.DuplicateFlags, AgentId, - m_activeGroupID); + ActiveGroupId); } } @@ -7779,7 +7782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerObjectDuplicateOnRay != null) { handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + AgentId, ActiveGroupId, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); } -- cgit v1.1 From 998d7009a65def0a4debc9369d35b63611db5b55 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 22 Apr 2014 20:04:12 +0300 Subject: Eliminated many warnings --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c905f20..3ab837d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -71,7 +71,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Events - public event GenericMessage OnGenericMessage; public event BinaryGenericMessage OnBinaryGenericMessage; public event Action OnLogout; public event ObjectPermissions OnObjectPermissions; @@ -79,13 +78,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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 OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; - public event CachedTextureRequest OnCachedTextureRequest; public event SetAppearance OnSetAppearance; public event AvatarNowWearing OnAvatarNowWearing; public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; @@ -138,15 +135,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; public event UpdateVector OnUpdatePrimScale; public event UpdateVector OnUpdatePrimGroupScale; - public event StatusChange OnChildAgentStatus; - public event GenericCall2 OnStopMovement; - public event Action OnRemoveAvatar; public event RequestMapBlocks OnRequestMapBlocks; public event RequestMapName OnMapNameRequest; public event TeleportLocationRequest OnTeleportLocationRequest; public event TeleportLandmarkRequest OnTeleportLandmarkRequest; public event TeleportCancel OnTeleportCancel; - public event DisconnectUser OnDisconnectUser; public event RequestAvatarProperties OnRequestAvatarProperties; public event SetAlwaysRun OnSetAlwaysRun; public event FetchInventory OnAgentDataUpdateRequest; @@ -176,7 +169,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; @@ -207,7 +199,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; @@ -216,7 +207,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; @@ -239,7 +229,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; public event Action OnAutoPilotGo; - public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; public event ObjectOwner OnObjectOwner; @@ -297,6 +286,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event GodlikeMessage onGodlikeMessage; public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; +#pragma warning disable 0067 + public event GenericMessage OnGenericMessage; + public event TextureRequest OnRequestTexture; + public event StatusChange OnChildAgentStatus; + public event GenericCall2 OnStopMovement; + public event Action OnRemoveAvatar; + public event DisconnectUser OnDisconnectUser; + public event RequestAsset OnRequestAsset; + public event BuyObjectInventory OnBuyObjectInventory; + public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; + public event TerrainUnacked OnUnackedTerrain; + public event CachedTextureRequest OnCachedTextureRequest; +#pragma warning restore 0067 + #endregion Events #region Class Members -- cgit v1.1 From c31d93cb6f478062332c6a04fd1c357bb11205ee Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 1 May 2014 22:24:21 +0100 Subject: Fix issue where only one of multiple attachments on the same attachpoint for NPCs would be seen by other viewers. It appears that at least Singularity 1.8.5 (but probably others) rely on attachment FromItemIDs being different to display more than one. This commit resolves this by generating random IDs instead of always using UUID.Zero for NPCs. Resolves http://opensimulator.org/mantis/view.php?id=7110 --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3ab837d..7cb5b53 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5304,10 +5304,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP //update.JointType = 0; update.Material = data.Material; update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim + if (data.ParentGroup.IsAttachment) { - update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); + update.NameValue + = Util.StringToBytes256( + string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID)); + update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); + +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}", +// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name); +// +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", +// update.State, data.Name, data.LocalId, Name); } else { @@ -5318,10 +5330,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.State = data.ParentGroup.RootPart.Shape.State; } -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", -// update.State, data.Name, data.LocalId, Name); - update.ObjectData = objectData; update.ParentID = data.ParentID; update.PathBegin = data.Shape.PathBegin; -- cgit v1.1 From 0fe08c8799b1a3a2d5a07c206c2f9680d1c0798e Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 4 May 2014 13:36:36 +0300 Subject: - When sending the "My Suitcase" folder to the client, always claim it has Folder Type 8. (Previously we had used Folder Type -1 in one place, and LLClientView didn't even bother changing Folder Type 100 to anything else.) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7cb5b53..53217a0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1761,6 +1761,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP newBlock.Name = Util.StringToBytes256(folder.Name); newBlock.ParentID = folder.ParentID; newBlock.Type = (sbyte)folder.Type; + if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; return newBlock; } @@ -2010,8 +2012,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; - //folderBlock.Type = -1; folderBlock.Type = (sbyte)folder.Type; + if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; -- cgit v1.1 From 667a272cce75dbfd39c30bff9a5d9999bbacb460 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 9 May 2014 11:06:03 -0700 Subject: This little sucker had evaded my attention forever. As a consequence some assets associated with foreign users were being missed. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 38 ++++++++++++++++------ 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 53217a0..c28e58d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8949,7 +8949,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) { string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); + if (!string.IsNullOrEmpty(assetServer)) + return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); } return null; @@ -12658,16 +12659,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (asset == null) { - req.AssetInf = null; - req.AssetRequestSource = source; - req.IsTextureRequest = false; - req.NumPackets = 0; - req.Params = transferRequest.TransferInfo.Params; - req.RequestAssetID = requestID; - req.TransferRequestID = transferRequest.TransferInfo.TransferID; + // Try the user's asset server + IInventoryAccessModule inventoryAccessModule = Scene.RequestModuleInterface(); + + string assetServerURL = string.Empty; + if (inventoryAccessModule.IsForeignUser(AgentId, out assetServerURL) && !string.IsNullOrEmpty(assetServerURL)) + { + if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("=")) + assetServerURL = assetServerURL + "/"; + + //m_log.DebugFormat("[LLCLIENTVIEW]: asset {0} not found in local storage. Trying user's storage.", assetServerURL + id); + asset = m_scene.AssetService.Get(assetServerURL + id); + } + + if (asset == null) + { + req.AssetInf = null; + req.AssetRequestSource = source; + req.IsTextureRequest = false; + req.NumPackets = 0; + req.Params = transferRequest.TransferInfo.Params; + req.RequestAssetID = requestID; + req.TransferRequestID = transferRequest.TransferInfo.TransferID; + + SendAssetNotFound(req); + return; + } - SendAssetNotFound(req); - return; } if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) -- cgit v1.1 From 0aa0dad47868d6f64fa19f81b0f5daf35196fc3b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 1 Jun 2014 19:22:26 -0700 Subject: Send multiple terrain patches per terrain update packet if terrain draw distance optimization is enabled. Makes terrain editting a lot snappier. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 124 +++++++++++++++++---- 1 file changed, 100 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c28e58d..44386c9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1154,6 +1154,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Send the region heightmap to the client + /// This method is only called when not doing intellegent terrain patch sending and + /// is only called when the scene presence is initially created and sends all of the + /// region's patches to the client. /// /// heightmap public virtual void SendLayerData(float[] map) @@ -1237,9 +1240,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Legacy form of invocation that passes around a bare data array. // Just ignore what was passed and use the real terrain info that is part of the scene. + // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, + // there is a special form for specifying multiple terrain patches to send. + // The form is to pass 'px' as negative the number of patches to send and to + // pass the float array as pairs of patch X and Y coordinates. So, passing 'px' + // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches + // and the patches to send are <3,5> and <8,4>. public void SendLayerData(int px, int py, float[] map) { - SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); + if (px >= 0) + { + SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); + } + else + { + int numPatches = -px; + int[] xPatches = new int[numPatches]; + int[] yPatches = new int[numPatches]; + for (int pp = 0; pp < numPatches; pp++) + { + xPatches[pp] = (int)map[pp * 2]; + yPatches[pp] = (int)map[pp * 2 + 1]; + } + + // DebugSendingPatches("SendLayerData", xPatches, yPatches); + + SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData()); + } + } + + private void DebugSendingPatches(string pWho, int[] pX, int[] pY) + { + if (m_log.IsDebugEnabled) + { + int numPatches = pX.Length; + string Xs = ""; + string Ys = ""; + for (int pp = 0; pp < numPatches; pp++) + { + Xs += String.Format("{0}", (int)pX[pp]) + ","; + Ys += String.Format("{0}", (int)pY[pp]) + ","; + } + m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys); + } } /// @@ -1252,6 +1295,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// heightmap public void SendLayerData(int px, int py, TerrainData terrData) { + int[] xPatches = new[] { px }; + int[] yPatches = new[] { py }; + SendLayerData(xPatches, yPatches, terrData); + } + + private void SendLayerData(int[] px, int[] py, TerrainData terrData) + { try { /* test code using the terrain compressor in libOpenMetaverse @@ -1259,31 +1309,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP patchInd[0] = px + (py * Constants.TerrainPatchSize); LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); */ - LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py); - - // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. - // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. - // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area - // invalidating previous packets for that area. - - // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a - // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower. - - // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will - // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain - // patches. + // Many, many patches could have been passed to us. Since the patches will be compressed + // into variable sized blocks, we cannot pre-compute how many will fit into one + // packet. While some fancy packing algorithm is possible, 4 seems to always fit. + int PatchesAssumedToFit = 4; + for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit) + { + int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit); + int[] xPatches = new int[remaining]; + int[] yPatches = new int[remaining]; + for (int ii = 0; ii < remaining; ii++) + { + xPatches[ii] = px[pcnt + ii]; + yPatches[ii] = py[pcnt + ii]; + } + LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches); + // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches); - // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss. - if (m_justEditedTerrain) - { - layerpack.Header.Reliable = false; - OutPacket(layerpack, ThrottleOutPacketType.Unknown ); - } - else - { - layerpack.Header.Reliable = true; - OutPacket(layerpack, ThrottleOutPacketType.Land); + SendTheLayerPacket(layerpack); } + // LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py); + } catch (Exception e) { @@ -1291,6 +1337,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + // When a user edits the terrain, so much data is sent, the data queues up fast and presents a + // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we + // start skipping the queues until they're done editing the terrain. We also make them + // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch + // area invalidating previous packets for that area. + + // It's possible for an editing user to flood themselves with edited packets but the majority + // of use cases are such that only a tiny percentage of users will be editing the terrain. + // Other, non-editing users will see the edits much slower. + + // One last note on this topic, by the time users are going to be editing the terrain, it's + // extremely likely that the sim will have rezzed already and therefore this is not likely going + // to cause any additional issues with lost packets, objects or terrain patches. + + // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we + // only have one cache miss. + private void SendTheLayerPacket(LayerDataPacket layerpack) + { + if (m_justEditedTerrain) + { + layerpack.Header.Reliable = false; + OutPacket(layerpack, ThrottleOutPacketType.Unknown ); + } + else + { + layerpack.Header.Reliable = true; + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + } + /// /// Send the wind matrix to the client /// -- cgit v1.1 From ca2379ee8388d9c04fbd3c6eae49b7407bde5b95 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 21 Jun 2014 15:38:38 -0700 Subject: Bug fix in map teleports in varregions. The cherry was missing from the ice-cream Sunday: the packet itself was hardcoding the size of the region... --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 44386c9..bd0f5ca 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1543,10 +1543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP mapReply.Data[i].Access = mapBlocks2[i].Access; mapReply.Data[i].Agents = mapBlocks2[i].Agents; - // TODO: hookup varregion sim size here mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock(); - mapReply.Size[i].SizeX = 256; - mapReply.Size[i].SizeY = 256; + mapReply.Size[i].SizeX = mapBlocks2[i].SizeX; + mapReply.Size[i].SizeY = mapBlocks2[i].SizeY; } OutPacket(mapReply, ThrottleOutPacketType.Land); } -- cgit v1.1 From 2d034e20c4f0fd7508cdd8780435f362cfc17890 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 14 Jul 2014 10:55:57 +0300 Subject: XBakes: store the assets only in the sim's local assets cache; not in the main assets server. Also, some cleanup. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 126 ++++++--------------- 1 file changed, 37 insertions(+), 89 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bd0f5ca..bfdb24f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11848,7 +11848,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) { - //m_log.Debug("texture cached: " + packet.ToString()); AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); @@ -11864,24 +11863,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - //IAvatarFactoryModule fac = m_scene.RequestModuleInterface(); - // var item = fac.GetBakedTextureFaces(AgentId); - //WearableCacheItem[] items = fac.GetCachedItems(AgentId); - - IAssetService cache = m_scene.AssetService; - IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); - //bakedTextureModule = null; int maxWearablesLoop = cachedtex.WearableData.Length; if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) maxWearablesLoop = AvatarWearable.MAX_WEARABLES; + // Find the cached baked textures for this user, if they're available + + IAssetService cache = m_scene.AssetService; + IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); + + WearableCacheItem[] cacheItems = null; + if (bakedTextureModule != null && cache != null) { - // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid - - WearableCacheItem[] cacheItems = null; ScenePresence p = m_scene.GetScenePresence(AgentId); if (p.Appearance != null) + { if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty) { try @@ -11890,22 +11887,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP p.Appearance.WearableCacheItems = cacheItems; p.Appearance.WearableCacheItemsDirty = false; } - - /* - * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception! - * - catch (System.Net.Sockets.SocketException) - { - cacheItems = null; - } - catch (WebException) - { - cacheItems = null; - } - catch (InvalidOperationException) - { - cacheItems = null; - } */ catch (Exception) { cacheItems = null; @@ -11916,87 +11897,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP { cacheItems = p.Appearance.WearableCacheItems; } + } + } - if (cache != null && cacheItems != null) + if (cacheItems != null) + { + // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid. + // Copy the baked textures to the sim's assets cache (local only). + foreach (WearableCacheItem item in cacheItems) { - foreach (WearableCacheItem item in cacheItems) + if (cache.GetCached(item.TextureID.ToString()) == null) { - - if (cache.GetCached(item.TextureID.ToString()) == null) - { - item.TextureAsset.Temporary = true; - cache.Store(item.TextureAsset); - } - - + item.TextureAsset.Temporary = true; + item.TextureAsset.Local = true; + cache.Store(item.TextureAsset); } } - if (cacheItems != null) + + // Return the cached textures + for (int i = 0; i < maxWearablesLoop; i++) { + WearableCacheItem item = + WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems); - for (int i = 0; i < maxWearablesLoop; i++) + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].HostName = new byte[0]; + if (item != null && cachedtex.WearableData[i].ID == item.CacheId) { - WearableCacheItem item = - WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems); - - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].HostName = new byte[0]; - if (item != null && cachedtex.WearableData[i].ID == item.CacheId) - { - - cachedresp.WearableData[i].TextureID = item.TextureID; - } - else - { - cachedresp.WearableData[i].TextureID = UUID.Zero; - } + cachedresp.WearableData[i].TextureID = item.TextureID; } - } - else - { - for (int i = 0; i < maxWearablesLoop; i++) + else { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; } } } else { - if (cache == null) + // Cached textures not available + for (int i = 0; i < maxWearablesLoop; i++) { - for (int i = 0; i < maxWearablesLoop; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; - } - } - else - { - for (int i = 0; i < maxWearablesLoop; i++) - { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - - - - if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null) - cachedresp.WearableData[i].TextureID = UUID.Zero; - //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - else - cachedresp.WearableData[i].TextureID = UUID.Zero; - // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; - } + 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]; } } + cachedresp.Header.Zerocoded = true; OutPacket(cachedresp, ThrottleOutPacketType.Task); -- cgit v1.1 From b375f86f114d11b92a0b7b0c67e39a1bac243c2c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 18 Aug 2014 22:51:36 +0100 Subject: Make LLUDPServer.Scene publicly gettable/privately settable instead of protected so that other logging code in the clientstack can record more useful information Adds some commented out logging for use again in the future. No functional change. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bfdb24f..9d6085d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4201,6 +4201,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", +// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); +// #endregion Packet Sending } -- cgit v1.1 From 298376d5c7a8207f3c42f950cf9c212950038477 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Aug 2014 18:34:17 +0100 Subject: Add "debug lludp drop out " console command for debug/test purposes. This drops all outbound packets that match a given packet name. Can currently only be applied to all connections in a scene. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9d6085d..15a90af 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12341,6 +12341,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// provide your own method. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) { + if (m_outPacketsToDrop != null) + if (m_outPacketsToDrop.Contains(packet.Type.ToString())) + return; + if (DebugPacketLevel > 0) { bool logPacket = true; @@ -13123,5 +13127,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP eq.Enqueue(BuildEvent("BulkUpdateInventory", llsd), AgentId); } + + private HashSet m_outPacketsToDrop; + + public bool AddOutPacketToDropSet(string packetName) + { + if (m_outPacketsToDrop == null) + m_outPacketsToDrop = new HashSet(); + + return m_outPacketsToDrop.Add(packetName); + } + + public bool RemoveOutPacketFromDropSet(string packetName) + { + if (m_outPacketsToDrop == null) + return false; + + return m_outPacketsToDrop.Remove(packetName); + } + + public HashSet GetOutPacketDropSet() + { + return new HashSet(m_outPacketsToDrop); + } } } -- cgit v1.1 From 4e03d352c356ca9ebe22a1ac623dc85f4b7922e8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 19 Aug 2014 18:43:21 +0100 Subject: Extend drop command to "debug lludp drop ..." to allow drop of inbound packets. For test/debug purposes. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 15a90af..c839c05 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12403,6 +12403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// OpenMetaverse.packet public void ProcessInPacket(Packet packet) { + if (m_inPacketsToDrop != null) + if (m_inPacketsToDrop.Contains(packet.Type.ToString())) + return; + if (DebugPacketLevel > 0) { bool logPacket = true; @@ -13150,5 +13154,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP { return new HashSet(m_outPacketsToDrop); } + + private HashSet m_inPacketsToDrop; + + public bool AddInPacketToDropSet(string packetName) + { + if (m_inPacketsToDrop == null) + m_inPacketsToDrop = new HashSet(); + + return m_inPacketsToDrop.Add(packetName); + } + + public bool RemoveInPacketFromDropSet(string packetName) + { + if (m_inPacketsToDrop == null) + return false; + + return m_inPacketsToDrop.Remove(packetName); + } + + public HashSet GetInPacketDropSet() + { + return new HashSet(m_inPacketsToDrop); + } } } -- cgit v1.1 From e6af551007b20acda5ec32c3a15a08d0c393a454 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 21 Oct 2014 18:27:09 +0100 Subject: For now, send all non-full terse updates for ones own avatar directly to the LLUDP client stack rather than queueing internally within LLClientView. When an HG avatar enters a scene, it delays processing of entity updates. Could be crowding out by other updates or something else. This delay in ones own av mvmt updates results in mvmt lag experienced on the client. Avoiding the internal LLClientView for these packets appears to resolve this issue. Appears most noticeably for avatars with attachments, though has also been seen on those without sometimes. Hasn't been observed for non-HG avatars in general. Will be investigating exactly what the problem is, at which point there will be a more permanent solution. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c839c05..c8c00c8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3834,11 +3834,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) { - //double priority = m_prioritizer.GetUpdatePriority(this, entity); - uint priority = m_prioritizer.GetUpdatePriority(this, entity); + if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) + { + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - lock (m_entityUpdates.SyncRoot) - m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = Utils.FloatToUInt16(1, 0.0f, 1.0f); + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false); + OutPacket(packet, ThrottleOutPacketType.Unknown, true); + } + else + { + //double priority = m_prioritizer.GetUpdatePriority(this, entity); + uint priority = m_prioritizer.GetUpdatePriority(this, entity); + + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); + } } /// -- cgit v1.1 From ec8d21c434a39f46518ee9cf9f5539d1790eacc0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 4 Nov 2014 00:55:48 +0000 Subject: Label all threadpool calls being made in core OpenSimulator. This is to add problem diagnosis. "show threadpool calls" now also returns named (labelled), anonymous (unlabelled) and total call stats. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c8c00c8..516327c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1161,7 +1161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// heightmap public virtual void SendLayerData(float[] map) { - Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData()); + Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData"); } /// @@ -1373,7 +1373,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// 16x16 array of wind speeds public virtual void SendWindData(Vector2[] windSpeeds) { - Util.FireAndForget(DoSendWindData, windSpeeds); + Util.FireAndForget(DoSendWindData, windSpeeds, "LLClientView.SendWindData"); } /// @@ -1382,7 +1382,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// 16x16 array of cloud densities public virtual void SendCloudData(float[] cloudDensity) { - Util.FireAndForget(DoSendCloudData, cloudDensity); + Util.FireAndForget(DoSendCloudData, cloudDensity, "LLClientView.SendCloudData"); } /// @@ -8093,7 +8093,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // This requests the asset if needed HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer); - }); + }, null, "LLClientView.HandleTransferRequest"); + return true; } } -- cgit v1.1 From d6c9705a3b9d4c9bbe0e23f6d8d3793c07bf53ea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 5 Nov 2014 19:02:26 +0000 Subject: Add incoming packet async handling engine to queue some inbound udp async requests. This is to reduce the potential for overload of the threadpool if there are many simultaneous requets in high concurrency situations. Currently only applied to AvatarProperties and GenericMessage requests. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 67 ++++++++++++++++++---- 1 file changed, 56 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 516327c..85f9d68 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -648,12 +648,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// true if the handler was added. This is currently always the case. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) { + return AddLocalPacketHandler(packetType, handler, doAsync, false); + } + + /// + /// Add a handler for the given packet type. + /// + /// + /// + /// + /// If true, when the packet is received handle it on a different thread. Whether this is given direct to + /// a threadpool thread or placed in a queue depends on the inEngine parameter. + /// + /// + /// If async is false then this parameter is ignored. + /// If async is true and inEngine is false, then the packet is sent directly to a + /// threadpool thread. + /// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine. + /// This may result in slower handling but reduces the risk of overloading the simulator when there are many + /// simultaneous async requests. + /// + /// true if the handler was added. This is currently always the case. + public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine) + { bool result = false; lock (m_packetHandlers) { if (!m_packetHandlers.ContainsKey(packetType)) { - m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync }); + m_packetHandlers.Add( + packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine }); result = true; } } @@ -688,21 +712,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP PacketProcessor pprocessor; if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor)) { + ClientInfo cinfo = UDPClient.GetClientInfo(); + //there is a local handler for this packet type if (pprocessor.Async) { - ClientInfo cinfo = UDPClient.GetClientInfo(); if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) cinfo.AsyncRequests[packet.Type.ToString()] = 0; cinfo.AsyncRequests[packet.Type.ToString()]++; object obj = new AsyncPacketProcess(this, pprocessor.method, packet); - Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); + + if (pprocessor.InEngine) + m_udpServer.IpahEngine.QueueRequest( + packet.Type.ToString(), + ProcessSpecificPacketAsync, + obj); + else + Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); + result = true; } else { - ClientInfo cinfo = UDPClient.GetClientInfo(); if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) cinfo.SyncRequests[packet.Type.ToString()] = 0; cinfo.SyncRequests[packet.Type.ToString()]++; @@ -5554,10 +5586,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); - AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); - AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage, true, true); + AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest, true, true); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); - AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); + AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate, true, true); AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); @@ -5742,8 +5774,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); - AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate); - AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate); + AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate, true, true); + AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate, true, true); AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); @@ -12801,8 +12833,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP public struct PacketProcessor { - public PacketMethod method; - public bool Async; + /// + /// Packet handling method. + /// + public PacketMethod method { get; set; } + + /// + /// Should this packet be handled asynchronously? + /// + public bool Async { get; set; } + + /// + /// If async is true, should this packet be handled in the async engine or given directly to a threadpool + /// thread? + /// + public bool InEngine { get; set; } } public class AsyncPacketProcess -- cgit v1.1 From 265fe349e00b3ece59ec02e56f83bb7623e9d962 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 29 Nov 2014 00:12:11 +0000 Subject: Somewhat improve avatar region crossings by properly preserving velocity when avatar enters the new region. This commit addresses the following issues were causing velocity to be set to 0 on the new region, disrupting flight in particular * Full avatar updates contained no velocity information, which does appear to have some effect in testing. * BulletSim was always setting the velocity to 0 for the new BSCharacter. Now, physics engines take a velocity parameter when setting up characters so we can avoid this. This patch applies to both Bullet and ODE. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 85f9d68..5da0ca1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5195,8 +5195,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { ScenePresence presence = (ScenePresence)entity; -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}", +// Name, presence.OffsetPosition, presence.Velocity, m_scene.Name); attachPoint = presence.State; collisionPlane = presence.CollisionPlane; @@ -5333,13 +5334,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) { // m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name); +// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); byte[] objectData = new byte[76]; data.CollisionPlane.ToBytes(objectData, 0); data.OffsetPosition.ToBytes(objectData, 16); -// data.Velocity.ToBytes(objectData, 28); + data.Velocity.ToBytes(objectData, 28); // data.Acceleration.ToBytes(objectData, 40); // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis -- cgit v1.1 From 8e1e8a0920a9e94305619e9afb8e053b4daefb89 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Jan 2015 20:56:37 +0000 Subject: Make the performance controlling job processing threads introduced in conference code use a generic JobEngine class rather than 4 slightly different copy/pasted versions. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5da0ca1..bb4f8a7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -724,10 +724,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP object obj = new AsyncPacketProcess(this, pprocessor.method, packet); if (pprocessor.InEngine) - m_udpServer.IpahEngine.QueueRequest( - packet.Type.ToString(), - ProcessSpecificPacketAsync, - obj); + m_udpServer.IpahEngine.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj)); else Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); -- cgit v1.1 From 7a86b01226199ec061f5723c79d190f729fc9a31 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Feb 2015 23:09:43 +0000 Subject: Make any exception that gets to LLClientView.ProcessSpecificPacketAsync() tells us the exception type as well as the message and stacktrace details. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bb4f8a7..ee0f790 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -772,9 +772,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP catch (Exception e) { // Make sure that we see any exception caused by the asynchronous operation. - m_log.ErrorFormat( - "[LLCLIENTVIEW]: Caught exception while processing {0} for {1}, {2} {3}", - packetObject.Pack, Name, e.Message, e.StackTrace); + m_log.Error( + string.Format( + "[LLCLIENTVIEW]: Caught exception while processing {0} for {1} ", packetObject.Pack, Name), + e); } } -- cgit v1.1 From cfa4e6642eabe8b277052c8295127d1bf4e97c7f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 1 Mar 2015 20:48:51 -0500 Subject: Handle kick user from estate management tools --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ee0f790..311dd31 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9904,6 +9904,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP } return true; + case "kickestate": + + if(((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UUID Prey; + + UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); + + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + } + return true; + default: m_log.WarnFormat( "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", -- cgit v1.1 From cde4e7ec865b1e6c933fad0f6b14e6df55123f0c Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Sat, 25 Apr 2015 05:39:20 +0100 Subject: Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL. Recent viewer changes by linden lab now require more information when requesting prim tooltip data. The object properties must now be sent when the viewer requests the object family properties used to display the tool tip. Thanks to Liru for finding the viewer commit that broke this feature in OS. Signed-off-by: BlueWall --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 311dd31..855342f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From d80230adcdd26a7f512355df256cc5c9c5e3d0e6 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Mon, 27 Apr 2015 15:46:09 -0500 Subject: Revert "Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL." See: http://opensimulator.org/mantis/view.php?id=7426#c28089 Reverting this commit due to unwanted effects. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 855342f..311dd31 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From 38459104eb7d3484d17bc764c500fb9f4026c49a Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 28 Apr 2015 09:36:56 -0500 Subject: Revert "Revert "Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL."" This brings back the fix for recent viewer click to buy prim dialog which was reverted after some reports of objects being altered when touched. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 311dd31..855342f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From 6a48c87cd20e9df5ebdd2898872618455106be4c Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 13 May 2015 15:59:58 -0700 Subject: resolve possible nullref when sending appearance packet. Thanks to zadark for pointing this out. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 855342f..284c5fa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3747,6 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; + avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } -- cgit v1.1 From 959872315f67a1a33a2bae7330749f7dd74a4774 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 8 Aug 2015 12:12:50 -0700 Subject: WARNING: massive refactor to follow libomv's latest changes regarding inventory folders. The newest version of libomv itself is committed here. Basically, everything that was using the AssetType enum has been combed through; many of those uses were changed to the new FolderType enum. This means that from now on, [new] root folders have code 8 (FolderType.Root), as the viewers expect, as opposed to 9, which was what we had been doing. Normal folders are as they were, -1. Also now sending folder code 100 for Suitcase folders to viewers, with no filter. All tests pass, but fingers crossed! --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 284c5fa..c8e5881 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1866,8 +1866,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP newBlock.Name = Util.StringToBytes256(folder.Name); newBlock.ParentID = folder.ParentID; newBlock.Type = (sbyte)folder.Type; - if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) - newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; + //if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + // newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; return newBlock; } @@ -2118,8 +2118,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; folderBlock.Type = (sbyte)folder.Type; - if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) - folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; + // Leaving this here for now, just in case we need to do this for a while + //if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + // folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; -- cgit v1.1 From d70db51466bc2576181ac82a0de8271cd42db210 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Fri, 14 Aug 2015 18:13:41 -0400 Subject: Only send the requested ObjectPropertiesFamily in the RequestObjectPropertiesFamily reply and not the actual ObjectProperties packet Signed-off-by: Diva Canto --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c8e5881..e7dd9d3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4467,7 +4467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1