diff --git a/SlipeServer.Console/Program.cs b/SlipeServer.Console/Program.cs
index 7d2036c9..f9d87e97 100644
--- a/SlipeServer.Console/Program.cs
+++ b/SlipeServer.Console/Program.cs
@@ -22,6 +22,7 @@
using System.IO;
using System.Threading;
using SlipeServer.Example;
+using SlipeServer.Scripting.Luau;
namespace SlipeServer.Console;
@@ -108,6 +109,7 @@ public Program(string[] args)
});
builder.AddLua();
+ builder.AddLuauTranspiler();
builder.AddPhysics();
builder.AddParachuteResource();
builder.AddLuaControllers();
diff --git a/SlipeServer.Console/test.lua b/SlipeServer.Console/test.lua
index 92ea066e..54472bef 100644
--- a/SlipeServer.Console/test.lua
+++ b/SlipeServer.Console/test.lua
@@ -1,4 +1,10 @@
-if(isSlipeServer)then
+type Point = { x: number, y: number }
+
+local p: Point = { x = 1, y = 2 }
+
+print("Point with luau:", p.x, p.y);
+
+if(isSlipeServer)then
local object = createObject(321, 5, 5, 5)
setElementPosition(object, 50, 50, 250)
setElementRotation(object, 180, 180, 90)
diff --git a/SlipeServer.Example/SlipeServer.Example.csproj b/SlipeServer.Example/SlipeServer.Example.csproj
index ad69586e..d78e26fa 100644
--- a/SlipeServer.Example/SlipeServer.Example.csproj
+++ b/SlipeServer.Example/SlipeServer.Example.csproj
@@ -10,6 +10,7 @@
+
diff --git a/SlipeServer.Lua/LuaService.cs b/SlipeServer.Lua/LuaService.cs
index 10e0f464..c5b28b5c 100644
--- a/SlipeServer.Lua/LuaService.cs
+++ b/SlipeServer.Lua/LuaService.cs
@@ -18,15 +18,17 @@ public class LuaService
private readonly MtaServer server;
private readonly ILogger logger;
private readonly RootElement root;
+ private readonly ScriptTransformationPipeline scriptTransformationPipeline;
private readonly Dictionary scripts = [];
private readonly Dictionary methods = [];
private readonly LuaTranslator translator = new();
- public LuaService(MtaServer server, ILogger logger, RootElement root)
+ public LuaService(MtaServer server, ILogger logger, RootElement root, ScriptTransformationPipeline scriptTransformationPipeline)
{
this.server = server;
this.logger = logger;
this.root = root;
+ this.scriptTransformationPipeline = scriptTransformationPipeline;
}
public void LoadDefinitions(object methodSet)
@@ -132,7 +134,10 @@ public void LoadScript(string identifier, string code)
LoadGlobals(script);
LoadDefinitions(script);
- script.DoString(code, codeFriendlyName: identifier);
+ using var ms = new MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(code));
+ var stream = this.scriptTransformationPipeline.Transform(ms, "lua");
+
+ script.DoStream(stream, codeFriendlyName: identifier);
}
public void LoadScript(string identifier, string[] codes)
diff --git a/SlipeServer.Lua/LuaServiceCollectionExtensions.cs b/SlipeServer.Lua/LuaServiceCollectionExtensions.cs
index 9defe844..bf4cce3d 100644
--- a/SlipeServer.Lua/LuaServiceCollectionExtensions.cs
+++ b/SlipeServer.Lua/LuaServiceCollectionExtensions.cs
@@ -7,14 +7,13 @@ public static class LuaServiceCollectionExtensions
{
public static void AddLua(this IServiceCollection services)
{
- services.AddSingleton();
- services.AddSingleton();
+ services.AddScripting();
services.AddSingleton();
}
public static void AddLua(this IServiceCollection services) where T : class, IScriptEventRuntime
{
- services.AddSingleton();
+ services.AddScripting();
services.AddSingleton();
}
}
diff --git a/SlipeServer.Luau/LuauToLuaTransform.cs b/SlipeServer.Luau/LuauToLuaTransform.cs
new file mode 100644
index 00000000..8e79ac28
--- /dev/null
+++ b/SlipeServer.Luau/LuauToLuaTransform.cs
@@ -0,0 +1,42 @@
+using System.Text;
+using Loretta.CodeAnalysis;
+using Loretta.CodeAnalysis.Lua;
+using Loretta.CodeAnalysis.Lua.Syntax;
+using Loretta.CodeAnalysis.Text;
+
+namespace SlipeServer.Scripting.Luau;
+
+internal sealed class LuauToLuaTransform : IScriptTransform
+{
+ public Stream Transform(Stream data, string lang)
+ {
+ if (lang != "lua")
+ return data;
+
+ SourceText sourceText = SourceText.From(data, Encoding.UTF8);
+
+ var syntaxTree = LuaSyntaxTree.ParseText(sourceText, options: new LuaParseOptions(LuaSyntaxOptions.Luau), path: "script.lua");
+
+ var root = syntaxTree.GetRoot();
+
+ var rewriter = new TypeAnnotationRemover();
+ var strippedRoot = rewriter.Visit(root);
+
+ var outData = new MemoryStream();
+ var writer = new StreamWriter(outData);
+ strippedRoot.WriteTo(writer);
+ writer.Flush();
+ return outData;
+ }
+
+ class TypeAnnotationRemover : LuaSyntaxRewriter
+ {
+ public override SyntaxNode? Visit(SyntaxNode? node)
+ {
+ if (node is TypeDeclarationStatementSyntax or TypeBindingSyntax)
+ return null;
+
+ return base.Visit(node);
+ }
+ }
+}
diff --git a/SlipeServer.Luau/ServerBuilderExtensions.cs b/SlipeServer.Luau/ServerBuilderExtensions.cs
new file mode 100644
index 00000000..7e79d431
--- /dev/null
+++ b/SlipeServer.Luau/ServerBuilderExtensions.cs
@@ -0,0 +1,16 @@
+using SlipeServer.Server.ServerBuilders;
+
+namespace SlipeServer.Scripting.Luau;
+
+public static class ServerBuilderExtensions
+{
+ public static ServerBuilder AddLuauTranspiler(this ServerBuilder builder)
+ {
+ builder.ConfigureServices(services =>
+ {
+ services.AddLuauTranspiler();
+ });
+
+ return builder;
+ }
+}
diff --git a/SlipeServer.Luau/ServiceCollectionExtensions.cs b/SlipeServer.Luau/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..4ae4946c
--- /dev/null
+++ b/SlipeServer.Luau/ServiceCollectionExtensions.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace SlipeServer.Scripting.Luau;
+
+public static class ServiceCollectionExtensions
+{
+ public static IServiceCollection AddLuauTranspiler(this IServiceCollection services)
+ {
+ services.AddSingleton();
+ return services;
+ }
+}
diff --git a/SlipeServer.Luau/SlipeServer.Luau.csproj b/SlipeServer.Luau/SlipeServer.Luau.csproj
new file mode 100644
index 00000000..3b9e7e84
--- /dev/null
+++ b/SlipeServer.Luau/SlipeServer.Luau.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlipeServer.Scripting/ScriptTransformationPipeline.cs b/SlipeServer.Scripting/ScriptTransformationPipeline.cs
new file mode 100644
index 00000000..95729a04
--- /dev/null
+++ b/SlipeServer.Scripting/ScriptTransformationPipeline.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace SlipeServer.Scripting;
+
+public interface IScriptTransform
+{
+ Stream Transform(Stream data, string lang);
+}
+
+public sealed class ScriptTransformationPipeline
+{
+ private readonly List scriptTransforms;
+
+ public ScriptTransformationPipeline(IEnumerable scriptTransforms)
+ {
+ this.scriptTransforms = scriptTransforms.ToList();
+ }
+
+ public void Add(IScriptTransform scriptTransform)
+ {
+ this.scriptTransforms.Add(scriptTransform);
+ }
+
+ public Stream Transform(Stream data, string lang)
+ {
+ var transformedData = data;
+
+ foreach (var transformation in this.scriptTransforms)
+ {
+ transformedData = transformation.Transform(transformedData, lang);
+ transformedData.Position = 0;
+ }
+
+ return transformedData;
+
+ }
+}
diff --git a/SlipeServer.Scripting/ServiceCollectionExtensions.cs b/SlipeServer.Scripting/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..a3987d9d
--- /dev/null
+++ b/SlipeServer.Scripting/ServiceCollectionExtensions.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+
+namespace SlipeServer.Scripting;
+
+public static class ServiceCollectionExtensions
+{
+ public static void AddScripting(this IServiceCollection services)
+ {
+ services.TryAddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ }
+
+ public static void AddScripting(this IServiceCollection services) where T : class, IScriptEventRuntime
+ {
+ services.TryAddSingleton();
+ services.AddSingleton();
+ }
+}
diff --git a/SlipeServer.sln b/SlipeServer.sln
index 7b55d3ae..0caf2ff6 100644
--- a/SlipeServer.sln
+++ b/SlipeServer.sln
@@ -58,7 +58,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlipeServer.Hosting", "Slip
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlipeServer.WebHostBuilderExample", "SlipeServer.WebHostBuilderExample\SlipeServer.WebHostBuilderExample.csproj", "{ED9BDF71-BEDA-4C55-B6FA-360B3A5259E8}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlipeServer.Example", "SlipeServer.Example\SlipeServer.Example.csproj", "{E11F25F8-8DBD-412C-9504-B42CA8083D96}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlipeServer.Example", "SlipeServer.Example\SlipeServer.Example.csproj", "{E11F25F8-8DBD-412C-9504-B42CA8083D96}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlipeServer.Luau", "SlipeServer.Luau\SlipeServer.Luau.csproj", "{882D841E-E5E8-4876-BB19-05B58C4B3AE8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -450,6 +452,26 @@ Global
{E11F25F8-8DBD-412C-9504-B42CA8083D96}.Release|x64.Build.0 = Release|Any CPU
{E11F25F8-8DBD-412C-9504-B42CA8083D96}.Release|x86.ActiveCfg = Release|Any CPU
{E11F25F8-8DBD-412C-9504-B42CA8083D96}.Release|x86.Build.0 = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|ARM32.ActiveCfg = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|ARM32.Build.0 = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|x64.Build.0 = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Debug|x86.Build.0 = Debug|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|ARM32.ActiveCfg = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|ARM32.Build.0 = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|ARM64.Build.0 = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|x64.ActiveCfg = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|x64.Build.0 = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|x86.ActiveCfg = Release|Any CPU
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -479,6 +501,7 @@ Global
{DB94A24C-3B3C-4C12-8B87-55F6503960E7} = {7287CD6F-078B-470F-B508-74A442D98B64}
{ED9BDF71-BEDA-4C55-B6FA-360B3A5259E8} = {9A8750C3-0CC3-411D-A234-7869E2D54ECD}
{E11F25F8-8DBD-412C-9504-B42CA8083D96} = {9A8750C3-0CC3-411D-A234-7869E2D54ECD}
+ {882D841E-E5E8-4876-BB19-05B58C4B3AE8} = {DEAEE2A1-118A-4ED7-8CC5-7C446ED97AE3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E5DA52B5-6C04-4C6F-B5E3-3A7441C58986}