From efe3f3eb2a0a31b1da474974c7d8193c2b28e13f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 18 Oct 2008 05:51:36 +0000 Subject: Megapatch. :) Fix skull attachment editing. Streamline Object terse updates. Add rezzing time to objects. Add Object return and traffic fields to land database. Add plumbing for auto return. Implement auto return. Contains a migration. May contain nuts. --- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 17 +- OpenSim/Region/Environment/Scenes/ReturnInfo.cs | 38 ++++ .../Region/Environment/Scenes/Scene.Inventory.cs | 202 +++++++++++---------- OpenSim/Region/Environment/Scenes/Scene.cs | 49 +++++ .../Region/Environment/Scenes/SceneObjectGroup.cs | 72 ++++---- .../Region/Environment/Scenes/SceneObjectPart.cs | 118 +++++++----- OpenSim/Region/Environment/Scenes/ScenePresence.cs | 2 +- 7 files changed, 312 insertions(+), 186 deletions(-) create mode 100644 OpenSim/Region/Environment/Scenes/ReturnInfo.cs (limited to 'OpenSim/Region/Environment/Scenes') diff --git a/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs index 21fa71b..bd81a6d 100644 --- a/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Environment/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -38,8 +38,7 @@ namespace OpenSim.Region.Environment.Scenes { class DeleteToInventoryHolder { - public DeRezObjectPacket DeRezPacket; - public EntityBase selectedEnt; + public int destination; public IClientAPI remoteClient; public SceneObjectGroup objectGroup; public UUID folderID; @@ -70,20 +69,19 @@ namespace OpenSim.Region.Environment.Scenes /// /// Delete the given object from the scene /// - public void DeleteToInventory( - DeRezObjectPacket DeRezPacket, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient, - EntityBase selectedEnt, bool permissionToDelete) + public void DeleteToInventory(int destination, UUID folderID, + SceneObjectGroup objectGroup, IClientAPI remoteClient, + bool permissionToDelete) { m_inventoryTicker.Stop(); lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); - dtis.DeRezPacket = DeRezPacket; + dtis.destination = destination; dtis.folderID = folderID; dtis.objectGroup = objectGroup; dtis.remoteClient = remoteClient; - dtis.selectedEnt = selectedEnt; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); @@ -121,8 +119,9 @@ namespace OpenSim.Region.Environment.Scenes "[SCENE]: Sending deleted object to user's inventory, {0} item(s) remaining.", left); x = m_inventoryDeletes.Dequeue(); - m_scene.DeleteToInventory( - x.DeRezPacket, x.selectedEnt, x.remoteClient, x.objectGroup, x.folderID, x.permissionToDelete); + m_scene.DeleteToInventory(x.destination, + x.folderID, x.objectGroup, x.remoteClient, + x.permissionToDelete); return true; } diff --git a/OpenSim/Region/Environment/Scenes/ReturnInfo.cs b/OpenSim/Region/Environment/Scenes/ReturnInfo.cs new file mode 100644 index 0000000..68c563d --- /dev/null +++ b/OpenSim/Region/Environment/Scenes/ReturnInfo.cs @@ -0,0 +1,38 @@ +/* + * 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 OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; + +namespace OpenSim.Region.Environment.Scenes +{ + public struct ReturnInfo + { + public int count; + public Vector3 location; + public string objectName; + } +} diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 226f39a..b91eb83 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -1517,78 +1517,90 @@ namespace OpenSim.Region.Environment.Scenes /// /// /// - public virtual void DeRezObject(Packet packet, IClientAPI remoteClient) + public virtual void DeRezObject(IClientAPI remoteClient, uint localID, + UUID groupID, byte destination, UUID destinationID) { - DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) packet; + SceneObjectPart part = GetSceneObjectPart(localID); + if (part == null) + return; - UUID folderID = UUID.Zero; + if (part.ParentGroup == null || part.ParentGroup.RootPart == null) + return; - foreach (DeRezObjectPacket.ObjectDataBlock Data in DeRezPacket.ObjectData) - { -// m_log.DebugFormat( -// "[AGENT INVENTORY]: Received request to derez {0} into folder {1}", -// Data.ObjectLocalID, DeRezPacket.AgentBlock.DestinationID); + // Can't delete child prims + if (part != part.ParentGroup.RootPart) + return; + + SceneObjectGroup grp = part.ParentGroup; + + bool permissionToTake = false; + bool permissionToDelete = false; - EntityBase selectedEnt = null; - //m_log.Info("[CLIENT]: LocalID:" + Data.ObjectLocalID.ToString()); + if (destination == 1) // Take Copy + { + permissionToTake = + ExternalChecks.ExternalChecksCanTakeCopyObject( + grp.UUID, + remoteClient.AgentId); + } + else if (destination == 5) // God take copy + { + permissionToTake = + ExternalChecks.ExternalChecksCanBeGodLike( + remoteClient.AgentId); + } + else if (destination == 4) // Take + { + permissionToTake = + ExternalChecks.ExternalChecksCanTakeObject( + grp.UUID, + remoteClient.AgentId); - List EntityList = GetEntities(); + //If they can take, they can delete! + permissionToDelete = permissionToTake; + } - foreach (EntityBase ent in EntityList) + else if (destination == 6) //Delete + { + permissionToTake = + ExternalChecks.ExternalChecksCanDeleteObject( + grp.UUID, + remoteClient.AgentId); + permissionToDelete = + ExternalChecks.ExternalChecksCanDeleteObject( + grp.UUID, + remoteClient.AgentId); + } + else if (destination == 9) //Return + { + if (remoteClient != null) { - if (ent.LocalId == Data.ObjectLocalID) - { - selectedEnt = ent; - break; - } + permissionToTake = + ExternalChecks.ExternalChecksCanDeleteObject( + grp.UUID, + remoteClient.AgentId); + permissionToDelete = + ExternalChecks.ExternalChecksCanDeleteObject( + grp.UUID, + remoteClient.AgentId); } - if (selectedEnt != null) + else // Auto return passes through here with null agent { - bool permissionToTake = false; - bool permissionToDelete = false; - if (DeRezPacket.AgentBlock.Destination == 1)// Take Copy - { - permissionToTake = ExternalChecks.ExternalChecksCanTakeCopyObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - permissionToDelete = false; //Just taking copy! - - } - else if (DeRezPacket.AgentBlock.Destination == 5) //God take copy - { - permissionToTake = ExternalChecks.ExternalChecksCanBeGodLike(remoteClient.AgentId); - permissionToDelete = false; //Just taking copy! - - } - else if (DeRezPacket.AgentBlock.Destination == 4) //Take - { - // Take - permissionToTake = ExternalChecks.ExternalChecksCanTakeObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - permissionToDelete = permissionToTake; //If they can take, they can delete! - } - - else if (DeRezPacket.AgentBlock.Destination == 6) //Delete - { - permissionToTake = ExternalChecks.ExternalChecksCanDeleteObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - permissionToDelete = ExternalChecks.ExternalChecksCanDeleteObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - } - else if (DeRezPacket.AgentBlock.Destination == 9) //Return - { - permissionToTake = ExternalChecks.ExternalChecksCanDeleteObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - permissionToDelete = ExternalChecks.ExternalChecksCanDeleteObject(((SceneObjectGroup)selectedEnt).UUID, remoteClient.AgentId); - } - - SceneObjectGroup objectGroup = (SceneObjectGroup)selectedEnt; - - if (permissionToTake) - { - m_asyncSceneObjectDeleter.DeleteToInventory( - DeRezPacket, folderID, objectGroup, remoteClient, selectedEnt, permissionToDelete); - } - else if (permissionToDelete) - { - DeleteSceneObject(objectGroup); - } + permissionToTake = true; + permissionToDelete = true; } } + + if (permissionToTake) + { + m_asyncSceneObjectDeleter.DeleteToInventory( + destination, destinationID, grp, remoteClient, + permissionToDelete); + } + else if (permissionToDelete) + { + DeleteSceneObject(grp); + } } /// @@ -1600,51 +1612,50 @@ namespace OpenSim.Region.Environment.Scenes /// /// /// - public void DeleteToInventory(DeRezObjectPacket DeRezPacket, EntityBase selectedEnt, IClientAPI remoteClient, - SceneObjectGroup objectGroup, UUID folderID, bool permissionToDelete) + public void DeleteToInventory(int destination, UUID folderID, + SceneObjectGroup objectGroup, IClientAPI remoteClient, + bool permissionToDelete) { string sceneObjectXml = objectGroup.ToXmlString(); CachedUserInfo userInfo = - CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); - if (userInfo != null) - { -// string searchFolder = ""; + CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); -// if (DeRezPacket.AgentBlock.Destination == 6) -// searchFolder = "Trash"; -// else if (DeRezPacket.AgentBlock.Destination == 9) -// searchFolder = "Lost And Found"; + if (remoteClient == null) + { + userInfo = CommsManager.UserProfileCacheService.GetUserDetails( + objectGroup.RootPart.OwnerID); + } + else + { + userInfo = CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); + } - // If we're deleting someone else's item, it goes back to their deleted items folder - // If we're returning someone's item, it goes back to the owner's Lost And Found folder. + if (userInfo != null) + { + // If we're deleting someone else's item, it goes back to + // their deleted items folder + // If we're returning someone's item, it goes back to the + // owner's Lost And Found folder. - if (DeRezPacket.AgentBlock.DestinationID == UUID.Zero || (DeRezPacket.AgentBlock.Destination == 6 && objectGroup.OwnerID != remoteClient.AgentId)) + if (folderID == UUID.Zero || (destination == 6 && + objectGroup.OwnerID != remoteClient.AgentId)) { - List subrootfolders = userInfo.RootFolder.RequestListOfFolders(); - foreach (InventoryFolderBase flder in subrootfolders) - { - if (flder.Name == "Lost And Found") - { - folderID = flder.ID; - break; - } - } + InventoryFolderBase folder = + userInfo.FindFolderForType( + (int)AssetType.LostAndFoundFolder); - if (folderID == UUID.Zero) - { + if (folder != null) + folderID = folder.ID; + else folderID = userInfo.RootFolder.ID; - } - //currently following code not used (or don't know of any case of destination being zero - } - else - { - folderID = DeRezPacket.AgentBlock.DestinationID; } AssetBase asset = CreateAsset( - ((SceneObjectGroup) selectedEnt).GetPartName(selectedEnt.LocalId), - ((SceneObjectGroup) selectedEnt).GetPartDescription(selectedEnt.LocalId), + objectGroup.GetPartName(objectGroup.RootPart.LocalId), + objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(sceneObjectXml)); AssetCache.AddAsset(asset); @@ -1652,7 +1663,8 @@ namespace OpenSim.Region.Environment.Scenes InventoryItemBase item = new InventoryItemBase(); item.Creator = objectGroup.RootPart.CreatorID; - if (DeRezPacket.AgentBlock.Destination == 1 || DeRezPacket.AgentBlock.Destination == 4)// Take / Copy + if (destination == 1 || + destination == 4)// Take / Copy item.Owner = remoteClient.AgentId; else // Delete / Return item.Owner = objectGroup.OwnerID; @@ -1720,7 +1732,7 @@ namespace OpenSim.Region.Environment.Scenes { if (!grp.HasGroupChanged) { - m_log.InfoFormat("[ATTACHMENT] Detaching {0} which is unchanged", grp.UUID.ToString()); + m_log.InfoFormat("[ATTACHMENT] Save request for {0} which is unchanged", grp.UUID.ToString()); return; } m_log.InfoFormat("[ATTACHMENT] Updating asset for attachment {0}, attachpoint {1}", grp.UUID.ToString(), grp.GetAttachmentPoint()); diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 299d0da..139281d 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -96,6 +96,8 @@ namespace OpenSim.Region.Environment.Scenes private int m_incrementsof15seconds = 0; private volatile bool m_backingup = false; + private Dictionary m_returns = new Dictionary(); + protected string m_simulatorVersion = "OpenSimulator Server"; protected ModuleLoader m_moduleLoader; @@ -929,8 +931,54 @@ namespace OpenSim.Region.Environment.Scenes /// public void Backup() { + m_returns.Clear(); + EventManager.TriggerOnBackup(m_storageManager.DataStore); m_backingup = false; + + foreach (KeyValuePair ret in m_returns) + { + UUID transaction = UUID.Random(); + + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server + msg.fromAgentSession = new Guid(transaction.ToString()); + msg.toAgentID = new Guid(ret.Key.ToString()); + msg.imSessionID = new Guid(transaction.ToString()); + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "Server"; + msg.dialog = (byte)19; // Object msg + msg.fromGroup = false; + msg.offline = (byte)1; + msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; + msg.Position = Vector3.Zero; + msg.RegionID = RegionInfo.RegionID.Guid; + msg.binaryBucket = new byte[0]; + if (ret.Value.count > 1) + msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to parcel auto return", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName); + else + msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to parcel auto return", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName); + + TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + } + } + + public void AddReturn(UUID agentID, string objectName, Vector3 location) + { + if (m_returns.ContainsKey(agentID)) + { + ReturnInfo info = m_returns[agentID]; + info.count++; + m_returns[agentID] = info; + } + else + { + ReturnInfo info = new ReturnInfo(); + info.count = 1; + info.objectName = objectName; + info.location = location; + m_returns[agentID] = info; + } } #endregion @@ -2254,6 +2302,7 @@ namespace OpenSim.Region.Environment.Scenes client.OnUndo += m_innerScene.HandleUndo; client.OnObjectGroupRequest += m_innerScene.HandleObjectGroupUpdate; client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; + client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; client.OnObjectSaleInfo += ObjectSaleInfo; client.OnScriptReset += ProcessScriptReset; client.OnGetScriptRunning += GetScriptRunning; diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 8c5afab..60cf061 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -99,6 +99,8 @@ namespace OpenSim.Region.Environment.Scenes private Vector3 lastPhysGroupPos; private Quaternion lastPhysGroupRot; + private bool m_isBackedUp = false; + /// /// The constituent parts of this group /// @@ -120,7 +122,11 @@ namespace OpenSim.Region.Environment.Scenes /// public override string Name { - get { return RootPart.Name; } + get { + if (RootPart == null) + return ""; + return RootPart.Name; + } set { RootPart.Name = value; } } @@ -544,7 +550,9 @@ namespace OpenSim.Region.Environment.Scenes //m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); - m_scene.EventManager.OnBackup += ProcessBackup; + if (!m_isBackedUp) + m_scene.EventManager.OnBackup += ProcessBackup; + m_isBackedUp = true; } } @@ -786,6 +794,7 @@ namespace OpenSim.Region.Environment.Scenes SetAttachmentPoint((byte)0); m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim); HasGroupChanged = true; + RootPart.Rezzed = DateTime.Now; AttachToBackup(); m_scene.EventManager.TriggerParcelPrimCountTainted(); m_rootPart.ScheduleFullUpdate(); @@ -1000,6 +1009,8 @@ namespace OpenSim.Region.Environment.Scenes // that they don't happen, otherwise the deleted objects will reappear m_isDeleted = true; + DetachFromBackup(); + foreach (SceneObjectPart part in m_parts.Values) { List avatars = Scene.GetScenePresences(); @@ -1149,6 +1160,28 @@ namespace OpenSim.Region.Environment.Scenes // any exception propogate upwards. try { + ILandObject parcel = m_scene.LandChannel.GetLandObject( + m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); + + if (parcel.landData.OtherCleanTime != 0) + { + if (parcel.landData.OwnerID != OwnerID && + (parcel.landData.GroupID != GroupID || + parcel.landData.GroupID == UUID.Zero)) + { + if ((DateTime.Now - RootPart.Rezzed).TotalMinutes > + parcel.landData.OtherCleanTime) + { + m_log.InfoFormat("[SCENE] Returning object {0} due to parcel auto return", RootPart.UUID.ToString()); + m_scene.AddReturn(OwnerID, Name, AbsolutePosition); + m_scene.DeRezObject(null, RootPart.LocalId, + RootPart.GroupID, 9, UUID.Zero); + + return; + } + } + } + if (HasGroupChanged) { // don't backup while it's selected or you're asking for changes mid stream. @@ -1226,35 +1259,6 @@ namespace OpenSim.Region.Environment.Scenes } } - /// - /// Send a terse update to the client for the given part - /// - /// - /// - internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part) - { - SceneObjectPart rootPart = m_rootPart; - - // TODO: that could by caused by some race condition with attachments on sim-crossing - if (rootPart == null) return; - - if (rootPart.UUID == part.UUID) - { - if (rootPart.IsAttachment) - { - part.SendTerseUpdateToClient(remoteClient, rootPart.AttachedPos); - } - else - { - part.SendTerseUpdateToClient(remoteClient, AbsolutePosition); - } - } - else - { - part.SendTerseUpdateToClient(remoteClient); - } - } - #endregion #region Copying @@ -1920,6 +1924,8 @@ namespace OpenSim.Region.Environment.Scenes if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); + linkPart.Rezzed = RootPart.Rezzed; + HasGroupChanged = true; ScheduleGroupForFullUpdate(); } @@ -1937,7 +1943,9 @@ namespace OpenSim.Region.Environment.Scenes /// public void DetachFromBackup() { - m_scene.EventManager.OnBackup -= ProcessBackup; + if (m_isBackedUp) + m_scene.EventManager.OnBackup -= ProcessBackup; + m_isBackedUp = false; } private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation) diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index bf6025e..6c76d54 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -212,6 +212,7 @@ namespace OpenSim.Region.Environment.Scenes // It's not necessary to persist this m_TextureAnimation = new byte[0]; m_particleSystem = new byte[0]; + Rezzed = DateTime.Now; } public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, UUID ownerID, uint localID, @@ -237,6 +238,7 @@ namespace OpenSim.Region.Environment.Scenes m_regionHandle = regionHandle; m_parentGroup = parent; + Rezzed = DateTime.Now; _creationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; _ownerID = ownerID; _creatorID = _ownerID; @@ -311,6 +313,8 @@ namespace OpenSim.Region.Environment.Scenes RotationOffset = rotation; ObjectFlags = flags; + Rezzed = DateTime.Now; + m_TextureAnimation = new byte[0]; m_particleSystem = new byte[0]; // Since we don't store script state, this is only a 'temporary' objectflag now @@ -339,6 +343,7 @@ namespace OpenSim.Region.Environment.Scenes */ //System.Console.WriteLine("SceneObjectPart Deserialize END"); + Rezzed = DateTime.Now; } #endregion Constructors @@ -362,6 +367,7 @@ namespace OpenSim.Region.Environment.Scenes private uint _nextOwnerMask = (uint)PermissionMask.All; private PrimFlags _flags = 0; private DateTime m_expires; + private DateTime m_rezzed; public UUID CreatorID { get @@ -459,6 +465,13 @@ namespace OpenSim.Region.Environment.Scenes set { m_expires = value; } } + [XmlIgnore] + public DateTime Rezzed + { + get { return m_rezzed; } + set { m_rezzed = value; } + } + /// /// The position of the entire group that this prim belongs to. /// @@ -1270,6 +1283,7 @@ if (m_shape != null) { dupe._objectSaleType = _objectSaleType; dupe._salePrice = _salePrice; dupe._category = _category; + dupe.m_rezzed = m_rezzed; dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); @@ -2226,10 +2240,10 @@ if (m_shape != null) { /// Send a terse update to the client. /// /// - public void SendTerseUpdate(IClientAPI remoteClient) - { - m_parentGroup.SendPartTerseUpdate(remoteClient, this); - } +// public void SendTerseUpdate(IClientAPI remoteClient) +// { +// SendTerseUpdateToClient(remoteClient); +// } /// /// @@ -2239,54 +2253,14 @@ if (m_shape != null) { List avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Count; i++) { - m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this); - } - } - - public void SendTerseUpdateToClient(IClientAPI remoteClient) - { - Vector3 lPos; - lPos = OffsetPosition; - Quaternion mRot = RotationOffset; - // TODO: I have no idea why we are making this check. This should be sorted out - if ((ObjectFlags & (uint) PrimFlags.Physics) == 0) - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, FromAssetID); - } - else - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, - RotationalVelocity); - //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); + SendTerseUpdateToClient(avatars[i].ControllingClient); } } - public void SendTerseUpdateToClient(IClientAPI remoteClient, Vector3 lPos) - { - Quaternion mRot = RotationOffset; - //bool isattachment = IsAttachment; - //if (LocalId != ParentGroup.RootPart.LocalId) - //isattachment = ParentGroup.RootPart.IsAttachment; - - if (IsAttachment) - { - //m_log.Debug(AttachmentPoint.ToString()); - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, (byte)((AttachmentPoint % 16) * 16 + (AttachmentPoint / 16)),FromAssetID); - } - else - { - if ((ObjectFlags & (uint)PrimFlags.Physics) == 0) - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, FromAssetID); - } - else - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, - RotationalVelocity); - //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); - } - } - } +// public void SendTerseUpdateToClient(IClientAPI remoteClient, Vector3 lPos) +// { +// SendTerseUpdateToClient(remoteclient); +// } public void SetAttachmentPoint(uint AttachmentPoint) { @@ -3257,6 +3231,15 @@ if (m_shape != null) { PhysActor.Shape = m_shape; } + // This is what makes vehicle trailers work + // A script in a child prim re-issues + // llSetPrimitiveParams(PRIM_TYPE) every few seconds. That + // prevents autoreturn. This is not well known. It also works + // in SL. + // + if (ParentGroup.RootPart != this) + ParentGroup.RootPart.Rezzed = DateTime.Now; + ParentGroup.HasGroupChanged = true; ScheduleFullUpdate(); } @@ -3427,5 +3410,42 @@ if (m_shape != null) { } #endregion Public Methods + + private byte GetAttachPointEncoded() + { + return (byte)((AttachmentPoint % 16) * 16 + (AttachmentPoint / 16)); + } + + public void SendTerseUpdateToClient(IClientAPI remoteClient) + { + if (ParentGroup == null || ParentGroup.RootPart == null) + return; + + Vector3 lPos = OffsetPosition; + + byte state = Shape.State; + if (IsAttachment) + { + if (ParentGroup.RootPart != this) + return; + + lPos = ParentGroup.RootPart.AttachedPos; + state = GetAttachPointEncoded(); + } + else + { + if (ParentGroup.RootPart == this) + lPos = AbsolutePosition; + } + + remoteClient.SendPrimTerseUpdate(m_regionHandle, + (ushort)(m_parentGroup.GetTimeDilation() * + (float)ushort.MaxValue), LocalId, lPos, + RotationOffset, Velocity, + RotationalVelocity, state, FromAssetID); + } } } + + + diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 0fe2bdb..4517d11 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -640,7 +640,7 @@ namespace OpenSim.Region.Environment.Scenes // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampTerse); - part.SendTerseUpdate(ControllingClient); + part.SendTerseUpdateToClient(ControllingClient); update.LastTerseUpdateTime = part.TimeStampTerse; updateCount++; -- cgit v1.1