Add Visual Basic plugin compiling and creating support

This commit is contained in:
UnknownShadow200 2021-03-26 22:39:47 +11:00
parent 5425c0103b
commit a6a04ec92d
7 changed files with 157 additions and 89 deletions

View File

@ -64,8 +64,5 @@
<Name>MCGalaxy_</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -39,13 +39,14 @@ namespace MCGalaxy.Gui.Popups {
}
ICompiler engine = radVB.Checked ? ICompiler.VB : ICompiler.CS;
string path = engine.SourcePath(cmdName);
string path = engine.CommandPath(cmdName);
if (File.Exists(path)) {
Popup.Warning("Command already exists"); return;
}
try {
engine.CreateNew(path, cmdName);
string source = engine.GenExampleCommand(cmdName);
File.WriteAllText(path, source);
} catch (Exception ex) {
Logger.LogError(ex);
Popup.Error("Failed to generate command. Check error logs for more details.");
@ -99,8 +100,8 @@ namespace MCGalaxy.Gui.Popups {
void lstCommands_SelectedIndexChanged(object sender, EventArgs e) {
btnUnload.Enabled = lstCommands.SelectedIndex != -1;
}
void LoadCommands(Assembly assembly) {
List<Command> commands = IScripting.LoadTypes<Command>(assembly);
if (commands == null) {

View File

@ -30,22 +30,18 @@ namespace MCGalaxy.Commands.Scripting {
if (message.Length == 0) { Help(p); return; }
string[] args = message.SplitSpaces();
ICompiler engine = null;
if (args.Length == 1) {
engine = ICompiler.CS;
} else if (args[1].CaselessEq("vb")) {
engine = ICompiler.VB;
} else {
Help(p); return;
}
string language = args.Length > 1 ? args[1] : "";
ICompiler engine = ICompiler.Lookup(language, p);
if (engine == null) return;
string path = engine.SourcePath(args[0]);
string path = engine.CommandPath(args[0]);
if (File.Exists(path)) {
p.Message("File {0} already exists. Choose another name.", path); return;
}
try {
engine.CreateNew(path, args[0]);
string source = engine.GenExampleCommand(args[0]);
File.WriteAllText(path, source);
} catch (Exception ex) {
Logger.LogError("Error saving new command to " + path, ex);
p.Message("An error occurred creating the command.");

View File

@ -30,17 +30,12 @@ namespace MCGalaxy.Commands.Scripting {
public override void Use(Player p, string message, CommandData data) {
if (message.Length == 0) { Help(p); return; }
string[] args = message.SplitSpaces();
ICompiler engine = null;
if (args.Length == 1) {
engine = ICompiler.CS;
} else if (args[1].CaselessEq("vb")) {
engine = ICompiler.VB;
} else {
Help(p); return;
}
string srcPath = engine.SourcePath(args[0]);
string language = args.Length > 1 ? args[1] : "";
ICompiler engine = ICompiler.Lookup(language, p);
if (engine == null) return;
string srcPath = engine.CommandPath(args[0]);
string dstPath = IScripting.CommandPath(args[0]);
if (!File.Exists(srcPath)) {
p.Message("File &9{0} &Snot found.", srcPath); return;

View File

@ -38,25 +38,29 @@ namespace MCGalaxy.Commands.Scripting {
return;
}
string[] parts = message.SplitSpaces(2);
if (parts.Length == 1) { Help(p); return; }
if (!Formatter.ValidName(p, parts[1], "plugin")) return;
string[] args = message.SplitSpaces(3);
if (args.Length == 1) { Help(p); return; }
if (parts[0].CaselessEq("load")) {
LoadPlugin(p, parts[1]);
} else if (parts[0].CaselessEq("unload")) {
UnloadPlugin(p, parts[1]);
} else if (parts[0].CaselessEq("create")) {
CreatePlugin(p, parts[1]);
} else if (parts[0].CaselessEq("compile")) {
CompilePlugin(p, parts[1]);
string cmd = args[0], name = args[1];
if (!Formatter.ValidName(p, name, "plugin")) return;
string language = args.Length > 2 ? args[2] : "";
if (cmd.CaselessEq("load")) {
LoadPlugin(p, name);
} else if (cmd.CaselessEq("unload")) {
UnloadPlugin(p, name);
} else if (cmd.CaselessEq("create")) {
CreatePlugin(p, name, language);
} else if (cmd.CaselessEq("compile")) {
CompilePlugin(p, name, language);
} else {
Help(p);
}
}
static void CompilePlugin(Player p, string name) {
ICompiler engine = ICompiler.CS;
static void CompilePlugin(Player p, string name, string language) {
ICompiler engine = ICompiler.Lookup(language, p);
if (engine == null) return;
string srcPath = "plugins/" + name + engine.Ext;
string dstPath = IScripting.PluginPath(name);
@ -108,46 +112,18 @@ namespace MCGalaxy.Commands.Scripting {
}
}
static void CreatePlugin(Player p, string name) {
static void CreatePlugin(Player p, string name, string language) {
ICompiler engine = ICompiler.Lookup(language, p);
if (engine == null) return;
string path = engine.PluginPath(name);
p.Message("Creating a plugin example source");
string creator = p.IsSuper ? Server.Config.Name : p.name;
string syntax = pluginSrc.Replace(@"\t", "\t");
syntax = string.Format(syntax, name, creator, Server.Version);
File.WriteAllText("plugins/" + name + ".cs", syntax);
string creator = p.IsSuper ? Server.Config.Name : p.truename;
string source = engine.GenExamplePlugin(name, creator);
File.WriteAllText(path, source);
}
const string pluginSrc =
@"//This is an example plugin source!
using System;
namespace MCGalaxy
{{
\tpublic class {0} : Plugin
\t{{
\t\tpublic override string name {{ get {{ return ""{0}""; }} }}
\t\tpublic override string website {{ get {{ return ""www.example.com""; }} }}
\t\tpublic override string MCGalaxy_Version {{ get {{ return ""{2}""; }} }}
\t\tpublic override int build {{ get {{ return 100; }} }}
\t\tpublic override string welcome {{ get {{ return ""Loaded Message!""; }} }}
\t\tpublic override string creator {{ get {{ return ""{1}""; }} }}
\t\tpublic override bool LoadAtStartup {{ get {{ return true; }} }}
\t\tpublic override void Load(bool startup)
\t\t{{
\t\t\t//LOAD YOUR PLUGIN WITH EVENTS OR OTHER THINGS!
\t\t}}
\t\tpublic override void Unload(bool shutdown)
\t\t{{
\t\t\t//UNLOAD YOUR PLUGIN BY SAVING FILES OR DISPOSING OBJECTS!
\t\t}}
\t\tpublic override void Help(Player p)
\t\t{{
\t\t\t//HELP INFO!
\t\t}}
\t}}
}}";
public override void Help(Player p) {
p.Message("&T/Plugin create [name]");
p.Message("&HCreate a example .cs plugin file");

View File

@ -77,6 +77,40 @@ namespace MCGalaxy
\t\t\tp.Message(""/{0} - Does stuff. Example command."");
\t\t}}
\t}}
}}";
}
}
public override string PluginSkeleton {
get {
return @"//This is an example plugin source!
using System;
namespace MCGalaxy
{{
\tpublic class {0} : Plugin
\t{{
\t\tpublic override string name {{ get {{ return ""{0}""; }} }}
\t\tpublic override string MCGalaxy_Version {{ get {{ return ""{2}""; }} }}
\t\tpublic override int build {{ get {{ return 100; }} }}
\t\tpublic override string welcome {{ get {{ return ""Loaded Message!""; }} }}
\t\tpublic override string creator {{ get {{ return ""{1}""; }} }}
\t\tpublic override bool LoadAtStartup {{ get {{ return true; }} }}
\t\tpublic override void Load(bool startup)
\t\t{{
\t\t\t//LOAD YOUR PLUGIN WITH EVENTS OR OTHER THINGS!
\t\t}}
\t\tpublic override void Unload(bool shutdown)
\t\t{{
\t\t\t//UNLOAD YOUR PLUGIN BY SAVING FILES OR DISPOSING OBJECTS!
\t\t}}
\t\tpublic override void Help(Player p)
\t\t{{
\t\t\t//HELP INFO!
\t\t}}
\t}}
}}";
}
}
@ -154,6 +188,61 @@ Namespace MCGalaxy
\t\t\tp.Message(""/{0} - Does stuff. Example command."")
\t\tEnd Sub
\tEnd Class
End Namespace";
}
}
public override string PluginSkeleton {
get {
return @"' This is an example plugin source!
Imports System
Namespace MCGalaxy
\tPublic Class {0}
\t\tInherits Plugin
\t\tPublic Overrides ReadOnly Property name() As String
\t\t\tGet
\t\t\t\tReturn ""{0}""
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides ReadOnly Property MCGalaxy_Version() As String
\t\t\tGet
\t\t\t\tReturn ""{2}""
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides ReadOnly Property build() As Integer
\t\t\tGet
\t\t\t\tReturn 100
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides ReadOnly Property welcome() As String
\t\t\tGet
\t\t\t\tReturn ""Loaded Message!""
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides ReadOnly Property creator() As String
\t\t\tGet
\t\t\t\tReturn ""{1}""
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides ReadOnly Property LoadAtStartup() As Boolean
\t\t\tGet
\t\t\t\tReturn true
\t\t\tEnd Get
\t\t End Property
\t\tPublic Overrides Sub Load(startup As Boolean)
\t\t\t' LOAD YOUR PLUGIN WITH EVENTS OR OTHER THINGS!
\t\tEnd Sub
\t\tPublic Overrides Sub Unload(shutdown As Boolean)
\t\t\t' UNLOAD YOUR PLUGIN BY SAVING FILES OR DISPOSING OBJECTS!
\t\tEnd Sub
\t\tPublic Overrides Sub Help(p As Player)
\t\t\t' HELP INFO!
\t\tEnd Sub
\tEnd Class
End Namespace";
}
}

View File

@ -145,27 +145,41 @@ namespace MCGalaxy.Scripting {
public const string ErrorPath = "logs/errors/compiler.log";
public abstract string Ext { get; }
public abstract string CommandSkeleton { get; }
public abstract string PluginSkeleton { get; }
public string SourcePath(string cmdName) { return SourceDir + "Cmd" + cmdName + Ext; }
public string CommandPath(string name) { return SourceDir + "Cmd" + name + Ext; }
public string PluginPath(string name) { return "plugins/" + name + Ext; }
/// <summary> C# compiler instance. </summary>
public static ICompiler CS = new CSCompiler();
/// <summary> Visual Basic compiler instance. </summary>
public static ICompiler VB = new VBCompiler();
public void CreateNew(string path, string cmdName) {
cmdName = cmdName.ToLower();
public static ICompiler Lookup(string name, Player p) {
if (name.Length == 0) return CS;
if (name.CaselessEq("CS")) return CS;
if (name.CaselessEq("VB")) return VB;
string syntax = CommandSkeleton;
p.Message("&WUnknown language \"{0}\"", name);
return null;
}
static string FormatSource(string source, params string[] args) {
// Make sure we use the OS's line endings
syntax = syntax.Replace(@"\t", "\t");
syntax = syntax.Replace("\r\n", "\n");
syntax = syntax.Replace("\n", Environment.NewLine);
syntax = string.Format(syntax, cmdName.Capitalize());
using (StreamWriter sw = new StreamWriter(path)) {
sw.WriteLine(syntax);
}
source = source.Replace(@"\t", "\t");
source = source.Replace("\r\n", "\n");
source = source.Replace("\n", Environment.NewLine);
return string.Format(source, args);
}
public string GenExampleCommand(string cmdName) {
cmdName = cmdName.ToLower().Capitalize();
return FormatSource(CommandSkeleton, cmdName);
}
public string GenExamplePlugin(string plugin, string creator) {
return FormatSource(PluginSkeleton, plugin, creator, Server.Version);
}
const int maxLog = 2;