public ISceneEntity CreateEntity( ISceneEntity baseEntity, UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) { MainConsole.Instance.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); return(null); } ISceneChildEntity rootPart = baseEntity.GetChildPart(baseEntity.UUID); // if grass or tree, make phantom //rootPart.TrimPermissions(); rootPart.AddFlag(PrimFlags.Phantom); if (rootPart.Shape.PCode != (byte)PCode.Grass) { AdaptTree(ref shape); } m_scene.SceneGraph.AddPrimToScene(baseEntity); baseEntity.SetGroup(groupID, ownerID, true); baseEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return(baseEntity); }
/// <summary> /// Update the position of the given attachment /// </summary> /// <param name="client"></param> /// <param name="sog"></param> /// <param name="localID"></param> /// <param name="pos"></param> public void UpdateAttachmentPosition(IClientAPI client, ISceneEntity sog, uint localID, Vector3 pos) { if (sog != null) { // If this is an attachment, then we need to save the modified // object back into the avatar's inventory. First we save the // attachment point information, then we update the relative // positioning (which caused this method to get driven in the // first place. Then we have to mark the object as NOT an // attachment. This is necessary in order to correctly save // and retrieve GroupPosition information for the attachment. // Then we save the asset back into the appropriate inventory // entry. Finally, we restore the object's attachment status. byte attachmentPoint = (byte)sog.RootChild.AttachmentPoint; sog.UpdateGroupPosition(pos, true); sog.RootChild.AttachedPos = pos; sog.RootChild.FixOffsetPosition((pos), false); sog.SetAttachmentPoint(attachmentPoint); sog.ScheduleGroupUpdate(PrimUpdateFlags.TerseUpdate); } else { MainConsole.Instance.Warn("[Attachments]: Could not find attachment by ItemID!"); } }
public void llBreakAllLinks() { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return; } ISceneEntity parentPrim = m_host.ParentEntity; if (parentPrim.RootChild.AttachmentPoint != 0) { return; // Fail silently if attached } List <ISceneChildEntity> parts = new List <ISceneChildEntity>(parentPrim.ChildrenEntities()); parts.Remove(parentPrim.RootChild); foreach (ISceneChildEntity part in parts) { parentPrim.DelinkFromGroup(part, true); parentPrim.TriggerScriptChangedEvent(Changed.LINK); part.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); } parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); }
private void CreateTree(UUID uuid, Copse copse, Vector3 position) { position.Z = m_scene.RequestModuleInterface <ITerrainChannel>()[(int)position.X, (int)position.Y]; if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high) { ISceneEntity tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false); tree.Name = copse.ToString(); copse.m_trees.Add(tree.UUID); tree.ScheduleGroupUpdate(PrimUpdateFlags.FindBest); } }
public ISceneEntity CreateEntity( ISceneEntity sceneObject, UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) { MainConsole.Instance.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); return(null); } ISceneChildEntity rootPart = sceneObject.GetChildPart(sceneObject.UUID); rootPart.AddFlag(PrimFlags.Phantom); if (rootPart.Shape.PCode != (byte)PCode.Grass) { // Tree size has to be adapted depending on its type switch ((Tree)rootPart.Shape.State) { case Tree.Cypress1: case Tree.Cypress2: case Tree.Palm1: case Tree.Palm2: case Tree.WinterAspen: rootPart.Scale = new Vector3(4, 4, 10); break; case Tree.WinterPine1: case Tree.WinterPine2: rootPart.Scale = new Vector3(4, 4, 20); break; case Tree.Dogwood: rootPart.Scale = new Vector3(6.5f, 6.5f, 6.5f); break; // case... other tree types // tree.Scale = new Vector3(?, ?, ?); // break; default: rootPart.Scale = new Vector3(4, 4, 4); break; } } sceneObject.SetGroup(groupID, UUID.Zero, false); m_scene.SceneGraph.AddPrimToScene(sceneObject); sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return(sceneObject); }
/// <summary> /// Adds a Scene Object group to the Scene. /// Verifies that the creator of the object is not banned from the simulator. /// Checks if the item is an Attachment /// </summary> /// <param name="scene"></param> /// <param name="sceneObject"></param> /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> public bool AddSceneObject(IScene scene, ISceneEntity sceneObject) { // If the user is banned, we won't let any of their objects // enter. Period. // if (scene.RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) { MainConsole.Instance.Info("[EntityTransferModule]: Denied prim crossing for banned avatar"); return(false); } //if (!sceneObject.IsAttachmentCheckFull()) // Not Attachment { if (!scene.Permissions.CanObjectEntry(sceneObject.UUID, true, sceneObject.AbsolutePosition, sceneObject.OwnerID)) { // Deny non attachments based on parcel settings // MainConsole.Instance.Info("[EntityTransferModule]: Denied prim crossing " + "because of parcel settings"); IBackupModule backup = scene.RequestModuleInterface <IBackupModule>(); if (backup != null) { backup.DeleteSceneObjects(new[] { sceneObject }, true, true); } return(false); } sceneObject.IsInTransit = false; //Reset this now that it's entering here if (scene.SceneGraph.AddPrimToScene(sceneObject)) { if (sceneObject.IsSelected) { sceneObject.RootChild.CreateSelected = true; } sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return(true); } } return(false); }
public ISceneEntity CreateEntity( ISceneEntity baseEntity, UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { if (Array.IndexOf(creationCapabilities, (PCode) shape.PCode) < 0) { MainConsole.Instance.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); return null; } ISceneChildEntity rootPart = baseEntity.GetChildPart(baseEntity.UUID); // if grass or tree, make phantom //rootPart.TrimPermissions(); rootPart.AddFlag(PrimFlags.Phantom); if (rootPart.Shape.PCode != (byte) PCode.Grass) AdaptTree(ref shape); m_scene.SceneGraph.AddPrimToScene(baseEntity); baseEntity.SetGroup(groupID, ownerID, true); baseEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return baseEntity; }
private void DearchiveRegion0DotStar() { if (m_loadStream == null) { return; } int successfulAssetRestores = 0; int failedAssetRestores = 0; string filePath = "NONE"; DateTime start = DateTime.Now; TarArchiveReader archive = new TarArchiveReader(m_loadStream); if (!m_skipAssets) { m_threadpool = new AuroraThreadPool(new AuroraThreadPoolStartInfo() { Threads = 1, priority = System.Threading.ThreadPriority .BelowNormal }); } IBackupModule backup = m_scene.RequestModuleInterface <IBackupModule>(); if (!m_merge) { DateTime before = DateTime.Now; MainConsole.Instance.Info("[ARCHIVER]: Clearing all existing scene objects"); if (backup != null) { backup.DeleteAllSceneObjects(); } MainConsole.Instance.Info("[ARCHIVER]: Cleared all existing scene objects in " + (DateTime.Now - before).Minutes + ":" + (DateTime.Now - before).Seconds); } IScriptModule[] modules = m_scene.RequestModuleInterfaces <IScriptModule>(); //Disable the script engine so that it doesn't load in the background and kill OAR loading foreach (IScriptModule module in modules) { module.Disabled = true; } //Disable backup for now as well if (backup != null) { backup.LoadingPrims = true; } IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface <IRegionSerialiserModule>(); int sceneObjectsLoadedCount = 0; //We save the groups so that we can back them up later List <ISceneEntity> groupsToBackup = new List <ISceneEntity>(); List <LandData> landData = new List <LandData>(); // must save off some stuff until after assets have been saved and recieved new uuids // keeping these collection local because I am sure they will get large and garbage collection is better that way List <byte[]> seneObjectGroups = new List <byte[]>(); Dictionary <UUID, UUID> assetBinaryChangeRecord = new Dictionary <UUID, UUID>(); Queue <UUID> assets2Save = new Queue <UUID>(); try { byte[] data; TarArchiveReader.TarEntryType entryType; while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) { continue; } if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { seneObjectGroups.Add(data); } else if (!m_skipAssets && filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { AssetBase asset; if (LoadAsset(filePath, data, out asset)) { successfulAssetRestores++; if (m_useAsync) { lock (AssetsToAdd) AssetsToAdd.Add(asset); } else { if (asset.IsBinaryAsset) { UUID aid = asset.ID; asset.ID = m_scene.AssetService.Store(asset); if (asset.ID != aid && asset.ID != UUID.Zero) { assetBinaryChangeRecord.Add(aid, asset.ID); } } else { if (!assetNonBinaryCollection.ContainsKey(asset.ID)) { assetNonBinaryCollection.Add(asset.ID, asset); // I need something I can safely loop through assets2Save.Enqueue(asset.ID); } } } } else { failedAssetRestores++; } if ((successfulAssetRestores + failedAssetRestores) % 250 == 0) { MainConsole.Instance.Info("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..."); } } else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { LoadTerrain(filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { LoadRegionSettings(filePath, data); } else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { LandData parcel = LandDataSerializer.Deserialize(m_utf8Encoding.GetString(data)); parcel.OwnerID = ResolveUserUuid(parcel.OwnerID, UUID.Zero, "", Vector3.Zero, null); landData.Add(parcel); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(data); } } // Save Assets int savingAssetsCount = 0; while (assets2Save.Count > 0) { try { UUID assetid = assets2Save.Dequeue(); SaveNonBinaryAssets(assetid, assetNonBinaryCollection[assetid], assetBinaryChangeRecord); savingAssetsCount++; if ((savingAssetsCount) % 250 == 0) { MainConsole.Instance.Info("[ARCHIVER]: Saving " + savingAssetsCount + " assets..."); } } catch (Exception ex) { MainConsole.Instance.Info("[ARCHIVER]: Exception in saving an asset: " + ex.ToString()); } } foreach (byte[] data2 in seneObjectGroups) { byte[] data3 = data2; string stringData = Utils.BytesToString(data3); MatchCollection mc = Regex.Matches(stringData, sPattern); bool didChange = false; if (mc.Count >= 1) { foreach (Match match in mc) { UUID thematch = new UUID(match.Value); UUID newvalue = thematch; if (assetNonBinaryCollection.ContainsKey(thematch)) { newvalue = assetNonBinaryCollection[thematch].ID; } else if (assetBinaryChangeRecord.ContainsKey(thematch)) { newvalue = assetBinaryChangeRecord[thematch]; } if (thematch == newvalue) { continue; } stringData = stringData.Replace(thematch.ToString().Trim(), newvalue.ToString().Trim()); didChange = true; } } if (didChange) { data3 = Utils.StringToBytes(stringData); } ISceneEntity sceneObject = serialiser.DeserializeGroupFromXml2(data3, m_scene); if (sceneObject == null) { //! big error! MainConsole.Instance.Error("Error reading SOP XML (Please mantis this!): " + m_asciiEncoding.GetString(data3)); continue; } foreach (ISceneChildEntity part in sceneObject.ChildrenEntities()) { if (string.IsNullOrEmpty(part.CreatorData)) { part.CreatorID = ResolveUserUuid(part.CreatorID, part.CreatorID, part.CreatorData, part.AbsolutePosition, landData); } part.OwnerID = ResolveUserUuid(part.OwnerID, part.CreatorID, part.CreatorData, part.AbsolutePosition, landData); part.LastOwnerID = ResolveUserUuid(part.LastOwnerID, part.CreatorID, part.CreatorData, part.AbsolutePosition, landData); // And zap any troublesome sit target information part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); part.SitTargetPosition = new Vector3(0, 0, 0); // Fix ownership/creator of inventory items // Not doing so results in inventory items // being no copy/no mod for everyone lock (part.TaskInventory) { TaskInventoryDictionary inv = part.TaskInventory; foreach (KeyValuePair <UUID, TaskInventoryItem> kvp in inv) { kvp.Value.OwnerID = ResolveUserUuid(kvp.Value.OwnerID, kvp.Value.CreatorID, kvp.Value.CreatorData, part.AbsolutePosition, landData); if (string.IsNullOrEmpty(kvp.Value.CreatorData)) { kvp.Value.CreatorID = ResolveUserUuid(kvp.Value.CreatorID, kvp.Value.CreatorID, kvp.Value.CreatorData, part.AbsolutePosition, landData); } } } } //Add the offsets of the region Vector3 newPos = new Vector3(sceneObject.AbsolutePosition.X + m_offsetX, sceneObject.AbsolutePosition.Y + m_offsetY, sceneObject.AbsolutePosition.Z + m_offsetZ); if (m_flipX) { newPos.X = m_scene.RegionInfo.RegionSizeX - newPos.X; } if (m_flipY) { newPos.Y = m_scene.RegionInfo.RegionSizeY - newPos.Y; } sceneObject.SetAbsolutePosition(false, newPos); if (m_scene.SceneGraph.AddPrimToScene(sceneObject)) { groupsToBackup.Add(sceneObject); sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); sceneObject.CreateScriptInstances(0, false, StateSource.RegionStart, UUID.Zero, true); } sceneObjectsLoadedCount++; if (sceneObjectsLoadedCount % 250 == 0) { MainConsole.Instance.Info("[ARCHIVER]: Loaded " + sceneObjectsLoadedCount + " objects..."); } } assetNonBinaryCollection.Clear(); assetBinaryChangeRecord.Clear(); seneObjectGroups.Clear(); } catch (Exception e) { MainConsole.Instance.ErrorFormat( "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); m_errorMessage += e.ToString(); m_scene.EventManager.TriggerOarFileLoaded(UUID.Zero.Guid, m_errorMessage); return; } finally { archive.Close(); m_loadStream.Close(); m_loadStream.Dispose(); //Reeanble now that we are done foreach (IScriptModule module in modules) { module.Disabled = false; } //Reset backup too if (backup != null) { backup.LoadingPrims = false; } } //Now back up the prims foreach (ISceneEntity grp in groupsToBackup) { //Backup! grp.HasGroupChanged = true; } if (!m_skipAssets && m_useAsync && !AssetSaverIsRunning) { m_threadpool.QueueEvent(SaveAssets, 0); } if (!m_skipAssets) { MainConsole.Instance.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); if (failedAssetRestores > 0) { MainConsole.Instance.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); } } // Try to retain the original creator/owner/lastowner if their uuid is present on this grid // otherwise, use the master avatar uuid instead // Reload serialized parcels MainConsole.Instance.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", landData.Count); IParcelManagementModule parcelManagementModule = m_scene.RequestModuleInterface <IParcelManagementModule>(); if (parcelManagementModule != null) { parcelManagementModule.IncomingLandDataFromOAR(landData, m_merge, new Vector2(m_offsetX, m_offsetY)); } MainConsole.Instance.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); //Clean it out landData.Clear(); MainConsole.Instance.InfoFormat("[ARCHIVER]: Successfully loaded archive in " + (DateTime.Now - start).Minutes + ":" + (DateTime.Now - start).Seconds); m_validUserUuids.Clear(); m_scene.EventManager.TriggerOarFileLoaded(UUID.Zero.Guid, m_errorMessage); }
/// <summary> /// Adds a Scene Object group to the Scene. /// Verifies that the creator of the object is not banned from the simulator. /// Checks if the item is an Attachment /// </summary> /// <param name="scene"></param> /// <param name="sceneObject"></param> /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> public bool AddSceneObject(IScene scene, ISceneEntity sceneObject) { // If the user is banned, we won't let any of their objects // enter. Period. // if (scene.RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) { MainConsole.Instance.Info("[EntityTransferModule]: Denied prim crossing for banned avatar"); return false; } //if (!sceneObject.IsAttachmentCheckFull()) // Not Attachment { if (!scene.Permissions.CanObjectEntry(sceneObject.UUID, true, sceneObject.AbsolutePosition, sceneObject.OwnerID)) { // Deny non attachments based on parcel settings // MainConsole.Instance.Info("[EntityTransferModule]: Denied prim crossing " + "because of parcel settings"); IBackupModule backup = scene.RequestModuleInterface<IBackupModule>(); if (backup != null) backup.DeleteSceneObjects(new[] {sceneObject}, true, true); return false; } sceneObject.IsInTransit = false; //Reset this now that it's entering here if (scene.SceneGraph.AddPrimToScene(sceneObject)) { if (sceneObject.IsSelected) sceneObject.RootChild.CreateSelected = true; sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return true; } } return false; }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> /// <param name="destination"></param> public bool CrossGroupToNewRegion(ISceneEntity grp, Vector3 attemptedPosition, GridRegion destination) { if (grp == null) return false; if (grp.IsDeleted) return false; if (grp.Scene == null) return false; if (grp.RootChild.DIE_AT_EDGE) { // We remove the object here try { IBackupModule backup = grp.Scene.RequestModuleInterface<IBackupModule>(); if (backup != null) return backup.DeleteSceneObjects(new[] {grp}, true, true); } catch (Exception) { MainConsole.Instance.Warn( "[DATABASE]: exception when trying to remove the prim that crossed the border."); } return false; } if (grp.RootChild.RETURN_AT_EDGE) { // We remove the object here try { List<ISceneEntity> objects = new List<ISceneEntity> {grp}; ILLClientInventory inventoryModule = grp.Scene.RequestModuleInterface<ILLClientInventory>(); if (inventoryModule != null) return inventoryModule.ReturnObjects(objects.ToArray(), UUID.Zero); } catch (Exception) { MainConsole.Instance.Warn( "[SCENE]: exception when trying to return the prim that crossed the border."); } return false; } Vector3 oldGroupPosition = grp.RootChild.GroupPosition; // If we fail to cross the border, then reset the position of the scene object on that border. if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, attemptedPosition)) { grp.OffsetForNewRegion(oldGroupPosition); grp.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return false; } return true; }
/// <summary> /// Update the position of the given attachment /// </summary> /// <param name="client"></param> /// <param name="sog"></param> /// <param name="localID"></param> /// <param name="pos"></param> public void UpdateAttachmentPosition(IClientAPI client, ISceneEntity sog, uint localID, Vector3 pos) { if (sog != null) { // If this is an attachment, then we need to save the modified // object back into the avatar's inventory. First we save the // attachment point information, then we update the relative // positioning (which caused this method to get driven in the // first place. Then we have to mark the object as NOT an // attachment. This is necessary in order to correctly save // and retrieve GroupPosition information for the attachment. // Then we save the asset back into the appropriate inventory // entry. Finally, we restore the object's attachment status. byte attachmentPoint = (byte) sog.RootChild.AttachmentPoint; sog.UpdateGroupPosition(pos, true); sog.RootChild.AttachedPos = pos; sog.RootChild.FixOffsetPosition((pos), false); //sog.AbsolutePosition = sog.RootChild.AttachedPos; sog.SetAttachmentPoint(attachmentPoint); sog.ScheduleGroupUpdate(PrimUpdateFlags.TerseUpdate); //Don't update right now, wait until logout //UpdateKnownItem(client, sog, sog.GetFromItemID(), sog.OwnerID); } else { MainConsole.Instance.Warn("[Attachments]: Could not find attachment by ItemID!"); } }
/// <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, ISceneEntity group, int AttachmentPt, InventoryItemBase item) { //Make sure that we arn't over the limit of attachments ISceneEntity[] 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(); bool hasMultipleAttachmentsSet = (AttachmentPt & 0x7f) != 0 || AttachmentPt == 0; if(!m_allowMultipleAttachments) hasMultipleAttachmentsSet = false; AttachmentPt &= 0x7f; //Disable it! Its evil! //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 != 0 && AttachmentPt != (int)(group.GetAttachmentPoint() & 0x7f)) { attachPos = Vector3.Zero; changedPositionPoint = true; } else { // AttachmentPt 0 means the client chose to 'wear' the attachment. if (AttachmentPt == 0) { // Check object for stored attachment point AttachmentPt = (int)group.GetSavedAttachmentPoint() & 0x7f; attachPos = group.GetAttachmentPos(); } //Check state afterwards... use the newer GetSavedAttachmentPoint and Pos above first if (AttachmentPt == 0) { // Check object for older stored attachment point AttachmentPt = group.RootChild.Shape.State & 0x7f; //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 == 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 IScenePresence presence = m_scene.GetScenePresence (remoteClient.AgentId); if (presence == null) return; UUID itemID = UUID.Zero; //Check for multiple attachment bits and whether we should remove the old if(!hasMultipleAttachmentsSet) { foreach (ISceneEntity grp in attachments) { if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { itemID = grp.RootChild.FromUserInventoryItemID; break; } } if (itemID != UUID.Zero) DetachSingleAttachmentToInventory(itemID, remoteClient); } itemID = group.RootChild.FromUserInventoryItemID; group.RootChild.AttachedAvatar = presence.UUID; List<ISceneChildEntity> parts = group.ChildrenEntities(); for (int i = 0; i < parts.Count; i++) parts[i].AttachedAvatar = presence.UUID; if (group.RootChild.PhysActor != null) { m_scene.PhysicsScene.RemovePrim (group.RootChild.PhysActor); group.RootChild.PhysActor = null; } group.RootChild.AttachedPos = attachPos; group.RootChild.IsAttachment = true; group.AbsolutePosition = attachPos; group.RootChild.SetParentLocalId (presence.LocalId); group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); AvatarAttachments attPlugin = presence.RequestModuleInterface<AvatarAttachments>(); if (attPlugin != null) { attPlugin.AddAttachment (group); presence.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 (ISceneChildEntity part in group.ChildrenEntities()) { part.CreateSelected = true; } } //Kill the previous entity so that it will be selected SendKillEntity(group.RootChild); //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<ISceneEntity> groups = new List<ISceneEntity> (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, StateSource.AttachedRez, 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 (itemID); //If we updated the attachment, we need to save the change IAvatarAppearanceModule appearance = presence.RequestModuleInterface<IAvatarAppearanceModule> (); if (appearance.Appearance.SetAttachment ((int)AttachmentPt, itemID, item.AssetID)) AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); // In case it is later dropped again, don't let // it get cleaned up group.RootChild.RemFlag(PrimFlags.TemporaryOnRez); group.HasGroupChanged = false; //Now recreate it so that it is selected group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); m_scene.EventManager.TriggerOnAttach(localID, group.RootChild.FromUserInventoryItemID, remoteClient.AgentId); }
public DateTime llCreateLink(string target, int parent) { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return(DateTime.Now); } UUID invItemID = InventorySelf(); UUID targetID; if (!UUID.TryParse(target, out targetID)) { return(DateTime.Now); } TaskInventoryItem item; lock (m_host.TaskInventory) { item = m_host.TaskInventory[invItemID]; } if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set"); return(DateTime.Now); } IClientAPI client = null; IScenePresence sp = World.GetScenePresence(item.PermsGranter); if (sp != null) { client = sp.ControllingClient; } ISceneChildEntity targetPart = World.GetSceneObjectPart(targetID); if (targetPart.ParentEntity.RootChild.AttachmentPoint != 0) { return(DateTime.Now); } // Fail silently if attached ISceneEntity parentPrim = null; ISceneEntity childPrim = null; if (parent != 0) { parentPrim = m_host.ParentEntity; childPrim = targetPart.ParentEntity; } else { parentPrim = targetPart.ParentEntity; childPrim = m_host.ParentEntity; } // byte uf = childPrim.RootPart.UpdateFlag; parentPrim.LinkToGroup(childPrim); // if (uf != (Byte)0) // parent.RootPart.UpdateFlag = uf; parentPrim.TriggerScriptChangedEvent(Changed.LINK); parentPrim.RootChild.CreateSelected = true; parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); if (client != null) { parentPrim.GetProperties(client); } return(PScriptSleep(m_sleepMsOnCreateLink)); }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> /// <param name="destination"></param> public bool CrossGroupToNewRegion(ISceneEntity grp, Vector3 attemptedPosition, GridRegion destination) { if (grp == null) { return(false); } if (grp.IsDeleted) { return(false); } if (grp.Scene == null) { return(false); } if (grp.RootChild.DIE_AT_EDGE) { // We remove the object here try { IBackupModule backup = grp.Scene.RequestModuleInterface <IBackupModule> (); if (backup != null) { return(backup.DeleteSceneObjects(new [] { grp }, true, true)); } } catch (Exception) { MainConsole.Instance.Warn( "[Database]: exception when trying to remove the prim that crossed the border."); } return(false); } if (grp.RootChild.RETURN_AT_EDGE) { // We remove the object here try { List <ISceneEntity> objects = new List <ISceneEntity> { grp }; ILLClientInventory inventoryModule = grp.Scene.RequestModuleInterface <ILLClientInventory> (); if (inventoryModule != null) { return(inventoryModule.ReturnObjects(objects.ToArray(), UUID.Zero)); } } catch (Exception) { MainConsole.Instance.Warn( "[Scene]: exception when trying to return the prim that crossed the border."); } return(false); } Vector3 oldGroupPosition = grp.RootChild.GroupPosition; // If we fail to cross the border, then reset the position of the scene object on that border. if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, attemptedPosition)) { grp.OffsetForNewRegion(oldGroupPosition); grp.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); return(false); } return(true); }
public void llBreakLink(int linknum) { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return; } UUID invItemID = InventorySelf(); lock (m_host.TaskInventory) { if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set"); return; } } if (linknum < ScriptBaseClass.LINK_THIS) { return; } ISceneEntity parentPrim = m_host.ParentEntity; if (parentPrim.RootChild.AttachmentPoint != 0) { return; // Fail silently if attached } ISceneChildEntity childPrim = null; if (linknum == ScriptBaseClass.LINK_ROOT) { } else if (linknum == ScriptBaseClass.LINK_SET || ScriptBaseClass.LINK_ALL_OTHERS || ScriptBaseClass.LINK_ALL_CHILDREN || ScriptBaseClass.LINK_THIS) { foreach (ISceneChildEntity part in parentPrim.ChildrenEntities()) { if (part.UUID != m_host.UUID) { childPrim = part; break; } } } else { IEntity target = m_host.ParentEntity.GetLinkNumPart(linknum); if (target is ISceneChildEntity) { childPrim = target as ISceneChildEntity; } else { return; } if (childPrim.UUID == m_host.UUID) { childPrim = null; } } if (linknum == ScriptBaseClass.LINK_ROOT) { // Restructuring Multiple Prims. List <ISceneChildEntity> parts = new List <ISceneChildEntity>(parentPrim.ChildrenEntities()); parts.Remove(parentPrim.RootChild); foreach (ISceneChildEntity part in parts) { parentPrim.DelinkFromGroup(part, true); } parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); parentPrim.TriggerScriptChangedEvent(Changed.LINK); if (parts.Count > 0) { ISceneChildEntity newRoot = parts[0]; parts.Remove(newRoot); foreach (ISceneChildEntity part in parts) { newRoot.ParentEntity.LinkToGroup(part.ParentEntity); } newRoot.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); } } else { if (childPrim == null) { return; } parentPrim.DelinkFromGroup(childPrim, true); childPrim.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); parentPrim.TriggerScriptChangedEvent(Changed.LINK); } }
/// <summary> /// Create a tree entity /// </summary> /// <param name="sceneObject">Scene object.</param> /// <param name="ownerID"></param> /// <param name="groupID"></param> /// <param name="pos"></param> /// <param name="rot"></param> /// <param name="shape"></param> /// <returns>The tree entity created, or null if the creation failed</returns> public ISceneEntity CreateEntity( ISceneEntity sceneObject, UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { if ( Array.IndexOf( creationCapabilities, ( PCode)shape.PCode ) < 0 ) { MainConsole.Instance.Debug ( "[VEGETATION]: PCode " + shape.PCode + " not handled by "+ Name ); return null; } ISceneChildEntity rootPart = sceneObject.GetChildPart(sceneObject.UUID); rootPart.AddFlag(PrimFlags.Phantom); if ( rootPart.Shape.PCode != (byte)PCode.Grass ) { // Tree size has to be adapted depending on its type switch ( (Tree)rootPart.Shape.State ) { case Tree.Cypress1: case Tree.Cypress2: case Tree.Palm1: case Tree.Palm2: case Tree.WinterAspen: rootPart.Scale = new Vector3(4, 4, 10); break; case Tree.WinterPine1: case Tree.WinterPine2: rootPart.Scale = new Vector3(4, 4, 20); break; case Tree.Dogwood: rootPart.Scale = new Vector3(6.5f, 6.5f, 6.5f); break; // case... other tree types // tree.Scale = new Vector3(?, ?, ?); // break; default: rootPart.Scale = new Vector3(4, 4, 4); break; } } sceneObject.SetGroup( groupID, UUID.Zero, false ); m_scene.SceneGraph.AddPrimToScene( sceneObject ); sceneObject.ScheduleGroupUpdate( PrimUpdateFlags.ForcedFullUpdate ); return sceneObject; }
/// <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="assetID" /> /// <param name="forceUpdatePrim">Force updating of the prim the next time the user attempts to deattach it</param> /// <param name="isTempAttach">Is a temporary attachment</param> protected void FindAttachmentPoint(IClientAPI remoteClient, uint localID, ISceneEntity group, int AttachmentPt, UUID assetID, bool forceUpdatePrim, bool isTempAttach) { //Make sure that we arn't over the limit of attachments ISceneEntity[] 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(); bool hasMultipleAttachmentsSet = (AttachmentPt & 0x7f) != 0 || AttachmentPt == 0; if (!m_allowMultipleAttachments) { hasMultipleAttachmentsSet = false; } AttachmentPt &= 0x7f; //Disable it! Its evil! //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 != 0 && AttachmentPt != (group.GetAttachmentPoint() & 0x7f)) { attachPos = Vector3.Zero; changedPositionPoint = true; } else { // AttachmentPt 0 means the client chose to 'wear' the attachment. if (AttachmentPt == 0) { // Check object for stored attachment point AttachmentPt = group.GetSavedAttachmentPoint() & 0x7f; attachPos = group.GetAttachmentPos(); } //Check state afterwards... use the newer GetSavedAttachmentPoint and Pos above first if (AttachmentPt == 0) { // Check object for older stored attachment point AttachmentPt = group.RootChild.Shape.State & 0x7f; } // 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 == 0) { // Stick it on right hand with Zero Offset from the attachment point. AttachmentPt = (int)AttachmentPoint.RightHand; //Default location attachPos = Vector3.Zero; changedPositionPoint = true; } } MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2} localID {3}", group.Name, remoteClient.Name, AttachmentPt, group.LocalId); //Update where we are put group.SetAttachmentPoint((byte)AttachmentPt); //Fix the position with the one we found group.AbsolutePosition = attachPos; // Remove any previous attachments IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence == null) { return; } UUID itemID = UUID.Zero; //Check for multiple attachment bits and whether we should remove the old if (!hasMultipleAttachmentsSet) { foreach (ISceneEntity grp in attachments) { if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { itemID = grp.RootChild.FromUserInventoryItemID; break; } } if (itemID != UUID.Zero) { DetachSingleAttachmentToInventory(itemID, remoteClient); } } itemID = group.RootChild.FromUserInventoryItemID; group.RootChild.AttachedAvatar = presence.UUID; List <ISceneChildEntity> parts = group.ChildrenEntities(); foreach (ISceneChildEntity t in parts) { t.AttachedAvatar = presence.UUID; } if (group.RootChild.PhysActor != null) { m_scene.PhysicsScene.DeletePrim(group.RootChild.PhysActor); group.RootChild.PhysActor = null; } group.RootChild.AttachedPos = attachPos; group.RootChild.IsAttachment = true; group.AbsolutePosition = attachPos; group.RootChild.SetParentLocalId(presence.LocalId); group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); // 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 (ISceneChildEntity part in group.ChildrenEntities()) { part.CreateSelected = true; } } //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 (!isTempAttach) { if (itemID == UUID.Zero) { //Delete the object inworld to inventory List <ISceneEntity> groups = new List <ISceneEntity>(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. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); } if (UUID.Zero == itemID) { MainConsole.Instance.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 (assetID == UUID.Zero) { assetID = m_scene.InventoryService.GetItemAssetID(remoteClient.AgentId, itemID); //Update the ItemID with the new item group.SetFromItemID(itemID, assetID); } } else { // Fire after attach, so we don't get messy perms dialogs. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); group.RootChild.FromUserInventoryItemID = UUID.Zero; } AvatarAttachments attPlugin = presence.RequestModuleInterface <AvatarAttachments>(); if (attPlugin != null) { attPlugin.AddAttachment(group); presence.SetAttachments(attPlugin.Get()); if (!isTempAttach) { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); appearance.Appearance.SetAttachments(attPlugin.Get()); AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); } } // In case it is later dropped again, don't let // it get cleaned up group.RootChild.RemFlag(PrimFlags.TemporaryOnRez); group.HasGroupChanged = changedPositionPoint || forceUpdatePrim; //Now recreate it so that it is selected group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); m_scene.EventManager.TriggerOnAttach(localID, group.RootChild.FromUserInventoryItemID, remoteClient.AgentId); }