document scripting
This commit is contained in:
parent
fc65636513
commit
a1fa66f787
1 changed files with 234 additions and 17 deletions
|
@ -38,31 +38,65 @@ using System.Net;
|
|||
|
||||
namespace ShiftOS.Engine.Scripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Brings some C# goodies to the Lua system.
|
||||
/// </summary>
|
||||
[Exposed("strutils")]
|
||||
public class StringUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if a string ends with a specified string.
|
||||
/// </summary>
|
||||
/// <param name="operand">The string to operate on</param>
|
||||
/// <param name="value">The string to check for</param>
|
||||
/// <returns>Whether <paramref name="operand"/> ends with <paramref name="value"/>.</returns>
|
||||
public bool endswith(string operand, string value)
|
||||
{
|
||||
return operand.EndsWith(value);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a string starts with a specified string.
|
||||
/// </summary>
|
||||
/// <param name="operand">The string to operate on</param>
|
||||
/// <param name="value">The string to check for</param>
|
||||
/// <returns>Whether <paramref name="operand"/> starts with <paramref name="value"/>.</returns>
|
||||
public bool startswith(string operand, string value)
|
||||
{
|
||||
return operand.StartsWith(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a string contains a specified string.
|
||||
/// </summary>
|
||||
/// <param name="operand">The string to operate on</param>
|
||||
/// <param name="value">The string to check for</param>
|
||||
/// <returns>Whether <paramref name="operand"/> contains <paramref name="value"/>.</returns>
|
||||
public bool contains(string operand, string value)
|
||||
{
|
||||
return operand.Contains(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DynamicLua wrapper for the ShiftOS engine.
|
||||
/// </summary>
|
||||
public class LuaInterpreter
|
||||
{
|
||||
/// <summary>
|
||||
/// The DynamicLua backend.
|
||||
/// </summary>
|
||||
public dynamic Lua = new DynamicLua.DynamicLua();
|
||||
|
||||
/// <summary>
|
||||
/// Boolean representing whether the script is running.
|
||||
/// </summary>
|
||||
public bool Running = true;
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor for the <see cref="LuaInterpreter"/> class.
|
||||
/// </summary>
|
||||
static LuaInterpreter()
|
||||
{
|
||||
ServerManager.MessageReceived += (msg) =>
|
||||
|
@ -83,12 +117,21 @@ namespace ShiftOS.Engine.Scripting
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a .SFT representation of a Lua script.
|
||||
/// </summary>
|
||||
/// <param name="lua">The Lua code to convert</param>
|
||||
/// <returns>Base64 SFT representation.</returns>
|
||||
public static string CreateSft(string lua)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(lua);
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run a compressed .SFT file as a lua script.
|
||||
/// </summary>
|
||||
/// <param name="sft">The .sft file to run.</param>
|
||||
public static void RunSft(string sft)
|
||||
{
|
||||
if (Utils.FileExists(sft))
|
||||
|
@ -108,8 +151,14 @@ namespace ShiftOS.Engine.Scripting
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current working directory of the script.
|
||||
/// </summary>
|
||||
public static string CurrentDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="LuaInterpreter"/> class.
|
||||
/// </summary>
|
||||
public LuaInterpreter()
|
||||
{
|
||||
Lua(@"function totable(clrlist)
|
||||
|
@ -128,6 +177,9 @@ end");
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the engine, frontend, and all mods for Lua-exposed classes and functions.
|
||||
/// </summary>
|
||||
public void SetupAPIs()
|
||||
{
|
||||
Lua.currentdir = (string.IsNullOrWhiteSpace(CurrentDirectory)) ? "0:" : CurrentDirectory;
|
||||
|
@ -233,7 +285,10 @@ end");
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified file as an uncompressed Lua script.
|
||||
/// </summary>
|
||||
/// <param name="file">The file to execute.</param>
|
||||
public void ExecuteFile(string file)
|
||||
{
|
||||
if (Utils.FileExists(file))
|
||||
|
@ -247,6 +302,10 @@ end");
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified string as a Lua script.
|
||||
/// </summary>
|
||||
/// <param name="lua">The Lua code to execute.</param>
|
||||
public void Execute(string lua)
|
||||
{
|
||||
try
|
||||
|
@ -279,24 +338,46 @@ end");
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lua functions for .sft files.
|
||||
/// </summary>
|
||||
[Exposed("sft")]
|
||||
public class SFTFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Make a .sft file from a lua code string
|
||||
/// </summary>
|
||||
/// <param name="lua">The Lua code</param>
|
||||
/// <returns>The resulting .sft string</returns>
|
||||
public string make(string lua)
|
||||
{
|
||||
return LuaInterpreter.CreateSft(lua);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a .sft string and save to a specified file.
|
||||
/// </summary>
|
||||
/// <param name="lua">The Lua code to compress</param>
|
||||
/// <param name="outpath">The path to save the compressed .sft file to.</param>
|
||||
public void makefile(string lua, string outpath)
|
||||
{
|
||||
Utils.WriteAllText(outpath, make(lua));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run a compressed .sft file in the <see cref="LuaInterpreter"/>.
|
||||
/// </summary>
|
||||
/// <param name="inpath">The .sft file to run.</param>
|
||||
public void run(string inpath)
|
||||
{
|
||||
LuaInterpreter.RunSft(inpath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified .sft file and decompresses to it's Lua form.
|
||||
/// </summary>
|
||||
/// <param name="sft">The .sft file to uncompress</param>
|
||||
/// <returns>The resulting Lua code.</returns>
|
||||
public string unmake(string sft)
|
||||
{
|
||||
if (Utils.FileExists(sft))
|
||||
|
@ -310,9 +391,17 @@ end");
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Network functions for Lua.
|
||||
/// </summary>
|
||||
[Exposed("net")]
|
||||
public class NetFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Submit a GET request to the specified URL.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to open</param>
|
||||
/// <returns>The result from the server</returns>
|
||||
public string get(string url)
|
||||
{
|
||||
return new WebClient().DownloadString(url);
|
||||
|
@ -320,26 +409,48 @@ end");
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Console functions for Lua.
|
||||
/// </summary>
|
||||
[Exposed("console")]
|
||||
public class ConsoleFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Write text to the console.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to write.</param>
|
||||
public void write(dynamic text)
|
||||
{
|
||||
Console.Write(text.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write text to the console, followed by a new line.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to write.</param>
|
||||
public void writeLine(dynamic text)
|
||||
{
|
||||
Console.WriteLine(text.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The main ShiftOS API.
|
||||
/// </summary>
|
||||
[Exposed("sos")]
|
||||
public class SystemFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the user's Codepoints from the save file.
|
||||
/// </summary>
|
||||
/// <returns>The user's Codepoints.</returns>
|
||||
public long getCodepoints() { return SaveSystem.CurrentSave.Codepoints; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Run a command in the Terminal.
|
||||
/// </summary>
|
||||
/// <param name="cmd">The command to run, using regular ShiftOS syntax.</param>
|
||||
/// <returns>Whether the command was found and ran.</returns>
|
||||
public bool runCommand(string cmd)
|
||||
{
|
||||
var args = TerminalBackend.GetArgs(ref cmd);
|
||||
|
@ -347,6 +458,10 @@ end");
|
|||
return TerminalBackend.RunClient(cmd, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified amount of Codepoints to the save flie.
|
||||
/// </summary>
|
||||
/// <param name="cp">The codepoints to add.</param>
|
||||
public void addCodepoints(int cp)
|
||||
{
|
||||
if (cp > 100 || cp <= 0)
|
||||
|
@ -361,128 +476,227 @@ end");
|
|||
}
|
||||
}
|
||||
|
||||
[Exposed("mud")]
|
||||
public class MUDFunctions
|
||||
{
|
||||
public void sendDiagnostic(string src, string cat, object val)
|
||||
{
|
||||
ServerManager.SendMessage("diag_log", $"[{src}] <{cat}>: {val}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User information API.
|
||||
/// </summary>
|
||||
[Exposed("userinfo")]
|
||||
public class UserInfoFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user name of the currently logged in user.
|
||||
/// </summary>
|
||||
/// <returns>The user's username.</returns>
|
||||
public string getUsername()
|
||||
{
|
||||
return SaveSystem.CurrentSave.Username;
|
||||
return SaveSystem.CurrentUser.Username;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's system name.
|
||||
/// </summary>
|
||||
/// <returns>The user's system name.</returns>
|
||||
public string getSysname()
|
||||
{
|
||||
return SaveSystem.CurrentSave.SystemName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user's ShiftOS email (username@sysname).
|
||||
/// </summary>
|
||||
/// <returns>The user's email.</returns>
|
||||
public string getEmail()
|
||||
{
|
||||
return getUsername() + "@" + getSysname();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Infobox API for Lua.
|
||||
/// </summary>
|
||||
[Exposed("infobox")]
|
||||
public class InfoboxFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Show a message to the user in an Infobox.
|
||||
/// </summary>
|
||||
/// <param name="title">The title of the Infobox</param>
|
||||
/// <param name="message">The infobox's message</param>
|
||||
/// <param name="callback">A function to run when the user clicks "OK"</param>
|
||||
public void show(string title, string message, Action callback = null)
|
||||
{
|
||||
Infobox.Show(title, message, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ask a simple yes/no question to the user using an Infobox.
|
||||
/// </summary>
|
||||
/// <param name="title">The title of the Infobox</param>
|
||||
/// <param name="message">The infobox's message</param>
|
||||
/// <param name="callback">A function to run when they choose an option. The boolean argument will be true if the user clicks Yes, and false if they click No.</param>
|
||||
public void question(string title, string message, Action<bool> callback)
|
||||
{
|
||||
Infobox.PromptYesNo(title, message, callback);
|
||||
}
|
||||
|
||||
public void input(string title, string message, Action<string> callback)
|
||||
/// <summary>
|
||||
/// Prompt the user for text using an Infobox.
|
||||
/// </summary>
|
||||
/// <param name="title">The infobox's title</param>
|
||||
/// <param name="message">The infobox's message</param>
|
||||
/// <param name="callback">A function to run when the user clicks "OK". The string value is the text entered by the user.</param>
|
||||
/// <param name="isPassword">Whether the text box should hide its characters as if it were a password box.</param>
|
||||
public void input(string title, string message, Action<string> callback, bool isPassword = false)
|
||||
{
|
||||
Infobox.PromptText(title, message, callback);
|
||||
Infobox.PromptText(title, message, callback, isPassword);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File Skimmer API for Lua.
|
||||
/// </summary>
|
||||
[Exposed("fileskimmer")]
|
||||
public class FileSkimmerFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a File Skimmer "Open File" dialog.
|
||||
/// </summary>
|
||||
/// <param name="extensions">Semicolon-separated list of file extensions that the opener should let through the filter.</param>
|
||||
/// <param name="callback">Function to be called when the user chooses a file. The string value is the file's path.</param>
|
||||
public void openFile(string extensions, Action<string> callback)
|
||||
{
|
||||
FileSkimmerBackend.GetFile(extensions.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries), FileOpenerStyle.Open, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a File Skimmer "Save File" dialog.
|
||||
/// </summary>
|
||||
/// <param name="extensions">Semicolon-separated list of file extensions that the opener should let through the filter.</param>
|
||||
/// <param name="callback">Function to be called when the user chooses a file. The string value is the file's path.</param>
|
||||
public void saveFile(string extensions, Action<string> callback)
|
||||
{
|
||||
FileSkimmerBackend.GetFile(extensions.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries), FileOpenerStyle.Save, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ShiftFS API for Lua.
|
||||
/// </summary>
|
||||
[Exposed("fs")]
|
||||
public class ShiftFSFunctions
|
||||
{
|
||||
/// <summary>
|
||||
/// Read all text in a file to a string.
|
||||
/// </summary>
|
||||
/// <param name="path">The file path to read</param>
|
||||
/// <returns>The string containing the file's contents.</returns>
|
||||
public string readAllText(string path)
|
||||
{
|
||||
return Utils.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy a file from one place to another.
|
||||
/// </summary>
|
||||
/// <param name="i">The source file</param>
|
||||
/// <param name="o">The destination path</param>
|
||||
public void copy(string i, string o)
|
||||
{
|
||||
Utils.WriteAllBytes(o, Utils.ReadAllBytes(i));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all files in the specified directory.
|
||||
/// </summary>
|
||||
/// <param name="dir">The directory to search</param>
|
||||
/// <returns>A string array containing all file paths in the directory.</returns>
|
||||
public string[] getFiles(string dir)
|
||||
{
|
||||
return Utils.GetFiles(dir);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all directories inside a directory.
|
||||
/// </summary>
|
||||
/// <param name="dir">The directory to search</param>
|
||||
/// <returns>A string array containing all directory paths in the directory.</returns>
|
||||
public string[] getDirectories(string dir)
|
||||
{
|
||||
return Utils.GetDirectories(dir);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the binary contents of a file to a <see cref="byte"/> array.
|
||||
/// </summary>
|
||||
/// <param name="path">The file path to read.</param>
|
||||
/// <returns>The resulting byte array.</returns>
|
||||
public byte[] readAllBytes(string path)
|
||||
{
|
||||
return Utils.ReadAllBytes(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified text to a file.
|
||||
/// </summary>
|
||||
/// <param name="path">The file path</param>
|
||||
/// <param name="contents">The text to write</param>
|
||||
public void writeAllText(string path, string contents)
|
||||
{
|
||||
Utils.WriteAllText(path, contents);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified binary data to a file.
|
||||
/// </summary>
|
||||
/// <param name="path">The file path.</param>
|
||||
/// <param name="contents">The binary data</param>
|
||||
public void writeAllBytes(string path, byte[] contents)
|
||||
{
|
||||
Utils.WriteAllBytes(path, contents);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified path exists and is a file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to search</param>
|
||||
/// <returns>The result of the search.</returns>
|
||||
public bool fileExists(string path)
|
||||
{
|
||||
return Utils.FileExists(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified path exists and is a directory.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to search</param>
|
||||
/// <returns>The result of the search.</returns>
|
||||
public bool directoryExists(string path)
|
||||
{
|
||||
return Utils.DirectoryExists(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the file/directory at the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to delete</param>
|
||||
public void delete(string path)
|
||||
{
|
||||
Utils.Delete(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new directory at the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to create</param>
|
||||
public void createDirectory(string path)
|
||||
{
|
||||
Utils.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Marks the specified class as a Lua API object.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class ExposedAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -494,6 +708,9 @@ end");
|
|||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The API object's name
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue