Skip to content

Commit 0ea3eed

Browse files
object oriented lua support test branch
1 parent a653c8a commit 0ea3eed

5 files changed

Lines changed: 240 additions & 5 deletions

File tree

Project.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,23 @@
125125
<!-- Comment this out to use the default OpenFL assets system for the assets/ folder. !-->
126126
<haxedef name="USE_ADAPTED_ASSETS" />
127127

128+
<!-- Comment this out to disable the use of luajit. !-->
129+
<define name="ENABLE_LUA" if="windows || mac || linux"/>
130+
128131
<!-- Comment this out to disable video cutscene support, in case of compilation errors. !-->
129132
<define name="VIDEO_CUTSCENES" unless="web || linux || hl || mac" />
130133

131134

135+
<haxedef name="ENABLE_LUA" if="ENABLE_LUA" />
132136
<haxedef name="VIDEO_CUTSCENES" if="VIDEO_CUTSCENES" />
133137
<haxedef name="UPDATE_CHECKING" if="UPDATE_CHECKING" />
138+
<haxedef name="LUAJIT_ENABLE_LUA52COMPAT" if="ENABLE_LUA" />
134139
<haxedef name="DISCORD_RPC" if="DISCORD_RPC" />
135140
<haxeflag name="--macro" value="funkin.macros.StdDeprecationsRemover.init()" />
136141
<!-- _______________________________ Libraries ______________________________ -->
137142

138143

144+
<haxelib name="linc_luajit" if="ENABLE_LUA" />
139145
<haxelib name="hxCodec" if="VIDEO_CUTSCENES" />
140146
<haxelib name="away3d" />
141147
<haxelib name="format" />

buildnumber.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2071
1+
2107

hmm.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@
5353
"ref": "master",
5454
"url": "https://github.com/Aidan63/linc_discord-rpc"
5555
},
56+
{
57+
"name": "linc_luajit",
58+
"type": "git",
59+
"dir": null,
60+
"ref": "master",
61+
"url": "https://github.com/nebulazorua/linc_luajit"
62+
},
5663
{
5764
"name": "markdown",
5865
"type": "haxelib",
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package funkin.scripting;
2+
3+
#if ENABLE_LUA
4+
import llua.Lua;
5+
import llua.LuaL;
6+
import llua.State;
7+
import llua.Convert;
8+
9+
import openfl.utils.Assets;
10+
11+
using llua.Lua;
12+
using llua.LuaL;
13+
using llua.Convert;
14+
15+
class LuaScript extends Script {
16+
public var state:State = null;
17+
18+
public var lastStackID:Int = 0;
19+
public var stack:Map<Int, Dynamic> = [];
20+
21+
public var luaCallbacks:Map<String, Dynamic> = [];
22+
23+
public override function onCreate(path:String) {
24+
super.onCreate(path);
25+
26+
state = LuaL.newstate();
27+
Lua.set_callbacks_function(cpp.Callable.fromStaticFunction(callback_handler));
28+
LuaL.openlibs(state);
29+
Lua.register_hxtrace_func(cpp.Callable.fromStaticFunction(print_function));
30+
state.register_hxtrace_lib();
31+
32+
luaCallbacks["__onPointerIndex"] = onPointerIndex;
33+
luaCallbacks["__onPointerNewIndex"] = onPointerNewIndex;
34+
luaCallbacks["__gc"] = onGarbageCollection;
35+
36+
state.newmetatable("__funkinMetaTable");
37+
38+
state.pushstring('__index');
39+
state.pushcfunction(cpp.Callable.fromStaticFunction(__index));
40+
state.settable(-3);
41+
42+
state.pushstring('__newindex');
43+
state.pushcfunction(cpp.Callable.fromStaticFunction(__newindex));
44+
state.settable(-3);
45+
}
46+
47+
public override function onLoad() {
48+
state.dostring(Assets.getText(path));
49+
}
50+
51+
public static var callbackReturnVariables = [];
52+
53+
public override function onCall(funcName:String, args:Array<Dynamic>):Dynamic {
54+
state.settop(0);
55+
state.getglobal(funcName);
56+
57+
if (state.type(-1) != Lua.LUA_TFUNCTION)
58+
return null;
59+
60+
for (k=>val in args)
61+
pushArg(val);
62+
63+
if (state.pcall(args.length, 1, 0) != 0) {
64+
this.error('${state.tostring(-1)}');
65+
return null;
66+
}
67+
68+
return fromLua(state.gettop());
69+
}
70+
71+
public override function set(variable:String, value:Dynamic) {
72+
pushArg(value);
73+
state.setglobal(variable);
74+
}
75+
76+
public override function onDestroy() {
77+
super.onDestroy();
78+
79+
if (state != null) {
80+
Lua.close(state);
81+
state = null;
82+
}
83+
}
84+
public override function reload() {
85+
Logs.trace('Hot-reloading is currently not supported on Lua.', WARNING);
86+
}
87+
88+
// UTILS
89+
#if REGION
90+
91+
static inline function print_function(s:String) : Int {
92+
if (Script.curScript != null)
93+
Script.curScript.trace(s);
94+
return 0;
95+
}
96+
97+
public function fromLua(stackPos:Int):Dynamic {
98+
var v:Dynamic = state.fromLua(stackPos);
99+
if (v is Dynamic && Reflect.hasField(v, "__stack_id")) {
100+
// is a "pointer"! convert it back.
101+
var pos:Int = Reflect.field(v, "__stack_id");
102+
return stack[pos];
103+
}
104+
return v;
105+
}
106+
public function pushArg(val:Dynamic) {
107+
switch (Type.typeof(val)) {
108+
case Type.ValueType.TNull:
109+
state.pushnil();
110+
case Type.ValueType.TBool:
111+
state.pushboolean(val);
112+
case Type.ValueType.TInt:
113+
state.pushinteger(cast(val, Int));
114+
case Type.ValueType.TFloat:
115+
state.pushnumber(val);
116+
case Type.ValueType.TClass(String):
117+
state.pushstring(cast(val, String));
118+
case Type.ValueType.TClass(Array):
119+
state.arrayToLua(val);
120+
case Type.ValueType.TObject:
121+
@:privateAccess
122+
state.objectToLua(val); // {}
123+
default:
124+
125+
var p = {
126+
__stack_id: lastStackID++,
127+
};
128+
state.toLua(p);
129+
state.getmetatable("__funkinMetaTable");
130+
state.setmetatable(-2);
131+
132+
state.pushstring('__gc');
133+
state.pushcfunction(cpp.Callable.fromStaticFunction(__gc));
134+
state.settable(-3);
135+
136+
stack[p.__stack_id] = val;
137+
}
138+
}
139+
public static function __index(state:StatePointer):Int {
140+
return callback_handler(cast cpp.Pointer.fromRaw(state).ref, "__onPointerIndex");
141+
}
142+
public static function __newindex(state:StatePointer):Int {
143+
return callback_handler(cast cpp.Pointer.fromRaw(state).ref, "__onPointerNewIndex");
144+
}
145+
public static function __gc(state:StatePointer):Int {
146+
// callbackPreventAutoConvert = true;
147+
var v = callback_handler(cast cpp.Pointer.fromRaw(state).ref, "__gc");
148+
// callbackPreventAutoConvert = false;
149+
return v;
150+
}
151+
152+
public function onPointerIndex(obj:Dynamic, key:String) {
153+
if (obj != null)
154+
return Reflect.getProperty(obj, key);
155+
return null;
156+
}
157+
158+
public function onPointerNewIndex(obj:Dynamic, key:String, val:Dynamic) {
159+
if (obj != null)
160+
Reflect.setProperty(obj, key, val);
161+
}
162+
163+
public function onGarbageCollection(obj:Dynamic) {
164+
trace(obj);
165+
if (Reflect.hasField(obj, "__stack_id")) {
166+
trace('Clearing item ID: ${obj.__stack_id} from stack due to garbage collection');
167+
stack.remove(obj.__stack_id);
168+
}
169+
}
170+
171+
private static var callbackPreventAutoConvert:Bool = false;
172+
public static inline function callback_handler(l:State, fname:String):Int {
173+
174+
if (!(Script.curScript is LuaScript))
175+
return 0;
176+
var curLua:LuaScript = cast Script.curScript;
177+
178+
var cbf = curLua.luaCallbacks.get(fname);
179+
callbackReturnVariables = [];
180+
181+
if (cbf == null || !Reflect.isFunction(cbf))
182+
return 0;
183+
184+
var nparams:Int = Lua.gettop(l);
185+
var args:Array<Dynamic> = callbackPreventAutoConvert ? [for(i in 0...nparams) l.fromLua(i + 1)] : [for(i in 0...nparams) curLua.fromLua(i + 1)];
186+
187+
var ret:Dynamic = null;
188+
189+
try {
190+
ret = (nparams > 0) ? Reflect.callMethod(null, cbf, args) : cbf();
191+
} catch(e) {
192+
curLua.error(e.details()); // for super cool mega logging!!!
193+
throw e;
194+
}
195+
Lua.settop(l, 0);
196+
197+
if (callbackReturnVariables.length <= 0)
198+
callbackReturnVariables.push(ret);
199+
for(e in callbackReturnVariables)
200+
curLua.pushArg(e);
201+
202+
/* return the number of results */
203+
return callbackReturnVariables.length;
204+
205+
}
206+
#end
207+
}
208+
#end

source/funkin/scripting/Script.hx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,14 @@ class Script extends FlxBasic implements IFlxDestroyable {
110110
"SOFTCODED_STATES" => #if SOFTCODED_STATES true #else false #end,
111111
"USE_SOURCE_ASSETS" => #if USE_SOURCE_ASSETS true #else false #end,
112112
"USE_ADAPTED_ASSETS" => #if USE_ADAPTED_ASSETS true #else false #end,
113+
"ENABLE_LUA" => #if ENABLE_LUA true #else false #end,
113114
];
114115
}
115116
/**
116117
* All available script extensions
117118
*/
118119
public static var scriptExtensions:Array<String> = [
119-
"hx", "hscript", "hsc", "hxs", "lua" /** ACTUALLY NOT SUPPORTED, ONLY FOR THE MESSAGE **/
120+
"hx", "hscript", "hsc", "hxs", "lua"
120121
];
121122

122123
/**
@@ -144,8 +145,7 @@ class Script extends FlxBasic implements IFlxDestroyable {
144145
case "hx" | "hscript" | "hsc" | "hxs":
145146
new HScript(path);
146147
case "lua":
147-
Logs.trace("Lua is not supported in this engine. Use HScript instead.", ERROR);
148-
new DummyScript(path);
148+
new LuaScript(path);
149149
default:
150150
new DummyScript(path);
151151
}
@@ -160,6 +160,10 @@ class Script extends FlxBasic implements IFlxDestroyable {
160160
public function new(path:String) {
161161
super();
162162

163+
// #if cpp
164+
// cpp.vm.Gc.setFinalizer(this, cpp.Callable.fromStaticFunction(onFinalize));
165+
// #end
166+
163167
fileName = Path.withoutDirectory(path);
164168
this.path = path;
165169
onCreate(path);
@@ -263,10 +267,20 @@ class Script extends FlxBasic implements IFlxDestroyable {
263267

264268
public function onLoad() {}
265269

266-
public function onDestroy() {};
270+
public function onDestroy() {}
267271

268272
public override function destroy() {
269273
super.destroy();
270274
onDestroy();
271275
}
276+
277+
private static var __scriptType:Class<Script>;
278+
public static function onFinalize(s:Script) {
279+
#if cpp
280+
// destroy everything
281+
Sys.println("GARBAGE COLLECTOR - FINALIZING");
282+
s.destroy();
283+
Sys.println("GARBAGE COLLECTOR - FINALIZING");
284+
#end
285+
}
272286
}

0 commit comments

Comments
 (0)