From bbeec3c7075f0a5c98face4eec5c76bcf1a56120 Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 22 Feb 2022 23:31:29 -0800 Subject: [PATCH] Add support for Lua functions inside parameters --- autogen/common.py | 9 +++++++ autogen/convert_functions.py | 36 ++++++++++++++++++++++++++++ docs/lua/functions.md | 5 ++-- src/pc/lua/smlua_cobject.h | 1 + src/pc/lua/smlua_functions_autogen.c | 6 +++-- src/pc/lua/smlua_obj_utils.c | 13 +++++++++- src/pc/lua/smlua_obj_utils.h | 2 +- src/pc/lua/smlua_utils.c | 17 +++++++++++++ src/pc/lua/smlua_utils.h | 2 ++ 9 files changed, 85 insertions(+), 6 deletions(-) diff --git a/autogen/common.py b/autogen/common.py index 818188112..8796e5067 100644 --- a/autogen/common.py +++ b/autogen/common.py @@ -46,6 +46,9 @@ def translate_type_to_lvt(ptype): if ptype == 'float': return 'LVT_F32' + if ptype == 'LuaFunction': + return 'LVT_LUAFUNCTION' + if 'struct' in ptype: if ptype.count('*') > 1: return 'LVT_???' @@ -91,6 +94,9 @@ def translate_type_to_lot(ptype): if ptype == 'float': return 'LOT_NONE' + if ptype == 'LuaFunction': + return 'LOT_NONE' + if 'struct' in ptype: if ptype.count('*') > 1: return 'LOT_???' @@ -132,6 +138,9 @@ def translate_type_to_lua(ptype): if 'void' == ptype: return None, False + if ptype == 'LuaFunction': + return 'LuaFunction()', False + if ptype.count('*') == 1 and '???' not in translate_type_to_lvt(ptype): ptype = ptype.replace('const', '').replace('*', '').strip() s = 'Pointer <%s>' % translate_type_to_lua(ptype)[0] diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 0e4480f9f..88dbd235a 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -71,6 +71,10 @@ override_disallowed_functions = { "src/game/obj_behaviors_2.c": [ "wiggler_jumped_on_attack_handler", "huge_goomba_weakly_attacked" ], } +lua_function_params = { + "src/pc/lua/smlua_obj_utils.h::spawn_object_sync::objSetupFunction": [ "struct Object*" ] +} + ########################################################### template = """/* THIS FILE IS AUTOGENERATED */ @@ -174,6 +178,8 @@ def build_param(param, i): return ' %s %s = smlua_to_number(L, %d);\n' % (ptype, pid, i) elif ptype == 'const char*': return ' %s %s = smlua_to_string(L, %d);\n' % (ptype, pid, i) + elif ptype == 'LuaFunction': + return ' %s %s = smlua_to_lua_function(L, %d);\n' % (ptype, pid, i) elif translate_type_to_lot(ptype) == 'LOT_POINTER': lvt = translate_type_to_lvt(ptype) return ' %s %s = (%s)smlua_to_cpointer(L, %d, %s);\n' % (ptype, pid, ptype, i, lvt) @@ -354,6 +360,11 @@ def process_function(fname, line): if param['type'].replace(' ', '') == 's16*': param['type'] = 'Vec3s' + # remember lua function params + lf_key = fname + '::' + function['identifier'] + '::' + param['identifier'] + if param['type'] == 'LuaFunction' and lf_key in lua_function_params: + param['lua_function_params'] = lua_function_params[lf_key] + function['params'].append(param) param_index += 1 @@ -405,6 +416,27 @@ def doc_function_index(processed_files): return s +def doc_lua_func_param(param): + s = 'LuaFunction(' + + lfp = param['lua_function_params'] + first_lfp = True + + for lfp_type in lfp: + if not first_lfp: + lfp_type += ', ' + first_lfp = False + + lfp_type, lfp_link = translate_type_to_lua(lfp_type) + + if lfp_link: + s += '[%s](structs.md#%s)' % (lfp_type, lfp_type) + else: + s += lfp_type + + s += ')' + return s + def doc_function(function): if not function['implemented']: return '' @@ -430,6 +462,10 @@ def doc_function(function): ptype = param['type'] ptype, plink = translate_type_to_lua(ptype) + # build lua function params + if param['type'] == 'LuaFunction' and 'lua_function_params' in param: + ptype = doc_lua_func_param(param) + if plink: s += '| %s | [%s](structs.md#%s) |\n' % (pid, ptype, ptype) continue diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 561606005..cf6d20e55 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -8033,7 +8033,7 @@ ## [spawn_object_sync](#spawn_object_sync) ### Lua Example -`local ObjectValue = spawn_object_sync(behaviorId, modelId, x, y, z)` +`local ObjectValue = spawn_object_sync(behaviorId, modelId, x, y, z, objSetupFunction)` ### Parameters | Field | Type | @@ -8043,12 +8043,13 @@ | x | number | | y | number | | z | number | +| objSetupFunction | LuaFunction([Object](structs.md#Object)) | ### Returns [Object](structs.md#Object) ### C Prototype -`struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z);` +`struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z, LuaFunction objSetupFunction);` [:arrow_up_small:](#) diff --git a/src/pc/lua/smlua_cobject.h b/src/pc/lua/smlua_cobject.h index f351a02e0..2b0ec5473 100644 --- a/src/pc/lua/smlua_cobject.h +++ b/src/pc/lua/smlua_cobject.h @@ -23,6 +23,7 @@ enum LuaValueType { LVT_STRING_P, LVT_BEHAVIORSCRIPT, LVT_BEHAVIORSCRIPT_P, + LVT_LUAFUNCTION, LVT_POINTER, }; diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 5a2885ddc..f4fff1d2e 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -5287,7 +5287,7 @@ int smlua_func_save_file_get_total_star_count(lua_State* L) { /////////////////////// int smlua_func_spawn_object_sync(lua_State* L) { - if(!smlua_functions_valid_param_count(L, 5)) { return 0; } + if(!smlua_functions_valid_param_count(L, 6)) { return 0; } int behaviorId = smlua_to_integer(L, 1); if (!gSmLuaConvertSuccess) { return 0; } @@ -5299,8 +5299,10 @@ int smlua_func_spawn_object_sync(lua_State* L) { if (!gSmLuaConvertSuccess) { return 0; } f32 z = smlua_to_number(L, 5); if (!gSmLuaConvertSuccess) { return 0; } + LuaFunction objSetupFunction = smlua_to_lua_function(L, 6); + if (!gSmLuaConvertSuccess) { return 0; } - smlua_push_object(L, LOT_OBJECT, spawn_object_sync(behaviorId, modelId, x, y, z)); + smlua_push_object(L, LOT_OBJECT, spawn_object_sync(behaviorId, modelId, x, y, z, objSetupFunction)); return 1; } diff --git a/src/pc/lua/smlua_obj_utils.c b/src/pc/lua/smlua_obj_utils.c index f6b750f7c..662a39e19 100644 --- a/src/pc/lua/smlua_obj_utils.c +++ b/src/pc/lua/smlua_obj_utils.c @@ -3,12 +3,13 @@ #include "object_fields.h" #include "src/game/object_helpers.h" +#include "smlua.h" #include "smlua_obj_utils.h" #include "smlua_model_utils.h" #include "pc/debuglog.h" -struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z) { +struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z, LuaFunction objSetupFunction) { const BehaviorScript* behavior = get_behavior_from_id(behaviorId); if (behavior == NULL) { LOG_ERROR("failed to find behavior %u", behaviorId); @@ -43,6 +44,16 @@ struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedI obj->oHomeY = y; obj->oHomeZ = z; + if (objSetupFunction != 0) { + lua_State* L = gLuaState; + lua_rawgeti(L, LUA_REGISTRYINDEX, objSetupFunction); + smlua_push_object(L, LOT_OBJECT, obj); + if (0 != lua_pcall(L, 1, 0, 0)) { + LOG_LUA("Failed to call the callback: %u, %s", objSetupFunction, lua_tostring(L, -1)); + smlua_logline(); + } + } + struct SyncObject* so = &gSyncObjects[obj->oSyncID]; so->extendedModelId = modelId; so->o = obj; diff --git a/src/pc/lua/smlua_obj_utils.h b/src/pc/lua/smlua_obj_utils.h index 438638bee..a5068067d 100644 --- a/src/pc/lua/smlua_obj_utils.h +++ b/src/pc/lua/smlua_obj_utils.h @@ -4,6 +4,6 @@ #include "behavior_table.h" #include "smlua_model_utils.h" -struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z); +struct Object* spawn_object_sync(enum BehaviorId behaviorId, enum ModelExtendedId modelId, f32 x, f32 y, f32 z, LuaFunction objSetupFunction); #endif diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index 17c1c244d..eb4c16506 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -86,6 +86,23 @@ const char* smlua_to_string(lua_State* L, int index) { return lua_tostring(L, index); } +LuaFunction smlua_to_lua_function(lua_State* L, int index) { + if (lua_type(L, index) == LUA_TNIL) { + return 0; + } + + if (lua_type(L, index) != LUA_TFUNCTION) { + LOG_LUA("smlua_to_lua_function received improper type '%d'", lua_type(L, index)); + smlua_logline(); + gSmLuaConvertSuccess = false; + return 0; + } + + gSmLuaConvertSuccess = true; + lua_pushvalue(L, index); + return luaL_ref(L, LUA_REGISTRYINDEX); +} + void* smlua_to_cobject(lua_State* L, int index, u16 lot) { if (lua_type(L, index) != LUA_TTABLE) { LOG_LUA("smlua_to_cobject received improper type '%d'", lua_type(L, index)); diff --git a/src/pc/lua/smlua_utils.h b/src/pc/lua/smlua_utils.h index b859c973b..b8516d536 100644 --- a/src/pc/lua/smlua_utils.h +++ b/src/pc/lua/smlua_utils.h @@ -2,6 +2,7 @@ #define SMLUA_UTILS_H extern u8 gSmLuaConvertSuccess; +typedef int LuaFunction; f32* smlua_get_vec3f_from_buffer(void); s16* smlua_get_vec3s_from_buffer(void); @@ -13,6 +14,7 @@ bool smlua_to_boolean(lua_State* L, int index); lua_Integer smlua_to_integer(lua_State* L, int index); lua_Number smlua_to_number(lua_State* L, int index); const char* smlua_to_string(lua_State* L, int index); +LuaFunction smlua_to_lua_function(lua_State* L, int index); void* smlua_to_cobject(lua_State* L, int index, u16 lot); void* smlua_to_cpointer(lua_State* L, int index, u16 lvt); struct LSTNetworkType smlua_to_lnt(lua_State* L, int index);