From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../Framework/Scenes/Scene.PacketHandlers.cs | 291 ++++++++++++++------- 1 file changed, 200 insertions(+), 91 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 8ebcd92..84bad25 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, + public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, UUID targetID, bool fromAgent, bool broadcast) { OSChatMessage args = new OSChatMessage(); @@ -60,6 +60,7 @@ namespace OpenSim.Region.Framework.Scenes args.Position = fromPos; args.SenderUUID = fromID; args.Scene = this; + args.Destination = targetID; if (fromAgent) { @@ -74,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes } args.From = fromName; - args.TargetUUID = targetID; + //args. // m_log.DebugFormat( // "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", @@ -129,19 +130,6 @@ namespace OpenSim.Region.Framework.Scenes { SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true); } - /// - /// - /// - /// - /// - /// - /// - /// - /// - public void SimChatToAgent(UUID targetID, byte[] message, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent) - { - SimChat(message, ChatTypeEnum.Say, 0, fromPos, fromName, fromID, targetID, fromAgent, false); - } /// /// @@ -176,29 +164,34 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void SelectPrim(uint primLocalID, IClientAPI remoteClient) + public void SelectPrim(List primIDs, IClientAPI remoteClient) { - SceneObjectPart part = GetSceneObjectPart(primLocalID); + foreach(uint primLocalID in primIDs) + { + SceneObjectPart part = GetSceneObjectPart(primLocalID); - if (null == part) - return; + if (part == null) + continue; - if (part.IsRoot) - { SceneObjectGroup sog = part.ParentGroup; - sog.SendPropertiesToClient(remoteClient); - sog.IsSelected = true; + if (sog == null) + continue; + + // waste of time because properties do not send prim flags as they should + // if a friend got or lost edit rights after login, a full update is needed + if(sog.OwnerID != remoteClient.AgentId) + part.SendFullUpdate(remoteClient); // A prim is only tainted if it's allowed to be edited by the person clicking it. - if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) - || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) + if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent)) { - EventManager.TriggerParcelPrimCountTainted(); + bool oldsel = part.IsSelected; + part.IsSelected = true; + if(!oldsel) + EventManager.TriggerParcelPrimCountTainted(); } - } - else - { - part.SendPropertiesToClient(remoteClient); + + part.SendPropertiesToClient(remoteClient); } } @@ -220,13 +213,13 @@ namespace OpenSim.Region.Framework.Scenes if (groupID != UUID.Zero) { GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, remoteClient.AgentId); - + if (gmd == null) { // m_log.WarnFormat( // "[GROUPS]: User {0} is not a member of group {1} so they can't update {2} to this group", // remoteClient.Name, GroupID, objectLocalID); - + return; } } @@ -237,6 +230,7 @@ namespace OpenSim.Region.Framework.Scenes if (so.OwnerID == remoteClient.AgentId) { so.SetGroup(groupID, remoteClient); + EventManager.TriggerParcelPrimCountTainted(); } } } @@ -251,40 +245,29 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetSceneObjectPart(primLocalID); if (part == null) return; - - // A deselect packet contains all the local prims being deselected. However, since selection is still - // group based we only want the root prim to trigger a full update - otherwise on objects with many prims - // we end up sending many duplicate ObjectUpdates - if (part.ParentGroup.RootPart.LocalId != part.LocalId) - return; + + bool oldgprSelect = part.ParentGroup.IsSelected; // This is wrong, wrong, wrong. Selection should not be // handled by group, but by prim. Legacy cruft. // TODO: Make selection flagging per prim! // - part.ParentGroup.IsSelected = false; - - part.ParentGroup.ScheduleGroupForFullUpdate(); - - // If it's not an attachment, and we are allowed to move it, - // then we might have done so. If we moved across a parcel - // boundary, we will need to recount prims on the parcels. - // For attachments, that makes no sense. - // - if (!part.ParentGroup.IsAttachment) + if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent)) { - if (Permissions.CanEditObject( - part.UUID, remoteClient.AgentId) - || Permissions.CanMoveObject( - part.UUID, remoteClient.AgentId)) + part.IsSelected = false; + if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected) EventManager.TriggerParcelPrimCountTainted(); + + // restore targetOmega + if (part.AngularVelocity != Vector3.Zero) + part.ScheduleTerseUpdate(); } } - public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, + public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, int transactiontype, string description) { - EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs(source, destination, amount, + EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs(source, destination, amount, transactiontype, description); EventManager.TriggerMoneyTransfer(this, args); @@ -293,8 +276,8 @@ namespace OpenSim.Region.Framework.Scenes public virtual void ProcessParcelBuy(UUID agentId, UUID groupId, bool final, bool groupOwned, bool removeContribution, int parcelLocalID, int parcelArea, int parcelPrice, bool authenticated) { - EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned, - removeContribution, parcelLocalID, parcelArea, + EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned, + removeContribution, parcelLocalID, parcelArea, parcelPrice, authenticated); // First, allow all validators a stab at it @@ -307,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient, List surfaceArgs) { SceneObjectPart part = GetSceneObjectPart(localID); - + if (part == null) return; @@ -320,19 +303,17 @@ namespace OpenSim.Region.Framework.Scenes // Currently only grab/touch for the single prim // the client handles rez correctly obj.ObjectGrabHandler(localID, offsetPos, remoteClient); - + // If the touched prim handles touches, deliver it - // If not, deliver to root prim if ((part.ScriptEvents & scriptEvents.touch_start) != 0) - EventManager.TriggerObjectGrab(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg); + EventManager.TriggerObjectGrab(part.LocalId, 0, offsetPos, remoteClient, surfaceArg); // Deliver to the root prim if the touched prim doesn't handle touches - // or if we're meant to pass on touches anyway. Don't send to root prim - // if prim touched is the root prim as we just did it + // or if we're meant to pass on touches anyway. if (((part.ScriptEvents & scriptEvents.touch_start) == 0) || - (part.PassTouches && (part.LocalId != obj.RootPart.LocalId))) + (part.PassTouches && (part.LocalId != obj.RootPart.LocalId))) { - EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg); + EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, offsetPos, remoteClient, surfaceArg); } } @@ -343,23 +324,37 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) return; - SceneObjectGroup obj = part.ParentGroup; + SceneObjectGroup group = part.ParentGroup; + if(group == null || group.IsDeleted) + return; + + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) + { + group.GrabMovement(objectID, offset, pos, remoteClient); + } + + // This is outside the above permissions condition + // so that if the object is locked the client moving the object + // get's it's position on the simulator even if it was the same as before + // This keeps the moving user's client in sync with the rest of the world. + group.SendGroupTerseUpdate(); SurfaceTouchEventArgs surfaceArg = null; if (surfaceArgs != null && surfaceArgs.Count > 0) surfaceArg = surfaceArgs[0]; + Vector3 grabOffset = pos - part.AbsolutePosition; // If the touched prim handles touches, deliver it - // If not, deliver to root prim if ((part.ScriptEvents & scriptEvents.touch) != 0) - EventManager.TriggerObjectGrabbing(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg); +// EventManager.TriggerObjectGrabbing(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg); + EventManager.TriggerObjectGrabbing(part.LocalId, 0, grabOffset, remoteClient, surfaceArg); // Deliver to the root prim if the touched prim doesn't handle touches - // or if we're meant to pass on touches anyway. Don't send to root prim - // if prim touched is the root prim as we just did it + // or if we're meant to pass on touches anyway. if (((part.ScriptEvents & scriptEvents.touch) == 0) || - (part.PassTouches && (part.LocalId != obj.RootPart.LocalId))) + (part.PassTouches && (part.LocalId != group.RootPart.LocalId))) { - EventManager.TriggerObjectGrabbing(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg); +// EventManager.TriggerObjectGrabbing(group.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg); + EventManager.TriggerObjectGrabbing(group.RootPart.LocalId, part.LocalId, grabOffset, remoteClient, surfaceArg); } } @@ -369,18 +364,77 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) return; - SceneObjectGroup obj = part.ParentGroup; + SceneObjectGroup grp = part.ParentGroup; SurfaceTouchEventArgs surfaceArg = null; if (surfaceArgs != null && surfaceArgs.Count > 0) surfaceArg = surfaceArgs[0]; // If the touched prim handles touches, deliver it - // If not, deliver to root prim if ((part.ScriptEvents & scriptEvents.touch_end) != 0) EventManager.TriggerObjectDeGrab(part.LocalId, 0, remoteClient, surfaceArg); - else - EventManager.TriggerObjectDeGrab(obj.RootPart.LocalId, part.LocalId, remoteClient, surfaceArg); + // if not or PassTouchs, send it also to root. + if (((part.ScriptEvents & scriptEvents.touch_end) == 0) || + (part.PassTouches && (part.LocalId != grp.RootPart.LocalId))) + { + EventManager.TriggerObjectDeGrab(grp.RootPart.LocalId, part.LocalId, remoteClient, surfaceArg); + } + } + + /// + /// Start spinning the given object + /// + /// + /// + /// + public virtual void ProcessSpinStart(UUID objectID, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(objectID); + if (group != null) + { + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) + { + group.SpinStart(remoteClient); + } + } + } + + /// + /// Spin the given object + /// + /// + /// + /// + public virtual void ProcessSpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(objectID); + if (group != null) + { + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) + { + group.SpinMovement(rotation, remoteClient); + } + // This is outside the above permissions condition + // so that if the object is locked the client moving the object + // get's it's position on the simulator even if it was the same as before + // This keeps the moving user's client in sync with the rest of the world. + group.SendGroupTerseUpdate(); + } + } + + public virtual void ProcessSpinObjectStop(UUID objectID, IClientAPI remoteClient) + { +/* no op for now + SceneObjectGroup group = GetGroupByPrim(objectID); + if (group != null) + { + if (Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) + { +// group.SpinMovement(rotation, remoteClient); + } + group.SendGroupTerseUpdate(); + } +*/ } public void ProcessScriptReset(IClientAPI remoteClient, UUID objectID, @@ -439,6 +493,20 @@ namespace OpenSim.Region.Framework.Scenes return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; } + private class DescendentsRequestData + { + public IClientAPI RemoteClient; + public UUID FolderID; + public UUID OwnerID; + public bool FetchFolders; + public bool FetchItems; + public int SortOrder; + } + + private Queue m_descendentsRequestQueue = new Queue(); + private Object m_descendentsRequestLock = new Object(); + private bool m_descendentsRequestProcessing = false; + /// /// Tell the client about the various child items and folders contained in the requested folder. /// @@ -475,11 +543,31 @@ namespace OpenSim.Region.Framework.Scenes } } - // We're going to send the reply async, because there may be - // an enormous quantity of packets -- basically the entire inventory! - // We don't want to block the client thread while all that is happening. - SendInventoryDelegate d = SendInventoryAsync; - d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); + lock (m_descendentsRequestLock) + { + if (!m_descendentsRequestProcessing) + { + m_descendentsRequestProcessing = true; + + // We're going to send the reply async, because there may be + // an enormous quantity of packets -- basically the entire inventory! + // We don't want to block the client thread while all that is happening. + SendInventoryDelegate d = SendInventoryAsync; + d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); + + return; + } + + DescendentsRequestData req = new DescendentsRequestData(); + req.RemoteClient = remoteClient; + req.FolderID = folderID; + req.OwnerID = ownerID; + req.FetchFolders = fetchFolders; + req.FetchItems = fetchItems; + req.SortOrder = sortOrder; + + m_descendentsRequestQueue.Enqueue(req); + } } delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); @@ -494,16 +582,32 @@ namespace OpenSim.Region.Framework.Scenes { m_log.Error( string.Format( - "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e)); + "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e, folderID)); } + Thread.Sleep(20); } void SendInventoryComplete(IAsyncResult iar) { SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; d.EndInvoke(iar); + + lock (m_descendentsRequestLock) + { + if (m_descendentsRequestQueue.Count > 0) + { + DescendentsRequestData req = m_descendentsRequestQueue.Dequeue(); + + d = SendInventoryAsync; + d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d); + + return; + } + + m_descendentsRequestProcessing = false; + } } - + /// /// Handle an inventory folder creation request from the client. /// @@ -543,8 +647,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId); - InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); - folder = InventoryService.GetFolder(folder); + InventoryFolderBase folder = InventoryService.GetFolder(remoteClient.AgentId, folderID); if (folder != null) { folder.Name = name; @@ -558,11 +661,10 @@ namespace OpenSim.Region.Framework.Scenes } } } - + public void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID) { - InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); - folder = InventoryService.GetFolder(folder); + InventoryFolderBase folder = InventoryService.GetFolder(remoteClient.AgentId, folderID); if (folder != null) { folder.ParentID = parentID; @@ -601,10 +703,17 @@ namespace OpenSim.Region.Framework.Scenes { InventoryFolderBase folder = new InventoryFolderBase(folderID, userID); - if (InventoryService.PurgeFolder(folder)) - m_log.DebugFormat("[AGENT INVENTORY]: folder {0} purged successfully", folderID); - else - m_log.WarnFormat("[AGENT INVENTORY]: could not purge folder {0}", folderID); + try + { + if (InventoryService.PurgeFolder(folder)) + m_log.DebugFormat("[AGENT INVENTORY]: folder {0} purged successfully", folderID); + else + m_log.WarnFormat("[AGENT INVENTORY]: could not purge folder {0}", folderID); + } + catch (Exception e) + { + m_log.WarnFormat("[AGENT INVENTORY]: Exception on async purge folder for user {0}: {1}", userID, e.Message); + } } private void PurgeFolderCompleted(IAsyncResult iar) -- cgit v1.1