From fadd19f3140107d7c09e7a82a97dfb490146ccb9 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Sun, 30 Mar 2008 09:03:38 +0000 Subject: **Big ass update warning** * Renamed plugin console message, to send a message to a plugin, use either "plugin ", or any unrecognised message will be sent ("plugin" sends explicitly) This replaces the old "script ". * Terrain commands - "terrain " now works again. "Script terrain " does not. Many of the commands have now been reimplemented, eg load-tile. However some have new syntax. * New console command handler, you can now use things like "terrain help" or "terrain save help". See TerrainModule.cs for an example of how to use the new "Commander" class. * Commander class - advanced processing of console input and also enables a script API to be generated from registered console commands. --- OpenSim/Region/Environment/Interfaces/ICommand.cs | 16 ++ .../Environment/Interfaces/ICommandableModule.cs | 16 ++ .../Region/Environment/Interfaces/ICommander.cs | 14 ++ .../Environment/Modules/CommanderTestModule.cs | 92 +++++++ .../Modules/ModuleFramework/Commander.cs | 271 +++++++++++++++++++++ .../Modules/Terrain/FileLoaders/JPEG.cs | 10 + .../Modules/Terrain/FileLoaders/LLRAW.cs | 10 + .../Modules/Terrain/FileLoaders/RAW32.cs | 37 +++ .../Modules/Terrain/FileLoaders/Terragen.cs | 10 + .../Environment/Modules/Terrain/ITerrainLoader.cs | 1 + .../Environment/Modules/Terrain/TerrainModule.cs | 181 +++++++++++--- OpenSim/Region/Environment/Scenes/Scene.cs | 25 +- OpenSim/Region/Environment/Scenes/SceneManager.cs | 8 +- 13 files changed, 645 insertions(+), 46 deletions(-) create mode 100644 OpenSim/Region/Environment/Interfaces/ICommand.cs create mode 100644 OpenSim/Region/Environment/Interfaces/ICommandableModule.cs create mode 100644 OpenSim/Region/Environment/Interfaces/ICommander.cs create mode 100644 OpenSim/Region/Environment/Modules/CommanderTestModule.cs create mode 100644 OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs (limited to 'OpenSim/Region/Environment') diff --git a/OpenSim/Region/Environment/Interfaces/ICommand.cs b/OpenSim/Region/Environment/Interfaces/ICommand.cs new file mode 100644 index 0000000..bccd8d3 --- /dev/null +++ b/OpenSim/Region/Environment/Interfaces/ICommand.cs @@ -0,0 +1,16 @@ +using System; + +using OpenSim.Region.Environment.Modules.ModuleFramework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ICommand + { + void AddArgument(string name, string helptext, string type); + System.Collections.Generic.Dictionary Arguments { get; } + string Help { get; } + string Name { get; } + void Run(object[] args); + void ShowConsoleHelp(); + } +} diff --git a/OpenSim/Region/Environment/Interfaces/ICommandableModule.cs b/OpenSim/Region/Environment/Interfaces/ICommandableModule.cs new file mode 100644 index 0000000..31ef49b --- /dev/null +++ b/OpenSim/Region/Environment/Interfaces/ICommandableModule.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Region.Environment.Modules.ModuleFramework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ICommandableModule + { + ICommander CommandInterface + { + get; + } + } +} diff --git a/OpenSim/Region/Environment/Interfaces/ICommander.cs b/OpenSim/Region/Environment/Interfaces/ICommander.cs new file mode 100644 index 0000000..93a9956 --- /dev/null +++ b/OpenSim/Region/Environment/Interfaces/ICommander.cs @@ -0,0 +1,14 @@ +using System; + +using OpenSim.Region.Environment.Modules.ModuleFramework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ICommander + { + void ProcessConsoleCommand(string function, string[] args); + void RegisterCommand(string commandName, ICommand command); + void Run(string function, object[] args); + string GenerateRuntimeAPI(); + } +} diff --git a/OpenSim/Region/Environment/Modules/CommanderTestModule.cs b/OpenSim/Region/Environment/Modules/CommanderTestModule.cs new file mode 100644 index 0000000..555944c --- /dev/null +++ b/OpenSim/Region/Environment/Modules/CommanderTestModule.cs @@ -0,0 +1,92 @@ +/* + * 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 System; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Modules.ModuleFramework; + +namespace OpenSim.Region.Environment.Modules +{ + public class CommanderTestModule : IRegionModule, ICommandableModule + { + Commander m_commander = new Commander("CommanderTest"); + Scene m_scene; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + } + + private void InterfaceHelloWorld(Object[] args) + { + Console.WriteLine("Hello World"); + } + + public void PostInitialise() + { + Command testCommand = new Command("hello", InterfaceHelloWorld, "Says a simple debugging test string"); + testCommand.AddArgument("world", "Write world here", "string"); + + m_commander.RegisterCommand("hello", testCommand); + + // Register me + m_scene.RegisterModuleCommander("commandertest", m_commander); + } + + public void Close() + { + } + + public string Name + { + get { return "CommanderTestModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region ICommandableModule Members + + public ICommander CommandInterface + { + get { throw new NotImplementedException(); } + } + + #endregion + } +} diff --git a/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs b/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs new file mode 100644 index 0000000..a17348e --- /dev/null +++ b/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Modules.ModuleFramework +{ + /// + /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s. + /// Used for console commands and script API generation + /// + public class Command : ICommand + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Action m_command; + private string m_name; + private string m_help; + private List m_args = new List(); + + public Command(string name, Action command, string help) + { + m_name = name; + m_command = command; + m_help = help; + } + + public void AddArgument(string name, string helptext, string type) + { + m_args.Add(new CommandArgument(name, helptext, type)); + } + + public string Name + { + get { return m_name; } + } + + public string Help + { + get { return m_help; } + } + + public Dictionary Arguments + { + get + { + Dictionary tmp = new Dictionary(); + foreach (CommandArgument arg in m_args) + { + tmp.Add(arg.Name, arg.ArgumentType); + } + return tmp; + } + } + + public void ShowConsoleHelp() + { + m_log.Info("== " + Name + " =="); + m_log.Info(m_help); + m_log.Info("= Parameters ="); + foreach (CommandArgument arg in m_args) + { + m_log.Info("* " + arg.Name + " (" + arg.ArgumentType + ")"); + m_log.Info("\t" + arg.HelpText); + } + } + + public void Run(Object[] args) + { + Object[] cleanArgs = new Object[m_args.Count]; + + if (args.Length < cleanArgs.Length) + { + m_log.Error("Missing " + (cleanArgs.Length - args.Length) + " argument(s)"); + ShowConsoleHelp(); + return; + } + if (args.Length > cleanArgs.Length) + { + m_log.Error("Too many arguments for this command. Type ' help' for help."); + return; + } + + int i = 0; + foreach (Object arg in args) + { + if (string.IsNullOrEmpty(arg.ToString())) + { + m_log.Error("Empty arguments are not allowed"); + return; + } + try + { + switch (m_args[i].ArgumentType) + { + case "String": + m_args[i].ArgumentValue = arg.ToString(); + break; + case "Integer": + m_args[i].ArgumentValue = Int32.Parse(arg.ToString()); + break; + case "Double": + m_args[i].ArgumentValue = Double.Parse(arg.ToString()); + break; + case "Boolean": + m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); + break; + default: + m_log.Error("Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); + break; + } + } + catch (FormatException) + { + m_log.Error("Argument number " + (i + 1) + + " (" + m_args[i].Name + ") must be a valid " + + m_args[i].ArgumentType.ToLower() + "."); + } + cleanArgs[i] = m_args[i].ArgumentValue; + + i++; + } + + m_command.Invoke(cleanArgs); + } + } + + /// + /// A single command argument, contains name, type and at runtime, value. + /// + public class CommandArgument + { + private string m_name; + private string m_help; + private string m_type; + private Object m_val; + + public CommandArgument(string name, string help, string type) + { + m_name = name; + m_help = help; + m_type = type; + } + + public string Name + { + get { return m_name; } + } + + public string HelpText + { + get { return m_help; } + } + + public string ArgumentType + { + get { return m_type; } + } + + public Object ArgumentValue + { + get { return m_val; } + set { m_val = value; } + } + } + + /// + /// A class to enable modules to register console and script commands, which enforces typing and valid input. + /// + public class Commander : ICommander + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private Dictionary m_commands = new Dictionary(); + private string m_name; + + public Commander(string name) + { + m_name = name; + } + + public void RegisterCommand(string commandName, ICommand command) + { + m_commands[commandName] = command; + } + + void ShowConsoleHelp() + { + m_log.Info("===" + m_name + "==="); + foreach (ICommand com in m_commands.Values) + { + m_log.Info("* " + com.Name + " - " + com.Help); + } + } + + string EscapeRuntimeAPICommand(string command) + { + command = command.Replace('-', '_'); + StringBuilder tmp = new StringBuilder(command); + tmp[0] = tmp[0].ToString().ToUpper().ToCharArray()[0]; + + return tmp.ToString(); + } + + /// + /// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands + /// + /// Returns C# source code to create a binding + public string GenerateRuntimeAPI() + { + string classSrc = "\n\tpublic class " + m_name + " {\n"; + foreach (ICommand com in m_commands.Values) + { + classSrc += "\tpublic void " + EscapeRuntimeAPICommand(com.Name) + "( "; + foreach (KeyValuePair arg in com.Arguments) + { + classSrc += arg.Value + " " + Framework.Util.Md5Hash(arg.Key) + ","; + } + classSrc = classSrc.Remove(classSrc.Length - 1); // Delete the last comma + classSrc += " )\n\t{\n"; + classSrc += "\t\tObject[] args = new Object[" + com.Arguments.Count.ToString() + "];\n"; + int i = 0; + foreach (KeyValuePair arg in com.Arguments) + { + classSrc += "\t\targs[" + i.ToString() + "] = " + Framework.Util.Md5Hash(arg.Key) + " " + ";\n"; + i++; + } + classSrc += "\t\tGetCommander(\"" + m_name + "\").Run(\"" + com.Name + "\", args);\n"; + classSrc += "\t}\n"; + } + classSrc += "}\n"; + + return classSrc; + } + + /// + /// Runs a specified function with attached arguments + /// *** DO NOT CALL DIRECTLY. *** + /// Call ProcessConsoleCommand instead if handling human input. + /// + /// The function name to call + /// The function parameters + public void Run(string function, object[] args) + { + m_commands[function].Run(args); + } + + public void ProcessConsoleCommand(string function, string[] args) + { + if (m_commands.ContainsKey(function)) + { + if (args[0] == "help") + { + m_commands[function].ShowConsoleHelp(); + } + else + { + m_commands[function].Run(args); + } + } + else + { + if (function != "help") + m_log.Error("Invalid command - No such command exists"); + if (function == "api") + m_log.Info(GenerateRuntimeAPI()); + ShowConsoleHelp(); + } + } + } +} diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs index f2bdde7..d6430cd 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs @@ -41,6 +41,16 @@ namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders throw new NotImplementedException(); } + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + + public override string ToString() + { + return "JPEG"; + } + private Bitmap CreateBitmapFromMap(ITerrainChannel map) { Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs index 2d7d94f..7436dc5 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs @@ -58,6 +58,16 @@ namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders return retval; } + public override string ToString() + { + return "LL/SL RAW"; + } + + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + public void SaveFile(string filename, ITerrainChannel map) { FileInfo file = new FileInfo(filename); diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs index ba430b7..fc81376 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs @@ -57,6 +57,43 @@ namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders return retval; } + public override string ToString() + { + return "RAW32"; + } + + public ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) + { + TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + // Advance to our section of the file + if (fileStartY * sectionHeight > 0) + bs.ReadBytes(fileStartY * sectionHeight); + + int x, y; + for (y = 0; y < retval.Height; y++) + { + // Advance the stream if we aren't at the start of the section in the file + if (fileStartX * sectionWidth > 0) + bs.ReadBytes(fileStartX * sectionHeight); + + for (x = 0; x < retval.Width; x++) + { + // Read a strip and continue + retval[x, y] = bs.ReadSingle(); + } + } + + bs.Close(); + s.Close(); + + return retval; + } + public void SaveFile(string filename, ITerrainChannel map) { FileInfo file = new FileInfo(filename); diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs index e136397..6a3c354 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs @@ -107,6 +107,16 @@ namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders throw new NotImplementedException(); } + public override string ToString() + { + return "Terragen"; + } + + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + #endregion } } diff --git a/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs index 9b713f5..2c391df 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs @@ -32,6 +32,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain public interface ITerrainLoader { ITerrainChannel LoadFile(string filename); + ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight); void SaveFile(string filename, ITerrainChannel map); } } diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs index 742ea5b..745118b 100644 --- a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs +++ b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs @@ -33,11 +33,12 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Modules.ModuleFramework; namespace OpenSim.Region.Environment.Modules.Terrain { - public class TerrainModule : IRegionModule , ITerrainTemp + public class TerrainModule : IRegionModule , ITerrainTemp, ICommandableModule { public enum StandardTerrainEffects : byte { @@ -51,6 +52,8 @@ namespace OpenSim.Region.Environment.Modules.Terrain private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private Commander m_commander = new Commander("Terrain"); + private Dictionary m_painteffects = new Dictionary(); private Dictionary m_floodeffects = @@ -109,7 +112,44 @@ namespace OpenSim.Region.Environment.Modules.Terrain { lock (m_scene) { - ITerrainChannel channel = loader.Value.LoadFile(filename); + try + { + ITerrainChannel channel = loader.Value.LoadFile(filename); + m_scene.Heightmap = channel; + m_channel = channel; + UpdateRevertMap(); + } + catch (NotImplementedException) + { + m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value.ToString() + " parser does not support file loading. (May be save only)"); + return; + } + catch (System.IO.FileNotFoundException) + { + m_log.Error("[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); + return; + } + } + m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); + return; + } + } + m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader availible for that format."); + } + + public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) + { + fileStartX -= (int)m_scene.RegionInfo.RegionLocX; + fileStartY -= (int)m_scene.RegionInfo.RegionLocY; + + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + lock (m_scene) + { + ITerrainChannel channel = loader.Value.LoadFile(filename, fileStartX, fileStartY, + fileWidth, fileHeight, (int)Constants.RegionSize, (int)Constants.RegionSize); m_scene.Heightmap = channel; m_channel = channel; UpdateRevertMap(); @@ -177,46 +217,101 @@ namespace OpenSim.Region.Environment.Modules.Terrain } } - void EventManager_OnPluginConsole(string[] args) + #region Console Commands + + private void InterfaceLoadFile(Object[] args) { - if (args[0] == "terrain") + LoadFromFile((string)args[0]); + } + + private void InterfaceLoadTileFile(Object[] args) + { + LoadFromFile((string)args[0], + (int)args[1], + (int)args[2], + (int)args[3], + (int)args[4]); + } + + private void InterfaceSaveFile(Object[] args) + { + SaveToFile((string)args[0]); + } + + private void InterfaceFillTerrain(Object[] args) + { + int x, y; + + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] = (double)args[0]; + SendUpdatedLayerData(); + } + + private void InterfaceEnableExperimentalBrushes(Object[] args) + { + if ((bool)args[0]) { - string command = args[1]; - string param = args[2]; + m_painteffects[StandardTerrainEffects.Revert] = new PaintBrushes.WeatherSphere(); + m_painteffects[StandardTerrainEffects.Flatten] = new PaintBrushes.OlsenSphere(); + m_painteffects[StandardTerrainEffects.Smooth] = new PaintBrushes.ErodeSphere(); + } + else + { + InstallDefaultEffects(); + } + } - int x, y; + private void InstallInterfaces() + { + // Load / Save + string supportedFileExtensions = ""; + foreach (KeyValuePair loader in m_loaders) + supportedFileExtensions += " " + loader.Key + " (" + loader.Value.ToString() + ")"; + + Command loadFromFileCommand = new Command("load", InterfaceLoadFile, "Loads a terrain from a specified file."); + loadFromFileCommand.AddArgument("filename", "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + supportedFileExtensions, "String"); + + Command saveToFileCommand = new Command("save", InterfaceSaveFile, "Saves the current heightmap to a specified file."); + saveToFileCommand.AddArgument("filename", "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " + supportedFileExtensions, "String"); + + Command loadFromTileCommand = new Command("load-tile", InterfaceLoadTileFile, "Loads a terrain from a section of a larger file."); + loadFromTileCommand.AddArgument("filename", "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + supportedFileExtensions, "String"); + loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); + loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); + loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", "Integer"); + loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", "Integer"); + + // Terrain adjustments + Command fillRegionCommand = new Command("fill", InterfaceFillTerrain, "Fills the current heightmap with a specified value."); + fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.", "Double"); + + // Brushes + Command experimentalBrushesCommand = new Command("newbrushes", InterfaceEnableExperimentalBrushes, "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time."); + experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean"); + + m_commander.RegisterCommand("load", loadFromFileCommand); + m_commander.RegisterCommand("load-tile", loadFromTileCommand); + m_commander.RegisterCommand("save", saveToFileCommand); + m_commander.RegisterCommand("fill", fillRegionCommand); + m_commander.RegisterCommand("newbrushes", experimentalBrushesCommand); + + // Add this to our scene so scripts can call these functions + //TMPm_scene.RegisterModuleCommander("Terrain", m_commander); + } - switch (command) - { - case "load": - LoadFromFile(param); - SendUpdatedLayerData(); - break; - case "save": - SaveToFile(param); - break; - case "fill": - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] = Double.Parse(param); - SendUpdatedLayerData(); - break; - case "newbrushes": - if (Boolean.Parse(param)) - { - m_painteffects[StandardTerrainEffects.Revert] = new PaintBrushes.WeatherSphere(); - m_painteffects[StandardTerrainEffects.Flatten] = new PaintBrushes.OlsenSphere(); - m_painteffects[StandardTerrainEffects.Smooth] = new PaintBrushes.ErodeSphere(); - } - else - { - InstallDefaultEffects(); - } - break; - default: - m_log.Warn("Unknown terrain command."); - break; - } + #endregion + + void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "terrain") + { + string[] tmpArgs = new string[args.Length - 2]; + int i = 0; + for (i = 2; i < args.Length; i++) + tmpArgs[i - 2] = args[i]; + + m_commander.ProcessConsoleCommand(args[1], tmpArgs); } } @@ -363,6 +458,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain public void PostInitialise() { InstallDefaultEffects(); + InstallInterfaces(); } public void Close() @@ -378,5 +474,14 @@ namespace OpenSim.Region.Environment.Modules.Terrain { get { return false; } } + + #region ICommandable Members + + public ICommander CommandInterface + { + get { return m_commander; } + } + + #endregion } } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 819815b..2f277f9 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -40,10 +40,8 @@ using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Servers; using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Modules; using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Terrain; using Caps = OpenSim.Region.Capabilities.Caps; using Image = System.Drawing.Image; using Timer = System.Timers.Timer; @@ -75,7 +73,6 @@ namespace OpenSim.Region.Environment.Scenes private readonly Mutex _primAllocateMutex = new Mutex(false); private int m_timePhase = 24; - private int m_timeUpdateCount; private readonly Mutex updateLock; public bool m_physicalPrim; @@ -104,6 +101,7 @@ namespace OpenSim.Region.Environment.Scenes protected Dictionary Modules = new Dictionary(); public Dictionary ModuleInterfaces = new Dictionary(); protected Dictionary ModuleAPIMethods = new Dictionary(); + public Dictionary m_moduleCommanders = new Dictionary(); //API module interfaces @@ -1949,6 +1947,27 @@ namespace OpenSim.Region.Environment.Scenes } } + public void RegisterModuleCommander(string name, ICommander commander) + { + lock (m_moduleCommanders) + { + m_moduleCommanders.Add(name, commander); + } + } + + public ICommander GetCommander(string name) + { + lock (m_moduleCommanders) + { + return m_moduleCommanders[name]; + } + } + + public Dictionary GetCommanders() + { + return m_moduleCommanders; + } + /// /// /// diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs index ec72207..62994df 100644 --- a/OpenSim/Region/Environment/Scenes/SceneManager.cs +++ b/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -175,16 +175,14 @@ namespace OpenSim.Region.Environment.Scenes CurrentOrFirstScene.LoadPrimsFromXml2(filename); } + [Obsolete("TODO: Remove this warning by 0.7")] public bool RunTerrainCmdOnCurrentScene(string[] cmdparams, ref string result) { - m_log.Warn("Old terrain commands format has been deprecated."); - m_log.Warn("Please enter 'script terrain' rather than 'terrain'."); - m_log.Warn("FOR EXAMPLE: script terrain fill 25"); - + m_log.Warn("DEPRECIATED: The terrain engine has been replaced with a new terrain plugin module. Please type 'plugin terrain help' for new commands."); return false; } - public void SendCommandToCurrentSceneScripts(string[] cmdparams) + public void SendCommandToPluginModules(string[] cmdparams) { ForEachCurrentScene(delegate(Scene scene) { scene.SendCommandToPlugins(cmdparams); }); } -- cgit v1.1