diff --git a/Project.xml b/Project.xml
index f60790e76c2..7686581b716 100644
--- a/Project.xml
+++ b/Project.xml
@@ -124,10 +124,8 @@
-
+
-
-
diff --git a/hmm.json b/hmm.json
index 5d92add16c9..354ea150ac0 100644
--- a/hmm.json
+++ b/hmm.json
@@ -75,11 +75,11 @@
"url": "https://github.com/MAJigsaw77/hxdiscord_rpc"
},
{
- "name": "linc_luajit",
+ "name": "hxluajit",
"type": "git",
"dir": null,
"ref": "master",
- "url": "https://github.com/JS-Engine-things/linc_luajit"
+ "url": "https://github.com/JS-Engine-things/hxluajit"
},
{
"name": "funkin.vis",
diff --git a/setup/unix.sh b/setup/unix.sh
index 8bc2e0cbd8a..3e7d7a5a451 100644
--- a/setup/unix.sh
+++ b/setup/unix.sh
@@ -18,7 +18,7 @@ haxelib git away3d https://github.com/moxie-coder/away3d --quiet
haxelib git tjson https://github.com/moxie-coder/tjson --quiet
haxelib git hxcpp https://github.com/FunkinCrew/hxcpp --quiet
haxelib git flxanimate https://github.com/Dot-Stuff/flxanimate 768740a56b26aa0c072720e0d1236b94afe68e3e --quiet
-haxelib git linc_luajit https://github.com/JS-Engine-things/linc_luajit --quiet
+haxelib git hxluajit https://github.com/JS-Engine-things/hxluajit --quiet
haxelib git funkin.vis https://github.com/JS-Engine-things/funkVis-FrequencyFixed --quiet
haxelib git grig.audio https://github.com/JS-Engine-things/grig.audio --quiet
haxelib git hxdiscord_rpc https://github.com/MAJigsaw77/hxdiscord_rpc --quiet --skip-dependencies
diff --git a/setup/windows.bat b/setup/windows.bat
index c8f5ba4b92a..6efa93cb477 100644
--- a/setup/windows.bat
+++ b/setup/windows.bat
@@ -16,7 +16,7 @@ haxelib git away3d https://github.com/moxie-coder/away3d --quiet
haxelib git tjson https://github.com/moxie-coder/tjson --quiet
haxelib git hxcpp https://github.com/FunkinCrew/hxcpp --quiet
haxelib git flxanimate https://github.com/Dot-Stuff/flxanimate 768740a56b26aa0c072720e0d1236b94afe68e3e --quiet
-haxelib git linc_luajit https://github.com/JS-Engine-things/linc_luajit --quiet
+haxelib git hxluajit https://github.com/JS-Engine-things/hxluajit --quiet
haxelib git funkin.vis https://github.com/JS-Engine-things/funkVis-FrequencyFixed --quiet
haxelib git grig.audio https://github.com/JS-Engine-things/grig.audio --quiet
haxelib git hxdiscord_rpc https://github.com/MAJigsaw77/hxdiscord_rpc --quiet --skip-dependencies
diff --git a/source/Achievements.hx b/source/Achievements.hx
index 2195a731c6e..a9c9539f433 100644
--- a/source/Achievements.hx
+++ b/source/Achievements.hx
@@ -3,6 +3,9 @@ import flixel.FlxCamera;
#if ACHIEVEMENTS_ALLOWED
import haxe.Exception;
import objects.AchievementPopup;
+#if LUA_ALLOWED
+import psychlua.FunkinLua.State;
+#end
typedef Achievement =
{
@@ -261,7 +264,7 @@ class Achievements {
#if LUA_ALLOWED
public static function addLuaCallbacks(lua:State)
{
- Lua_helper.add_callback(lua, "getAchievementScore", function(name:String):Float
+ Convert.addCallback(lua, "getAchievementScore", function(name:String):Float
{
if(!achievements.exists(name))
{
@@ -270,7 +273,7 @@ class Achievements {
}
return getScore(name);
});
- Lua_helper.add_callback(lua, "setAchievementScore", function(name:String, ?value:Float = 1, ?saveIfNotUnlocked:Bool = true):Float
+ Convert.addCallback(lua, "setAchievementScore", function(name:String, ?value:Float = 1, ?saveIfNotUnlocked:Bool = true):Float
{
if(!achievements.exists(name))
{
@@ -279,7 +282,7 @@ class Achievements {
}
return setScore(name, value, saveIfNotUnlocked);
});
- Lua_helper.add_callback(lua, "addAchievementScore", function(name:String, ?value:Float = 1, ?saveIfNotUnlocked:Bool = true):Float
+ Convert.addCallback(lua, "addAchievementScore", function(name:String, ?value:Float = 1, ?saveIfNotUnlocked:Bool = true):Float
{
if(!achievements.exists(name))
{
@@ -288,7 +291,7 @@ class Achievements {
}
return addScore(name, value, saveIfNotUnlocked);
});
- Lua_helper.add_callback(lua, "unlockAchievement", function(name:String):Dynamic
+ Convert.addCallback(lua, "unlockAchievement", function(name:String):Dynamic
{
if(!achievements.exists(name))
{
@@ -297,7 +300,7 @@ class Achievements {
}
return unlock(name);
});
- Lua_helper.add_callback(lua, "isAchievementUnlocked", function(name:String):Dynamic
+ Convert.addCallback(lua, "isAchievementUnlocked", function(name:String):Dynamic
{
if(!achievements.exists(name))
{
@@ -306,7 +309,7 @@ class Achievements {
}
return isUnlocked(name);
});
- Lua_helper.add_callback(lua, "achievementExists", function(name:String) return achievements.exists(name));
+ Convert.addCallback(lua, "achievementExists", function(name:String) return achievements.exists(name));
}
#end
#end
diff --git a/source/DiscordClient.hx b/source/DiscordClient.hx
index 88b5b94373a..e560476aaa9 100644
--- a/source/DiscordClient.hx
+++ b/source/DiscordClient.hx
@@ -6,6 +6,9 @@ import cpp.ConstCharStar;
import cpp.Function;
import cpp.RawConstPointer;
#end
+#if LUA_ALLOWED
+import psychlua.FunkinLua.State;
+#end
import hxdiscord_rpc.Discord;
import hxdiscord_rpc.Types;
@@ -150,8 +153,8 @@ class DiscordClient
#if LUA_ALLOWED
public static function addLuaCallbacks(lua:State)
{
- Lua_helper.add_callback(lua, "changeDiscordPresence", changePresence);
- Lua_helper.add_callback(lua, "changeDiscordClientID", function(?newID:String) {
+ Convert.addCallback(lua, "changeDiscordPresence", changePresence);
+ Convert.addCallback(lua, "changeDiscordClientID", function(?newID:String) {
if(newID == null) newID = _defaultID;
clientID = newID;
});
diff --git a/source/Main.hx b/source/Main.hx
index 9f7e6cbde75..32afc2e02f0 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -78,8 +78,6 @@ class Main extends Sprite {
FlxG.sound = soundFrontEnd;
funkinGame._customSoundTray = objects.CustomSoundTray.CustomSoundTray;
}
- // turns out I forgot this, I'm a bit dumb for that
- #if LUA_ALLOWED Lua.set_callbacks_function(cpp.Callable.fromStaticFunction(psychlua.CallbackHandler.call)); #end
addChild(funkinGame);
diff --git a/source/import.hx b/source/import.hx
index 53a88efb676..6f3748d47f9 100644
--- a/source/import.hx
+++ b/source/import.hx
@@ -8,8 +8,8 @@ import sys.io.*;
#end
#if LUA_ALLOWED
-import llua.*;
-import llua.Lua;
+import hxluajit.*;
+import hxluajit.Types;
import psychlua.*;
#else
import psychlua.FunkinLua; // TODO: test and seperate this into LuaUtils
diff --git a/source/psychlua/CallbackHandler.hx b/source/psychlua/CallbackHandler.hx
deleted file mode 100644
index 82df5876d8d..00000000000
--- a/source/psychlua/CallbackHandler.hx
+++ /dev/null
@@ -1,54 +0,0 @@
-package psychlua;
-
-class CallbackHandler
-{
- public static inline function call(l:State, fname:String):Int
- {
- try
- {
- //trace('calling $fname');
- var cbf:Dynamic = Lua_helper.callbacks.get(fname);
-
- //Local functions have the lowest priority
- //This is to prevent a "for" loop being called in every single operation,
- //so that it only loops on reserved/special functions
- if(cbf == null)
- {
- //trace('looping thru scripts');
- for (script in PlayState.instance.luaArray)
- if(script != null && script.lua == l)
- {
- //trace('found script');
- cbf = script.callbacks.get(fname);
- break;
- }
- }
-
- if(cbf == null) return 0;
-
- var nparams:Int = Lua.gettop(l);
- var args:Array = [];
-
- for (i in 0...nparams) {
- args[i] = Convert.fromLua(l, i + 1);
- }
-
- var ret:Dynamic = null;
- /* return the number of results */
-
- ret = Reflect.callMethod(null,cbf,args);
-
- if(ret != null){
- Convert.toLua(l, ret);
- return 1;
- }
- }
- catch(e:Dynamic)
- {
- if(Lua_helper.sendErrorsToLua) {LuaL.error(l, 'CALLBACK ERROR! ${if(e.message != null) e.message else e}');return 0;}
- trace(e);
- throw(e);
- }
- return 0;
- }
-}
\ No newline at end of file
diff --git a/source/psychlua/Convert.hx b/source/psychlua/Convert.hx
new file mode 100644
index 00000000000..7726b925ccd
--- /dev/null
+++ b/source/psychlua/Convert.hx
@@ -0,0 +1,304 @@
+package psychlua;
+
+import haxe.ds.*;
+import psychlua.FunkinLua.State;
+import hxluajit.Types;
+
+
+/**
+ * Some borrowed code from hxluajit-wrapper.
+ * @see https://github.com/MAJigsaw77/hxluajit-wrapper/blob/main/hxluajit/wrapper/LuaConverter.hx
+ *
+ * We didn't use hxluajit-wrapper because we wanted to have our functions and methods as similar as possible to linc_luajit
+ */
+class Convert
+{
+ public static function addCallback(l:State, name:String, func:Dynamic)
+ {
+ // PsychLua expects the function to be null for local callbacks so if func is not TFunction we don't add the callback here
+ if (Type.typeof(func) == TFunction)
+ callbacks.set(name, func);
+
+ Lua.pushstring(l, name);
+ Lua.pushcclosure(l, cpp.Callable.fromStaticFunction(handleCallback), 1);
+ Lua.setglobal(l, name);
+ }
+
+ public static function removeCallback(l:State, name:String)
+ {
+ if (!callbacks.exists(name))
+ return;
+
+ callbacks.remove(name);
+
+ Lua.pushnil(l);
+ Lua.setglobal(l, name);
+ }
+
+ public static function toLua(l:State, v:Dynamic):Bool
+ {
+ switch (Type.typeof(v))
+ {
+ case TInt:
+ Lua.pushinteger(l, cast(v, Int));
+ case TFloat:
+ Lua.pushnumber(l, cast(v, Float));
+ case TBool:
+ Lua.pushboolean(l, v == true ? 1 : 0);
+ case TObject:
+ final fields:Array = Reflect.fields(v);
+
+ Lua.createtable(l, fields.length, 0);
+
+ for (field in fields)
+ {
+ Lua.pushstring(l, field);
+ toLua(l, Reflect.field(v, field));
+ Lua.settable(l, -3);
+ }
+ case TClass(String):
+ Lua.pushstring(l, cast(v, String));
+ case TClass(Array):
+ final elements:Array = v;
+
+ Lua.createtable(l, elements.length, 0);
+
+ for (i in 0...elements.length)
+ {
+ Lua.pushinteger(l, i + 1);
+ toLua(l, elements[i]);
+ Lua.settable(l, -3);
+ }
+ case TClass(IntMap) | TClass(StringMap) | TClass(ObjectMap):
+ final values:Map = v;
+
+ Lua.createtable(l, Lambda.count(values), 0);
+
+ for (key => value in values)
+ {
+ Lua.pushstring(l, key);
+ toLua(l, value);
+ Lua.settable(l, -3);
+ }
+ case TNull:
+ Lua.pushnil(l);
+ default:
+ Lua.pushnil(l);
+ return false;
+ }
+ return true;
+ }
+
+ public static function fromLua(l:State, idx:Int):Dynamic
+ {
+ var ret:Dynamic = null;
+
+ switch (Lua.type(l, idx))
+ {
+ case type if (type == Lua.TNUMBER):
+ ret = Lua.tonumber(l, idx);
+ case type if (type == Lua.TSTRING):
+ ret = Lua.tostring(l, idx).toString();
+ case type if (type == Lua.TBOOLEAN):
+ ret = Lua.toboolean(l, idx) == 1;
+ case type if (type == Lua.TTABLE):
+ ret = convertTable(l, idx);
+ case type if (type == Lua.TFUNCTION):
+ ret = new LuaFunction(cpp.Pointer.fromRaw(l), LuaL.ref(l, Lua.REGISTRYINDEX));
+ case type if (type == Lua.TUSERDATA || type == Lua.TLIGHTUSERDATA):
+ ret = cpp.Pointer.fromRaw(Lua.touserdata(l, idx));
+ default:
+ ret = null;
+ }
+
+ return ret;
+ }
+
+ public static function callFunctionWithoutName(l:State, args:Array):Array
+ {
+ for (arg in args)
+ toLua(l, arg);
+
+ final status:Int = Lua.pcall(l, args.length, Lua.MULTRET, 0);
+
+ if (status != Lua.OK)
+ {
+ var error = Lua.tostring(l, -1);
+ trace('Error calling a function without name: $error');
+ Lua.pop(l, 1);
+
+ return [];
+ }
+
+ final args:Array = [];
+
+ {
+ final count:Int = Lua.gettop(l);
+
+ for (i in 0...count)
+ args.push(fromLua(l, i + 1));
+
+ Lua.pop(l, count);
+ }
+
+ return args;
+ }
+
+ @:noCompletion
+ private static function convertTable(l:State, idx:Int):Dynamic
+ {
+ var isArray:Bool = true;
+
+ var count:Int = 0;
+
+ iterateTable(l, idx, function():Void
+ {
+ if (isArray)
+ {
+ if (Lua.type(l, -2) == Lua.TNUMBER)
+ {
+ final index:Lua_Integer = Lua.tointeger(l, -2);
+
+ if (index < 0)
+ isArray = false;
+ }
+ else
+ isArray = false;
+ }
+
+ count++;
+ });
+
+ if (count == 0)
+ return {};
+
+ if (isArray)
+ {
+ final obj:Array = [];
+
+ iterateTable(l, idx, function():Void
+ {
+ obj[Lua.tointeger(l, -2) - 1] = fromLua(l, -1);
+ });
+
+ return obj;
+ }
+ else
+ {
+ final obj:haxe.DynamicAccess = {};
+
+ iterateTable(l, idx, function():Void
+ {
+ obj.set(Std.string(fromLua(l, -2)), fromLua(l, -1));
+ });
+
+ return obj;
+ }
+ }
+
+ @:noCompletion
+ private static function iterateTable(l:State, idx:Int, fn:Void->Void):Void
+ {
+ Lua.pushnil(l);
+
+ while (Lua.next(l, idx < 0 ? idx - 1 : idx) != 0)
+ {
+ fn();
+
+ Lua.pop(l, 1);
+ }
+ }
+
+ @:noCompletion
+ private static var funcs = [];
+
+ @:noCompletion
+ private static function handleMethod(l:State):Int
+ {
+ var argsLength:Int = Lua.gettop(l);
+ var method = funcs[cast Lua.tonumber(l, Lua.upvalueindex(1))];
+ var args = [];
+
+ for (i in 0...argsLength)
+ args[i] = fromLua(l, i + 1);
+
+ try
+ {
+ var result = Reflect.callMethod(null, method, args);
+ if (result != null)
+ return toLua(l, result) ? 1 : 0;
+ else
+ return 0;
+ }
+ catch (e)
+ {
+ LuaL.error(l, 'METHOD ERROR!\n${e.stack}');
+ return 0;
+ }
+ }
+
+ @:noCompletion
+ private static var callbacks:Map = new Map();
+
+ @:noCompletion
+ private static function handleCallback(l:State):Int
+ {
+ try
+ {
+ var callbackName:String = Lua.tostring(l, Lua.upvalueindex(1));
+ var callbackMethod:Dynamic = callbacks.get(callbackName);
+
+ if (callbackMethod == null)
+ {
+ // trace('checking last script');
+ var last:FunkinLua = FunkinLua.lastCalledScript;
+ if (last == null || last.lua != l)
+ {
+ // trace('looping thru scripts');
+ for (script in PlayState.instance.luaArray)
+ {
+ if (script != FunkinLua.lastCalledScript && script != null && script.lua == l)
+ {
+ // trace('found script');
+ callbackMethod = script.callbacks.get(callbackName);
+ break;
+ }
+ }
+ }
+ else
+ {
+ callbackMethod = last.callbacks.get(callbackName);
+ }
+ }
+
+ if (callbackMethod == null)
+ return 0;
+
+ var nparams:Int = Lua.gettop(l);
+ var args:Array = [];
+
+ for (i in 0...nparams)
+ {
+ args[i] = fromLua(l, i + 1);
+ }
+
+ var ret:Dynamic = null;
+ /* return the number of results */
+
+ ret = Reflect.callMethod(null, callbackMethod, args);
+
+ if (ret != null)
+ {
+ toLua(l, ret);
+ return 1;
+ }
+ }
+ catch (e:Dynamic)
+ {
+ LuaL.error(l, 'CALLBACK ERROR! ${if (e.message != null) e.message else e}');
+ return 0;
+ }
+
+ return 0;
+ }
+}
diff --git a/source/psychlua/CustomSubstate.hx b/source/psychlua/CustomSubstate.hx
index 22032221c02..c8afd44c8e3 100644
--- a/source/psychlua/CustomSubstate.hx
+++ b/source/psychlua/CustomSubstate.hx
@@ -11,9 +11,9 @@ class CustomSubstate extends MusicBeatSubstate
public static function implement(funk:FunkinLua)
{
var lua = funk.lua;
- Lua_helper.add_callback(lua, "openCustomSubstate", openCustomSubstate);
- Lua_helper.add_callback(lua, "closeCustomSubstate", closeCustomSubstate);
- Lua_helper.add_callback(lua, "insertToCustomSubstate", insertToCustomSubstate);
+ Convert.addCallback(lua, "openCustomSubstate", openCustomSubstate);
+ Convert.addCallback(lua, "closeCustomSubstate", closeCustomSubstate);
+ Convert.addCallback(lua, "insertToCustomSubstate", insertToCustomSubstate);
}
#end
diff --git a/source/psychlua/FlxAnimateFunctions.hx b/source/psychlua/FlxAnimateFunctions.hx
index 565ef3c3493..24a4f937a07 100644
--- a/source/psychlua/FlxAnimateFunctions.hx
+++ b/source/psychlua/FlxAnimateFunctions.hx
@@ -2,13 +2,17 @@ package psychlua;
import openfl.utils.Assets;
+#if LUA_ALLOWED
+import psychlua.FunkinLua.State;
+#end
+
#if (LUA_ALLOWED && flxanimate)
class FlxAnimateFunctions
{
public static function implement(funk:FunkinLua)
{
final lua:State = funk.lua;
- Lua_helper.add_callback(lua, "makeFlxAnimateSprite", function(tag:String, ?x:Float = 0, ?y:Float = 0, ?loadFolder:String = null) {
+ Convert.addCallback(lua, "makeFlxAnimateSprite", function(tag:String, ?x:Float = 0, ?y:Float = 0, ?loadFolder:String = null) {
tag = tag.replace('.', '');
var lastSprite = MusicBeatState.getVariables().get(tag);
if(lastSprite != null)
@@ -24,12 +28,12 @@ class FlxAnimateFunctions
mySprite.active = true;
});
- Lua_helper.add_callback(lua, "loadAnimateAtlas", function(tag:String, folderOrImg:String, ?spriteJson:String = null, ?animationJson:String = null) {
+ Convert.addCallback(lua, "loadAnimateAtlas", function(tag:String, folderOrImg:String, ?spriteJson:String = null, ?animationJson:String = null) {
var spr:FlxAnimate = MusicBeatState.getVariables().get(tag);
if(spr != null) Paths.loadAnimateAtlas(spr, folderOrImg, spriteJson, animationJson);
});
- Lua_helper.add_callback(lua, "addAnimationBySymbol", function(tag:String, name:String, symbol:String, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0)
+ Convert.addCallback(lua, "addAnimationBySymbol", function(tag:String, name:String, symbol:String, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0)
{
var obj:FlxAnimate = cast MusicBeatState.getVariables().get(tag);
if(obj == null) return false;
@@ -44,7 +48,7 @@ class FlxAnimateFunctions
return true;
});
- Lua_helper.add_callback(lua, "addAnimationBySymbolIndices", function(tag:String, name:String, symbol:String, ?indices:Any = null, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0)
+ Convert.addCallback(lua, "addAnimationBySymbolIndices", function(tag:String, name:String, symbol:String, ?indices:Any = null, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0)
{
var obj:FlxAnimate = cast MusicBeatState.getVariables().get(tag);
if(obj == null) return false;
diff --git a/source/psychlua/FunkinLua.hx b/source/psychlua/FunkinLua.hx
index b0f800b4748..a83b9ac332d 100644
--- a/source/psychlua/FunkinLua.hx
+++ b/source/psychlua/FunkinLua.hx
@@ -211,7 +211,7 @@ class FunkinLua {
for (name => func in customFunctions) {
if (func != null)
- Lua_helper.add_callback(lua, name, func);
+ Convert.addCallback(lua, name, func);
}
// shader shit
@@ -605,11 +605,11 @@ class FunkinLua {
if(luaInstance.scriptName == cervix)
{
Lua.getglobal(luaInstance.lua, global);
- if(Lua.isnumber(luaInstance.lua,-1)){
+ if(Lua.isnumber(luaInstance.lua,-1) == 1){
Lua.pushnumber(lua, Lua.tonumber(luaInstance.lua, -1));
- }else if(Lua.isstring(luaInstance.lua,-1)){
+ }else if(Lua.isstring(luaInstance.lua,-1) == 1){
Lua.pushstring(lua, Lua.tostring(luaInstance.lua, -1));
- }else if(Lua.isboolean(luaInstance.lua,-1)){
+ }else if(Lua.isboolean(luaInstance.lua,-1) == 1){
Lua.pushboolean(lua, Lua.toboolean(luaInstance.lua, -1));
}else{
Lua.pushnil(lua);
@@ -2259,7 +2259,7 @@ class FunkinLua {
});
for (name => func in registeredFunctions) {
if (func != null)
- Lua_helper.add_callback(lua, name, func);
+ Convert.addCallback(lua, name, func);
}
#if ACHIEVEMENTS_ALLOWED Achievements.addLuaCallbacks(lua); #end
#if HSCRIPT_ALLOWED HScript.implement(this); #end
@@ -2890,7 +2890,7 @@ class FunkinLua {
public function addLocalCallback(name:String, myFunction:Dynamic)
{
callbacks.set(name, myFunction);
- Lua_helper.add_callback(lua, name, null); // just so that it gets called
+ Convert.addCallback(lua, name, null); // just so that it gets called
}
public static function registerFunction(name:String, func:Dynamic):Void
@@ -3185,8 +3185,8 @@ class FunkinLua {
Lua.getglobal(lua, func);
var type:Int = Lua.type(lua, -1);
- if (type != Lua.LUA_TFUNCTION) {
- if (type > Lua.LUA_TNIL)
+ if (type != Lua.TFUNCTION) {
+ if (type > Lua.TNIL)
LuaUtils.luaTrace(lua, "ERROR (" + func + "): attempt to call a " + typeToString(type) + " value", false, false, FlxColor.RED);
Lua.pop(lua, 1);
@@ -3197,7 +3197,7 @@ class FunkinLua {
var status:Int = Lua.pcall(lua, args.length, 1, 0);
// Checks if it's not successful, then show a error.
- if (status != Lua.LUA_OK) {
+ if (status != Lua.OK) {
var error:String = LuaUtils.getErrorMessage(lua, status);
LuaUtils.luaTrace(lua, "ERROR (" + func + "): " + error, false, false, FlxColor.RED);
return Function_Continue;
@@ -3266,16 +3266,24 @@ class FunkinLua {
return coverMeInPiss;
}
- function typeToString(type:Int):String {
+ public static function typeToString(type:Int):String
+ {
#if LUA_ALLOWED
- switch(type) {
- case Lua.LUA_TBOOLEAN: return "boolean";
- case Lua.LUA_TNUMBER: return "number";
- case Lua.LUA_TSTRING: return "string";
- case Lua.LUA_TTABLE: return "table";
- case Lua.LUA_TFUNCTION: return "function";
+ switch (type)
+ {
+ case type if (type == Lua.TBOOLEAN):
+ return "boolean";
+ case type if (type == Lua.TNUMBER):
+ return "number";
+ case type if (type == Lua.TSTRING):
+ return "string";
+ case type if (type == Lua.TTABLE):
+ return "table";
+ case type if (type == Lua.TFUNCTION):
+ return "function";
+ case type if (type <= Lua.TNIL):
+ return "nil";
}
- if (type <= Lua.LUA_TNIL) return "nil";
#end
return "unknown";
}
@@ -3287,7 +3295,7 @@ class FunkinLua {
if (Reflect.isFunction(data)) {
// Bind as a callable Lua function
- Lua_helper.add_callback(lua, variable, data);
+ Convert.addCallback(lua, variable, data);
return;
}
@@ -3317,4 +3325,5 @@ class FunkinLua {
return PlayState.instance.isDead ? GameOverSubstate.instance : PlayState.instance;
}
}
+typedef State = cpp.RawPointer;
// hi guys, my name is "secret"!
diff --git a/source/psychlua/HScript.hx b/source/psychlua/HScript.hx
index 149f15c4fb2..d2cf43c2b12 100644
--- a/source/psychlua/HScript.hx
+++ b/source/psychlua/HScript.hx
@@ -95,7 +95,7 @@ class HScript
#if HSCRIPT_ALLOWED
for (script in PlayState.instance.luaArray)
if(script != null && script.lua != null && !script.closed)
- Lua_helper.add_callback(script.lua, name, func);
+ Convert.addCallback(script.lua, name, func);
#end
FunkinLua.customFunctions.set(name, func);
});
diff --git a/source/psychlua/LuaFunction.hx b/source/psychlua/LuaFunction.hx
new file mode 100644
index 00000000000..4bd988f3a2a
--- /dev/null
+++ b/source/psychlua/LuaFunction.hx
@@ -0,0 +1,62 @@
+package psychlua;
+
+import hxluajit.Types;
+
+/**
+ * Holds a Lua function that can be called from Haxe.
+ *
+ * @see https://github.com/DragShot/linc_luajit/blob/master/llua/LuaCallback.hx
+ *
+ * @author DragShot
+ */
+@:allow(psychlua.Convert)
+class LuaFunction
+{
+ @:noCompletion
+ private var l:Null>;
+
+ @:noCompletion
+ private var ref:Int;
+
+ /**
+ * Creates a new LuaFunction instance.
+ *
+ * @param l The Lua state pointer.
+ * @param ref The Lua function reference.
+ */
+ private function new(l:cpp.Pointer, ref:Int):Void
+ {
+ this.l = l;
+ this.ref = ref;
+ }
+
+ /**
+ * Calls the Lua function.
+ *
+ * @param args The function arguments.
+ * @return The function results as a Haxe array.
+ */
+ public function call(args:Array):Array
+ {
+ if (l != null)
+ {
+ Lua.rawgeti(l.raw, Lua.REGISTRYINDEX, ref);
+
+ return Convert.callFunctionWithoutName(l.raw, args);
+ }
+
+ return [];
+ }
+
+ /**
+ * Disposes of the Lua function reference.
+ */
+ public function dispose():Void
+ {
+ if (l != null)
+ {
+ LuaL.unref(l.raw, Lua.REGISTRYINDEX, ref);
+ l = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/psychlua/LuaUtils.hx b/source/psychlua/LuaUtils.hx
index f168d49d88b..4b90a30a6c6 100644
--- a/source/psychlua/LuaUtils.hx
+++ b/source/psychlua/LuaUtils.hx
@@ -6,6 +6,10 @@ import flixel.util.FlxColor;
import openfl.display.BlendMode;
+#if LUA_ALLOWED
+import psychlua.FunkinLua.State;
+#end
+
using StringTools;
@:allow(psychlua.FunkinLua)
@@ -106,13 +110,18 @@ class LuaUtils {
Lua.pop(lua, 1);
if (v != null) v = v.trim();
- if (v == null || v == "") {
- return switch(status) {
- case Lua.LUA_ERRRUN: return "Runtime Error";
- case Lua.LUA_ERRMEM: return "Memory Allocation Error";
- case Lua.LUA_ERRERR: return "Critical Error";
- case _: return "Unknown Error";
+ if (v == null || v == "")
+ {
+ switch (status)
+ {
+ case type if (type == Lua.ERRRUN):
+ return "Runtime Error";
+ case type if (type == Lua.ERRMEM):
+ return "Memory Allocation Error";
+ case type if (type == Lua.ERRERR):
+ return "Critical Error";
}
+ return "Unknown Error";
}
return v;