public CreateScriptInstances ( int startParam, bool postOnRez, string engine, int stateSource ) : void | ||
startParam | int | |
postOnRez | bool | |
engine | string | |
stateSource | int | |
return | void |
/// <summary> /// Internal method which actually does all the work for attaching an object. /// </summary> /// <returns>The object attached.</returns> /// <param name='sp'></param> /// <param name='group'>The object to attach.</param> /// <param name='attachmentPt'></param> /// <param name='silent'></param> /// <param name='addToInventory'>If true then add object to user inventory.</param> /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> /// <param name='append'>Append to attachment point rather than replace.</param> private bool AttachObjectInternal( IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append) { if (group.GetSittingAvatarsCount() != 0) { if (DebugLevel > 0) m_log.WarnFormat( "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); return false; } Vector3 attachPos = group.AbsolutePosition; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint) { attachPos = Vector3.Zero; } // if the attachment point is the same as previous, make sure we get the saved // position info. if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint) { attachPos = group.RootPart.AttachedPos; } // AttachmentPt 0 means the client chose to 'wear' the attachment. if (attachmentPt == (uint)AttachmentPoint.Default) { // Check object for stored attachment point attachmentPt = group.AttachmentPoint; } // if we didn't find an attach point, look for where it was last attached if (attachmentPt == 0) { attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; attachPos = group.RootPart.AttachedPos; group.HasGroupChanged = true; } // if we still didn't find a suitable attachment point....... if (attachmentPt == 0) { // Stick it on left hand with Zero Offset from the attachment point. attachmentPt = (uint)AttachmentPoint.LeftHand; attachPos = Vector3.Zero; } group.AttachmentPoint = attachmentPt; group.AbsolutePosition = attachPos; List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); if (attachments.Contains(group)) { if (DebugLevel > 0) m_log.WarnFormat( "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", group.Name, group.LocalId, sp.Name, attachmentPt); return false; } // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones while (attachments.Count >= 5) { if (attachments[0].FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, attachments[0]); attachments.RemoveAt(0); } // If we're not appending, remove the rest as well if (attachments.Count != 0 && !append) { foreach (SceneObjectGroup g in attachments) { if (g.FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, g); } } lock (sp.AttachmentsSyncLock) { if (addToInventory && sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); AttachToAgent(sp, group, attachmentPt, attachPos, silent); if (resumeScripts) { // Fire after attach, so we don't get messy perms dialogs // 4 == AttachedRez group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); group.ResumeScripts(); } // Do this last so that event listeners have access to all the effects of the attachment m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); } return true; }
private SceneObjectGroup RezSingleObjectToWorld(IClientAPI remoteClient, UUID itemID, SceneObjectGroup group, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, byte bRayEndIsIntersection, bool RezSelected, bool attachment, Vector3 pos, string name, string description, IInventoryItem item, ItemPermissionBlock itemPermissions, int? startParam, UUID? newAvatarGroupId, UUID? rezzedByObjectUUID) { bool ownerChanged = false; // record this for the CHANGED_OWNER changed event if (IsBadUserLoad(group)) { if (remoteClient != null) remoteClient.SendAgentAlertMessage("You are currently not allowed to rez objects in this region.", false); return null; // already reported above } if (IsBlacklistedLoad(group)) { if (remoteClient != null) remoteClient.SendAgentAlertMessage("Cannot rez blacklisted object '" + group.Name + "'.", false); return null; // already reported above } //set the group here so that positioning in world will enable/disable the //script correctly based on the group the use is currently in // Initialize the server weight (LI) group.RecalcPrimWeights(); group.RezzedFromFolderId = item.Folder; //group.FromAssetId = item.AssetID; //not needed yet if (newAvatarGroupId.HasValue) { //set the object's land group group.SetGroup(newAvatarGroupId.Value, null); } if (attachment) { group.SetFromItemID(itemID); } else { group.RootPart.SetGroupPositionDirect(pos); if (RezSelected) { //also tell the client there is a new object being rezzed foreach (SceneObjectPart part in group.GetParts()) { part.AddFlag(PrimFlags.CreateSelected); } } } SceneObjectPart rootPart = group.GetChildPart(group.UUID); if (rootPart == null) { string what = "object "; if (attachment) what = " attachment "; m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + what + " root part not found."); return null; } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = name; rootPart.Description = description; var partList = group.GetParts(); foreach (SceneObjectPart part in partList) { /// This fixes inconsistencies between this part and the root part. /// In the past, there was a bug in Link operations that did not force /// these permissions on child prims when linking. part.SyncChildPermsWithRoot(); } if (rootPart.OwnerID != item.Owner) { if (Permissions.PropagatePermissions()) { if ((itemPermissions.CurrentPermissions & ScenePermBits.SLAM) != 0) { // enforce slam bit, apply item perms to the group parts foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } ownerChanged |= group.Rationalize(item.Owner, false); foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); ownerChanged = true; } else if (((itemPermissions.CurrentPermissions & ScenePermBits.SLAM) != 0) && (!attachment)) // Slam! { part.EveryoneMask = itemPermissions.EveryOnePermissions; part.NextOwnerMask = itemPermissions.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.IsPrim) { group.ClearPartAttachmentData(); } } if (this.AddObjectToSceneIfPermitted(group, remoteClient, pos, attachment, rezzedByObjectUUID)) { if (ownerChanged) { foreach (SceneObjectPart part in partList) part.TriggerScriptChangedEvent(Changed.OWNER); } if (!attachment) { // Fire on_rez group.CreateScriptInstances(startParam, ScriptStartFlags.PostOnRez, DefaultScriptEngine, (int)ScriptStateSource.PrimData, null); rootPart.ScheduleFullUpdate(PrimUpdateFlags.ForcedFullUpdate); } } else { // The viewer automatically removes no-copy items from inventory on a rez attempt. // Since this one did not rez, it's still in inventory so let's "put it back". if (remoteClient != null) { InventoryItemBase ib = item as InventoryItemBase; if (item != null) { //this is a folder item, not a task item. update the user remoteClient.SendInventoryItemCreateUpdate(ib, 0); } } return null; } return rootPart.ParentGroup; }
public virtual SceneObjectGroup RezPrim(SceneObjectPart sourcePart, SceneObjectPart newPart, int param, out string reason) { // Rez object Vector3 pos = newPart.AbsolutePosition; SceneObjectGroup group = new SceneObjectGroup(newPart); bool isTemp = (group.RootPart.GetEffectiveObjectFlags() & PrimFlags.TemporaryOnRez) != 0; ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); if (parcel == null) { reason = "land"; return null; } // Pass 0 for landImpact here so that it can be tested separately. if (!Permissions.CanRezObject(0, newPart.OwnerID, sourcePart.UUID, pos, isTemp)) { reason = "permission"; return null; } if (!CheckLandImpact(parcel, group.LandImpact, out reason)) { return null; } // Check for grey goo fence if (!CheckGreyGoo(sourcePart, group)) { reason = "fence"; return null; } // Allowing the rez... update the last rez time and the new group fields sourcePart.StampLastRez(); group.CurrentParcel = parcel; // initialize _currentParcel (and auto-return) group.SetGeneration(group.RootPart.Generation); // now update the rest of the parts group.ResetIDs(); //set the group's group before setting the object's position. //this will make sure that the group id is correct during the script //engine's group check group.SetGroup(sourcePart.ParentGroup.RootPart.GroupID, null); AddNewSceneObject(group, !isTemp); SceneObjectPart rootPart = group.GetChildPart(group.UUID); rootPart.TrimPermissions(); if (group.RootPart.IsPrim) { group.ClearPartAttachmentData(); } group.CreateScriptInstances(param, ScriptStartFlags.PostOnRez, DefaultScriptEngine, (int)ScriptStateSource.PrimData, null); rootPart.ScheduleFullUpdate(PrimUpdateFlags.ForcedFullUpdate); reason = "success"; return rootPart.ParentGroup; }
/// <summary> /// Attach the object to the avatar /// </summary> /// <param name="remoteClient">The client that is having the attachment done</param> /// <param name="localID">The localID (SceneObjectPart) that is being attached (for the attach script event)</param> /// <param name="group">The group (SceneObjectGroup) that is being attached</param> /// <param name="AttachmentPt">The point to where the attachment will go</param> /// <param name="item">If this is not null, it saves a query in this method to the InventoryService /// This is the Item that the object is in (if it is in one yet)</param> protected void FindAttachmentPoint(IClientAPI remoteClient, uint localID, SceneObjectGroup group, int AttachmentPt, InventoryItemBase item) { //Make sure that we arn't over the limit of attachments SceneObjectGroup[] attachments = GetAttachmentsForAvatar(remoteClient.AgentId); if (attachments.Length + 1 > m_maxNumberOfAttachments) { //Too many remoteClient.SendAgentAlertMessage( "You are wearing too many attachments. Take one off to attach this object", false); return; } Vector3 attachPos = group.GetAttachmentPos(); if(!m_allowMultipleAttachments) AttachmentPt &= 0x7f; //Disable it! //Did the attachment change position or attachment point? bool changedPositionPoint = false; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. //Simplier terms: the attachment point changed, set it to the default 0,0,0 location if ((AttachmentPt & 0x7f) != 0 && (AttachmentPt & 0x7f) != (int)group.GetAttachmentPoint()) { attachPos = Vector3.Zero; changedPositionPoint = true; } else { // AttachmentPt 0 means the client chose to 'wear' the attachment. if ((AttachmentPt & 0x7f) == 0) { // Check object for stored attachment point AttachmentPt = (int)group.GetSavedAttachmentPoint(); attachPos = group.GetAttachmentPos(); } //Check state afterwards... use the newer GetSavedAttachmentPoint and Pos above first if ((AttachmentPt & 0x7f) == 0) { // Check object for older stored attachment point AttachmentPt = group.RootPart.Shape.State; //attachPos = group.AbsolutePosition; } // if we still didn't find a suitable attachment point, force it to the default //This happens on the first time an avatar 'wears' an object if ((AttachmentPt & 0x7f) == 0) { // Stick it on right hand with Zero Offset from the attachment point. AttachmentPt = (int)AttachmentPoint.RightHand; //Default location attachPos = Vector3.Zero; changedPositionPoint = true; } } group.HasGroupChanged = changedPositionPoint; //Update where we are put group.SetAttachmentPoint((byte)AttachmentPt); //Fix the position with the one we found group.AbsolutePosition = attachPos; // Remove any previous attachments ScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence == null) return; UUID itemID = UUID.Zero; //Check for multiple attachment bits //If the numbers are the same, it wants to have the old attachment taken off if ((AttachmentPt & 0x7f) == AttachmentPt) { foreach (SceneObjectGroup grp in attachments) { if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { itemID = grp.GetFromItemID(); break; } } if (itemID != UUID.Zero) DetachSingleAttachmentToInventory(itemID, remoteClient); } itemID = group.GetFromItemID(); group.RootPart.AttachedAvatar = presence.UUID; //Anakin Lohner bug #3839 SceneObjectPart[] parts = group.Parts; for (int i = 0; i < parts.Length; i++) parts[i].AttachedAvatar = presence.UUID; if (group.RootPart.PhysActor != null) { m_scene.SceneGraph.PhysicsScene.RemovePrim(group.RootPart.PhysActor); group.RootPart.PhysActor = null; } group.AbsolutePosition = attachPos; group.RootPart.AttachedPos = attachPos; group.RootPart.IsAttachment = true; group.RootPart.SetParentLocalId(presence.LocalId); group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); AvatarAttachments attPlugin = presence.RequestModuleInterface<AvatarAttachments>(); if (attPlugin != null) attPlugin.AddAttachment(group); // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below // if (group.IsSelected) { foreach (SceneObjectPart part in group.ChildrenList) { part.CreateSelected = true; } } //Kill the previous entity so that it will be selected SendKillEntity(group.RootPart); //NOTE: This MUST be here, otherwise we limit full updates during attachments when they are selected and it will block the first update. // So until that is changed, this MUST stay. The client will instantly reselect it, so this value doesn't stay borked for long. group.IsSelected = false; if (itemID == UUID.Zero) { //Delete the object inworld to inventory List<SceneObjectGroup> groups = new List<SceneObjectGroup>(1) { group }; IInventoryAccessModule inventoryAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); if (inventoryAccess != null) inventoryAccess.DeleteToInventory(DeRezAction.AcquireToUserInventory, UUID.Zero, groups, remoteClient.AgentId, out itemID); } else { //it came from an item, we need to start the scripts // Fire after attach, so we don't get messy perms dialogs // 4 == AttachedRez group.CreateScriptInstances(0, true, 4, UUID.Zero); group.ResumeScripts(); } if (UUID.Zero == itemID) { m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID."); remoteClient.SendAgentAlertMessage( "Unable to save attachment. Error inventory item ID.", false); return; } // XXYY!! if (item == null) { item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); } //Update the ItemID with the new item group.SetFromItemID(item.ID); //If we updated the attachment, we need to save the change if (presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID)) AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); //Now recreate it so that it is selected group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate); // In case it is later dropped again, don't let // it get cleaned up group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); group.HasGroupChanged = false; m_scene.EventManager.TriggerOnAttach(localID, group.GetFromItemID(), remoteClient.AgentId); }