/// <summary> /// Only called from within the SimChat method. Hides all auras and meta entities, /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, /// then lets the view update the clients of the new objects. /// </summary> protected void rollback(Scene scene, CMModel model, CMView view) { if ((m_state & State.SHOWING_CHANGES) > 0) { view.HideAllAuras(); view.HideAllMetaEntities(); } System.Collections.Generic.List <Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); foreach (Scene currScene in proximitySceneList) { model.RollbackRegion(currScene); } if ((m_state & State.DIRTY) != 0) { model.DeleteAllMetaObjects(); foreach (Scene currScene in proximitySceneList) { model.UpdateCMEntities(currScene); } } if ((m_state & State.SHOWING_CHANGES) > 0) { view.DisplayRecentChanges(); } }
/// <summary> /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. /// </summary> private void ObjectDuplicated(CMModel model, CMView view, uint localId) { if ((m_state & State.SHOWING_CHANGES) > 0) { view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); } }
/// <summary> /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. /// </summary> private void MainLoop() { try { CMModel model = m_model; CMView view = m_view; int channel = m_channel; Work currentJob = new Work(); while (true) { currentJob = m_WorkQueue.Dequeue(); m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); switch (currentJob.Type) { case WorkType.NONE: break; case WorkType.OBJECTATTRIBUTECHANGE: ObjectAttributeChanged(model, view, currentJob.LocalId); break; case WorkType.PRIMITIVEADDED: PrimitiveAdded(model, view, currentJob); break; case WorkType.OBJECTDUPLICATED: ObjectDuplicated(model, view, currentJob.LocalId); break; case WorkType.OBJECTKILLED: ObjectKilled(model, view, (SceneObjectGroup)currentJob.Data1); break; case WorkType.UNDODID: UndoDid(model, view, currentJob.UUID); break; case WorkType.NEWCLIENT: NewClient(view, (IClientAPI)currentJob.Data1); break; case WorkType.SIMCHAT: m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage)currentJob.Data1).Message); SimChat(model, view, (OSChatMessage)currentJob.Data1, channel); break; default: m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); break; } } } catch (Exception e) { // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened m_log.ErrorFormat( "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", e); } }
/// <summary> /// Only called by the MainLoop. /// </summary> private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) { if ((m_state & State.SHOWING_CHANGES) > 0) { view.RemoveOrUpdateDeletedEntity(group); model.RemoveOrUpdateDeletedEntity(group); } }
private void Initialize(CMModel model, CMView view, Scene scene, int channel) { lock (this) { m_estateModule = scene.RequestModuleInterface <IEstateModule>(); Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true); m_state = State.NONE; } }
public void Initialise(Scene scene, IConfigSource source) { string databaseDir = "./"; string database = "FileSystemDatabase"; int channel = 345; try { if (source.Configs["CMS"] == null) { return; } m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); database = source.Configs["CMS"].GetString("database", database); channel = source.Configs["CMS"].GetInt("channel", channel); if (database != "FileSystemDatabase" && database != "GitDatabase") { m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); m_enabled = false; } } catch (Exception e) { m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); m_enabled = false; } if (!m_enabled) { m_log.Info("[Content Management]: Content Management System is not Enabled."); return; } lock (this) { if (!initialised) //only init once { m_view = new CMView(); m_model = new CMModel(); m_control = new CMController(m_model, m_view, scene, channel); m_model.Initialise(database); m_view.Initialise(m_model); initialised = true; m_model.InitialiseDatabase(scene, databaseDir); } else { m_model.InitialiseDatabase(scene, databaseDir); m_control.RegisterNewRegion(scene); } } }
/// <summary> /// Only called by the MainLoop. /// </summary> private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) { if ((m_state & State.SHOWING_CHANGES) > 0) { foreach (Object scene in m_sceneList.Values) { m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene)scene)); } } }
/// <summary> /// Only called by the MainLoop. /// </summary> private void UndoDid(CMModel model, CMView view, UUID uuid) { if ((m_state & State.SHOWING_CHANGES) > 0) { ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); if (ent != null) { view.DisplayEntity(ent); } } }
/// <summary> /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. /// </summary> public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) { if (e.Channel != channel) { return; } if (e.Sender == null) { return; } m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); IClientAPI client = e.Sender; Scene scene = (Scene)e.Scene; string message = e.Message; string[] args = e.Message.Split(new char[] { ' ' }); ScenePresence avatar = scene.GetScenePresence(client.AgentId); if (!(m_estateModule.IsManager(avatar.UUID))) { m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); return; } switch (args[0]) { case "ci": case "commit": commit(message, scene, model, view); break; case "dm": case "diff-mode": diffmode(scene, model, view); break; case "rb": case "rollback": rollback(scene, model, view); break; case "help": m_view.DisplayHelpMenu(scene); break; default: view.SendSimChatMessage(scene, "Command not found: " + args[0]); break; } }
private void Initialize(CMModel model, CMView view, Scene scene, int channel) { lock (this) { m_estateModule = scene.RequestModuleInterface <IEstateModule>(); m_thread = new Thread(MainLoop); m_thread.Name = "Content Management"; m_thread.IsBackground = true; m_thread.Start(); ThreadTracker.Add(m_thread); m_state = State.NONE; } }
/// <summary> /// Only called by the MainLoop. /// </summary> private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) { SceneObjectGroup group = null; if ((m_state & State.SHOWING_CHANGES) > 0) { group = GetGroupByPrim(LocalId); if (group != null) { view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) } } }
/// <summary> /// Only called from within the SimChat method. /// </summary> protected void diffmode(Scene scene, CMModel model, CMView view) { System.Collections.Generic.List <Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF { view.SendSimChatMessage(scene, "Hiding all meta objects."); view.HideAllMetaEntities(); view.HideAllAuras(); view.SendSimChatMessage(scene, "Diff-mode = OFF"); m_state &= ~State.SHOWING_CHANGES; return; } else // TURN ON { if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) { view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); //Hide objects from users and Forget about them view.HideAllMetaEntities(); view.HideAllAuras(); model.DeleteAllMetaObjects(); //Recreate them from backend files foreach (Object currScene in m_sceneList.Values) { model.UpdateCMEntities((Scene)currScene); } } else if ((m_state & State.DIRTY) != 0) { view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); foreach (Scene currScene in proximitySceneList) { model.UpdateCMEntities(currScene); } } view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); foreach (Scene currScene in proximitySceneList) { model.CheckForNewEntitiesMissingAuras(currScene); } view.DisplayRecentChanges(); view.SendSimChatMessage(scene, "Diff-mode = ON"); m_state |= State.SHOWING_CHANGES; m_state &= ~State.DIRTY; } }
/// <summary> /// Only called from within the SimChat method. /// </summary> protected void commit(string message, Scene scene, CMModel model, CMView view) { System.Collections.Generic.List <Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); string[] args = message.Split(new char[] { ' ' }); char[] logMessage = { ' ' }; if (args.Length > 1) { logMessage = new char[message.Length - (args[0].Length)]; message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); } m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); foreach (Scene currScene in proximitySceneList) { model.CommitRegion(currScene, new String(logMessage)); view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); } view.SendSimChatMessage(scene, "Successfully saved all regions."); m_state |= State.DIRTY; if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES { view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); //Hide objects from users and Forget about them view.HideAllMetaEntities(); view.HideAllAuras(); model.DeleteAllMetaObjects(); //Recreate them from backend files foreach (Scene currScene in proximitySceneList) { model.UpdateCMEntities(currScene); view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); } //Display new objects to users1 view.DisplayRecentChanges(); view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); m_state &= ~(State.DIRTY); m_state |= State.SHOWING_CHANGES; } }
/// <summary> /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. /// </summary> public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) { if (e.Channel != channel) return; if (e.Sender == null) return; m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); IClientAPI client = e.Sender; Scene scene = (Scene) e.Scene; string message = e.Message; string[] args = e.Message.Split(new char[] {' '}); ScenePresence avatar = scene.GetScenePresence(client.AgentId); if (!(m_estateModule.IsManager(avatar.UUID))) { m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); return; } switch (args[0]) { case "ci": case "commit": commit(message, scene, model, view); break; case "dm": case "diff-mode": diffmode(scene, model, view); break; case "rb": case "rollback": rollback(scene, model, view); break; case "help": m_view.DisplayHelpMenu(scene); break; default: view.SendSimChatMessage(scene, "Command not found: " + args[0]); break; } }
/// <summary> /// Only called from within the SimChat method. /// </summary> protected void diffmode(Scene scene, CMModel model, CMView view) { System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF { view.SendSimChatMessage(scene, "Hiding all meta objects."); view.HideAllMetaEntities(); view.HideAllAuras(); view.SendSimChatMessage(scene, "Diff-mode = OFF"); m_state &= ~State.SHOWING_CHANGES; return; } else // TURN ON { if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) { view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); //Hide objects from users and Forget about them view.HideAllMetaEntities(); view.HideAllAuras(); model.DeleteAllMetaObjects(); //Recreate them from backend files foreach (Object currScene in m_sceneList.Values) model.UpdateCMEntities((Scene) currScene); } else if ((m_state & State.DIRTY) != 0) { view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); foreach (Scene currScene in proximitySceneList) model.UpdateCMEntities(currScene); } view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); foreach (Scene currScene in proximitySceneList) model.CheckForNewEntitiesMissingAuras(currScene); view.DisplayRecentChanges(); view.SendSimChatMessage(scene, "Diff-mode = ON"); m_state |= State.SHOWING_CHANGES; m_state &= ~State.DIRTY; } }
/// <summary> /// Only called from within the SimChat method. Hides all auras and meta entities, /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, /// then lets the view update the clients of the new objects. /// </summary> protected void rollback(Scene scene, CMModel model, CMView view) { if ((m_state & State.SHOWING_CHANGES) > 0) { view.HideAllAuras(); view.HideAllMetaEntities(); } System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); foreach (Scene currScene in proximitySceneList) model.RollbackRegion(currScene); if ((m_state & State.DIRTY) != 0) { model.DeleteAllMetaObjects(); foreach (Scene currScene in proximitySceneList) model.UpdateCMEntities(currScene); } if ((m_state & State.SHOWING_CHANGES) > 0) view.DisplayRecentChanges(); }
/// <summary> /// Only called by the MainLoop. /// </summary> private void UndoDid(CMModel model, CMView view, UUID uuid) { if ((m_state & State.SHOWING_CHANGES) > 0) { ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); if (ent != null) view.DisplayEntity(ent); } }
/// <summary> /// Only called from within the SimChat method. /// </summary> protected void commit(string message, Scene scene, CMModel model, CMView view) { System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); string[] args = message.Split(new char[] {' '}); char[] logMessage = {' '}; if (args.Length > 1) { logMessage = new char[message.Length - (args[0].Length)]; message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); } m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); foreach (Scene currScene in proximitySceneList) { model.CommitRegion(currScene, new String(logMessage)); view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); } view.SendSimChatMessage(scene, "Successfully saved all regions."); m_state |= State.DIRTY; if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES { view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); //Hide objects from users and Forget about them view.HideAllMetaEntities(); view.HideAllAuras(); model.DeleteAllMetaObjects(); //Recreate them from backend files foreach (Scene currScene in proximitySceneList) { model.UpdateCMEntities(currScene); view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); } //Display new objects to users1 view.DisplayRecentChanges(); view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); m_state &= ~(State.DIRTY); m_state |= State.SHOWING_CHANGES; } }
/// <summary> /// Only called by the MainLoop. /// </summary> private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) { if ((m_state & State.SHOWING_CHANGES) > 0) { foreach (Object scene in m_sceneList.Values) m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); } }
/// <summary> /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. /// </summary> private void ObjectDuplicated(CMModel model, CMView view, uint localId) { if ((m_state & State.SHOWING_CHANGES) > 0) view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); }
/// <summary> /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. /// </summary> /// <param name="model"> /// <see cref="CMModel"/> /// </param> /// <param name="view"> /// <see cref="CMView"/> /// </param> /// <param name="scene"> /// The first scene to keep track of. <see cref="Scene"/> /// </param> /// <param name="channel"> /// The simchat channel number to listen to for instructions <see cref="System.Int32"/> /// </param> public CMController(CMModel model, CMView view, Scene scene, int channel) { m_model = model; m_view = view; m_channel = channel; RegisterNewRegion(scene); Initialize(model, view, scene, channel); }
private void Initialize(CMModel model, CMView view, Scene scene, int channel) { lock (this) { m_estateModule = scene.RequestModuleInterface<IEstateModule>(); m_thread = new Thread(MainLoop); m_thread.Name = "Content Management"; m_thread.IsBackground = true; m_thread.Start(); ThreadTracker.Add(m_thread); m_state = State.NONE; } }
private void Initialize(CMModel model, CMView view, Scene scene, int channel) { lock (this) { m_estateModule = scene.RequestModuleInterface<IEstateModule>(); Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true); m_state = State.NONE; } }
public void Initialise(CMModel model) { m_model = model; }
public void Initialise(Scene scene, IConfigSource source) { string databaseDir = "./"; string database = "FileSystemDatabase"; int channel = 345; try { if (source.Configs["CMS"] == null) return; m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); database = source.Configs["CMS"].GetString("database", database); channel = source.Configs["CMS"].GetInt("channel", channel); if (database != "FileSystemDatabase" && database != "GitDatabase") { m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); m_enabled = false; } } catch (Exception e) { m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); m_enabled = false; } if (!m_enabled) { m_log.Info("[Content Management]: Content Management System is not Enabled."); return; } lock (this) { if (!initialised) //only init once { m_view = new CMView(); m_model = new CMModel(); m_control = new CMController(m_model, m_view, scene, channel); m_model.Initialise(database); m_view.Initialise(m_model); initialised = true; m_model.InitialiseDatabase(scene, databaseDir); } else { m_model.InitialiseDatabase(scene, databaseDir); m_control.RegisterNewRegion(scene); } } }