mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-28 23:13:02 +00:00
Add define_custom_obj_fields() to Lua
This commit is contained in:
parent
bac0879ee7
commit
9c7036afe3
9 changed files with 301 additions and 27 deletions
|
@ -1,9 +1,9 @@
|
||||||
_CObject = {
|
_CObject = {
|
||||||
__index = function (t,k)
|
__index = function (t,k)
|
||||||
return _get_field(t['_lot'], t['_pointer'], k)
|
return _get_field(t['_lot'], t['_pointer'], k, t)
|
||||||
end,
|
end,
|
||||||
__newindex = function (t,k,v)
|
__newindex = function (t,k,v)
|
||||||
_set_field(t['_lot'], t['_pointer'], k, v)
|
_set_field(t['_lot'], t['_pointer'], k, v, t)
|
||||||
end,
|
end,
|
||||||
__eq = function (a, b)
|
__eq = function (a, b)
|
||||||
return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil
|
return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
lua_State* gLuaState = NULL;
|
lua_State* gLuaState = NULL;
|
||||||
u8 gLuaInitializingScript = 0;
|
u8 gLuaInitializingScript = 0;
|
||||||
|
struct ModListEntry* gLuaLoadingEntry = NULL;
|
||||||
|
struct ModListEntry* gLuaActiveEntry = NULL;
|
||||||
|
|
||||||
static void smlua_exec_file(char* path) {
|
static void smlua_exec_file(char* path) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
|
@ -46,6 +48,7 @@ static void smlua_load_script(char* path, u16 remoteIndex) {
|
||||||
|
|
||||||
// load per-file globals
|
// load per-file globals
|
||||||
smlua_sync_table_init_globals(path, remoteIndex);
|
smlua_sync_table_init_globals(path, remoteIndex);
|
||||||
|
smlua_cobject_init_per_file_globals(path);
|
||||||
|
|
||||||
// run chunks
|
// run chunks
|
||||||
if (lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK) {
|
if (lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK) {
|
||||||
|
@ -97,7 +100,11 @@ void smlua_init(void) {
|
||||||
struct ModListEntry* entry = &table->entries[i];
|
struct ModListEntry* entry = &table->entries[i];
|
||||||
if (!entry->enabled) { continue; }
|
if (!entry->enabled) { continue; }
|
||||||
LOG_INFO(" %s", entry->path);
|
LOG_INFO(" %s", entry->path);
|
||||||
|
gLuaLoadingEntry = entry;
|
||||||
|
gLuaActiveEntry = entry;
|
||||||
smlua_load_script(entry->path, entry->remoteIndex);
|
smlua_load_script(entry->path, entry->remoteIndex);
|
||||||
|
gLuaActiveEntry = NULL;
|
||||||
|
gLuaLoadingEntry = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
extern lua_State* gLuaState;
|
extern lua_State* gLuaState;
|
||||||
extern u8 gLuaInitializingScript;
|
extern u8 gLuaInitializingScript;
|
||||||
|
extern struct ModListEntry* gLuaLoadingEntry;
|
||||||
|
extern struct ModListEntry* gLuaActiveEntry;
|
||||||
|
|
||||||
void smlua_init(void);
|
void smlua_init(void);
|
||||||
void smlua_update(void);
|
void smlua_update(void);
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "audio/external.h"
|
#include "audio/external.h"
|
||||||
#include "object_fields.h"
|
#include "object_fields.h"
|
||||||
#include "pc/djui/djui_hud_utils.h"
|
#include "pc/djui/djui_hud_utils.h"
|
||||||
|
#include "pc/lua/smlua.h"
|
||||||
#include "pc/lua/smlua_anim_utils.h"
|
#include "pc/lua/smlua_anim_utils.h"
|
||||||
|
#include "pc/mod_list.h"
|
||||||
|
|
||||||
#define LUA_VEC3S_FIELD_COUNT 3
|
#define LUA_VEC3S_FIELD_COUNT 3
|
||||||
static struct LuaObjectField sVec3sFields[LUA_VEC3S_FIELD_COUNT] = {
|
static struct LuaObjectField sVec3sFields[LUA_VEC3S_FIELD_COUNT] = {
|
||||||
|
@ -69,8 +71,183 @@ bool smlua_valid_lvt(u16 lvt) {
|
||||||
return (lvt < LVT_MAX);
|
return (lvt < LVT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// obj behavior //
|
||||||
|
//////////////////
|
||||||
|
|
||||||
|
static int smlua_func_define_custom_obj_fields(lua_State* L) {
|
||||||
|
LUA_STACK_CHECK_BEGIN();
|
||||||
|
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
|
||||||
|
|
||||||
|
if (lua_type(L, 1) != LUA_TTABLE) {
|
||||||
|
LOG_LUA("Invalid parameter for define_custom_obj_fields()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gLuaLoadingEntry == NULL) {
|
||||||
|
LOG_LUA("define_custom_obj_fields() can only be called on load.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get _custom_object_fields
|
||||||
|
lua_getglobal(L, "_G"); // get global table
|
||||||
|
lua_getfield(L, LUA_REGISTRYINDEX, gLuaLoadingEntry->path); // push file's "global" table
|
||||||
|
int fileGlobalIndex = lua_gettop(L);
|
||||||
|
lua_getfield(L, fileGlobalIndex, "_custom_object_fields");
|
||||||
|
lua_remove(L, -2); // remove file's "global" table
|
||||||
|
lua_remove(L, -2); // remove global table
|
||||||
|
int customObjectFieldsIndex = lua_gettop(L);
|
||||||
|
|
||||||
|
u32 fieldIndex = 0x1B;
|
||||||
|
|
||||||
|
// table is in the stack at index 't'
|
||||||
|
lua_pushnil(L); // first key
|
||||||
|
int iterationTop = lua_gettop(L);
|
||||||
|
while (lua_next(L, 1) != 0) {
|
||||||
|
int keyIndex = lua_gettop(L) - 1;
|
||||||
|
int valueIndex = lua_gettop(L) - 0;
|
||||||
|
// uses 'key' (at index -2) and 'value' (at index -1)
|
||||||
|
if (lua_type(L, keyIndex) != LUA_TSTRING) {
|
||||||
|
LOG_LUA("Invalid key type for define_custom_obj_fields() : %u", lua_type(L, keyIndex));
|
||||||
|
lua_settop(L, iterationTop);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_type(L, valueIndex) != LUA_TSTRING) {
|
||||||
|
LOG_LUA("Invalid value type for define_custom_obj_fields() : %u", lua_type(L, valueIndex));
|
||||||
|
lua_settop(L, iterationTop);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* key = smlua_to_string(L, keyIndex);
|
||||||
|
if (key[0] != 'o') {
|
||||||
|
LOG_LUA("Invalid key name for define_custom_obj_fields()");
|
||||||
|
lua_settop(L, iterationTop);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* value = smlua_to_string(L, valueIndex);
|
||||||
|
enum LuaValueType lvt = LVT_U32;
|
||||||
|
if (!strcmp(value, "u32")) { lvt = LVT_U32; }
|
||||||
|
else if (!strcmp(value, "s32")) { lvt = LVT_S32; }
|
||||||
|
else if (!strcmp(value, "f32")) { lvt = LVT_F32; }
|
||||||
|
else {
|
||||||
|
LOG_LUA("Invalid value name for define_custom_obj_fields()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep fieldIndex in range
|
||||||
|
if (fieldIndex < 0x1B) {
|
||||||
|
fieldIndex = 0x1B;
|
||||||
|
} else if (fieldIndex > 0x22 && fieldIndex < 0x48) {
|
||||||
|
fieldIndex = 0x48;
|
||||||
|
} else if (fieldIndex > 0x4A) {
|
||||||
|
LOG_LUA("Ran out of custom fields!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushvalue(L, customObjectFieldsIndex);
|
||||||
|
lua_pushvalue(L, keyIndex);
|
||||||
|
lua_newtable(L);
|
||||||
|
{
|
||||||
|
// set fieldIndex
|
||||||
|
lua_pushstring(L, "_fieldIndex");
|
||||||
|
lua_pushinteger(L, fieldIndex);
|
||||||
|
lua_rawset(L, -3);
|
||||||
|
|
||||||
|
// set lvt
|
||||||
|
lua_pushstring(L, "_lvt");
|
||||||
|
lua_pushinteger(L, lvt);
|
||||||
|
lua_rawset(L, -3);
|
||||||
|
}
|
||||||
|
lua_settable(L, -3); // set _custom_object_fields
|
||||||
|
|
||||||
|
fieldIndex++;
|
||||||
|
lua_settop(L, iterationTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, iterationTop);
|
||||||
|
lua_pop(L, 1); // pop key
|
||||||
|
lua_pop(L, 1); // pop _custom_object_fields
|
||||||
|
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyIndex) {
|
||||||
|
LUA_STACK_CHECK_BEGIN();
|
||||||
|
static struct LuaObjectField lof = { 0 };
|
||||||
|
if (lot != LOT_OBJECT) { return NULL; }
|
||||||
|
|
||||||
|
if (gLuaActiveEntry == NULL) {
|
||||||
|
LOG_LUA("Failed to retrieve active mod entry.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get _custom_object_fields
|
||||||
|
lua_getglobal(L, "_G"); // get global table
|
||||||
|
lua_getfield(L, LUA_REGISTRYINDEX, gLuaActiveEntry->path); // push file's "global" table
|
||||||
|
int fileGlobalIndex = lua_gettop(L);
|
||||||
|
lua_getfield(L, fileGlobalIndex, "_custom_object_fields");
|
||||||
|
lua_remove(L, -2); // remove file's "global" table
|
||||||
|
lua_remove(L, -2); // remove global table
|
||||||
|
|
||||||
|
// get value table from key
|
||||||
|
lua_pushvalue(L, keyIndex);
|
||||||
|
lua_rawget(L, -2);
|
||||||
|
if (lua_type(L, -1) != LUA_TTABLE) {
|
||||||
|
lua_pop(L, 1); // pop value table
|
||||||
|
lua_pop(L, 1); // pop _custom_fields
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get _fieldIndex
|
||||||
|
lua_pushstring(L, "_fieldIndex");
|
||||||
|
lua_rawget(L, -2);
|
||||||
|
u32 fieldIndex = smlua_to_integer(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
bool validFieldIndex = (fieldIndex >= 0x1B && fieldIndex <= 0x22) || (fieldIndex >= 0x48 && fieldIndex <= 0x4A);
|
||||||
|
if (!gSmLuaConvertSuccess || !validFieldIndex) {
|
||||||
|
lua_pop(L, 1); // pop value table
|
||||||
|
lua_pop(L, 1); // pop _custom_fields
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get _lvt
|
||||||
|
lua_pushstring(L, "_lvt");
|
||||||
|
lua_rawget(L, -2);
|
||||||
|
u32 lvt = smlua_to_integer(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
bool validLvt = (lvt == LVT_U32 || lvt == LVT_S32 || lvt == LVT_F32);
|
||||||
|
if (!gSmLuaConvertSuccess || !validLvt) {
|
||||||
|
lua_pop(L, 1); // pop value table
|
||||||
|
lua_pop(L, 1); // pop _custom_fields
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lof.immutable = false;
|
||||||
|
//lof.key = key;
|
||||||
|
lof.lot = LOT_NONE;
|
||||||
|
lof.valueOffset = offsetof(struct Object, rawData.asU32[fieldIndex]);
|
||||||
|
lof.valueType = lvt;
|
||||||
|
|
||||||
|
lua_pop(L, 1); // pop value table
|
||||||
|
lua_pop(L, 1); // pop _custom_fields
|
||||||
|
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
return &lof;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// CObject get/set //
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
static int smlua__get_field(lua_State* L) {
|
static int smlua__get_field(lua_State* L) {
|
||||||
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
LUA_STACK_CHECK_BEGIN();
|
||||||
|
if (!smlua_functions_valid_param_count(L, 4)) { return 0; }
|
||||||
|
|
||||||
enum LuaObjectType lot = smlua_to_integer(L, 1);
|
enum LuaObjectType lot = smlua_to_integer(L, 1);
|
||||||
if (!gSmLuaConvertSuccess) { return 0; }
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
@ -100,12 +277,17 @@ static int smlua__get_field(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LuaObjectField* data = smlua_get_object_field(lot, key);
|
struct LuaObjectField* data = smlua_get_object_field(lot, key);
|
||||||
|
if (data == NULL) {
|
||||||
|
data = smlua_get_custom_field(L, lot, 3);
|
||||||
|
}
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
LOG_LUA("_get_field on invalid key '%s', lot '%d'", key, lot);
|
LOG_LUA("_get_field on invalid key '%s', lot '%d'", key, lot);
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
|
|
||||||
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
|
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
|
||||||
switch (data->valueType) {
|
switch (data->valueType) {
|
||||||
case LVT_BOOL: lua_pushboolean(L, *(u8* )p); break;
|
case LVT_BOOL: lua_pushboolean(L, *(u8* )p); break;
|
||||||
|
@ -146,7 +328,8 @@ static int smlua__get_field(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smlua__set_field(lua_State* L) {
|
static int smlua__set_field(lua_State* L) {
|
||||||
if (!smlua_functions_valid_param_count(L, 4)) { return 0; }
|
LUA_STACK_CHECK_BEGIN();
|
||||||
|
if (!smlua_functions_valid_param_count(L, 5)) { return 0; }
|
||||||
|
|
||||||
enum LuaObjectType lot = smlua_to_integer(L, 1);
|
enum LuaObjectType lot = smlua_to_integer(L, 1);
|
||||||
if (!gSmLuaConvertSuccess) { return 0; }
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
@ -176,6 +359,9 @@ static int smlua__set_field(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LuaObjectField* data = smlua_get_object_field(lot, key);
|
struct LuaObjectField* data = smlua_get_object_field(lot, key);
|
||||||
|
if (data == NULL) {
|
||||||
|
data = smlua_get_custom_field(L, lot, 3);
|
||||||
|
}
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
LOG_LUA("_set_field on invalid key '%s'", key);
|
LOG_LUA("_set_field on invalid key '%s'", key);
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
|
@ -191,17 +377,17 @@ static int smlua__set_field(lua_State* L) {
|
||||||
void* valuePointer = NULL;
|
void* valuePointer = NULL;
|
||||||
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
|
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
|
||||||
switch (data->valueType) {
|
switch (data->valueType) {
|
||||||
case LVT_BOOL:*(u8*) p = smlua_to_boolean(L, -1); break;
|
case LVT_BOOL:*(u8*) p = smlua_to_boolean(L, 4); break;
|
||||||
case LVT_U8: *(u8*) p = smlua_to_integer(L, -1); break;
|
case LVT_U8: *(u8*) p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_U16: *(u16*)p = smlua_to_integer(L, -1); break;
|
case LVT_U16: *(u16*)p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_U32: *(u32*)p = smlua_to_integer(L, -1); break;
|
case LVT_U32: *(u32*)p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_S8: *(s8*) p = smlua_to_integer(L, -1); break;
|
case LVT_S8: *(s8*) p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_S16: *(s16*)p = smlua_to_integer(L, -1); break;
|
case LVT_S16: *(s16*)p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_S32: *(s32*)p = smlua_to_integer(L, -1); break;
|
case LVT_S32: *(s32*)p = smlua_to_integer(L, 4); break;
|
||||||
case LVT_F32: *(f32*)p = smlua_to_number(L, -1); break;
|
case LVT_F32: *(f32*)p = smlua_to_number(L, 4); break;
|
||||||
|
|
||||||
case LVT_COBJECT_P:
|
case LVT_COBJECT_P:
|
||||||
valuePointer = smlua_to_cobject(L, -1, data->lot);
|
valuePointer = smlua_to_cobject(L, 4, data->lot);
|
||||||
if (gSmLuaConvertSuccess) {
|
if (gSmLuaConvertSuccess) {
|
||||||
*(u8**)p = valuePointer;
|
*(u8**)p = valuePointer;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +403,7 @@ static int smlua__set_field(lua_State* L) {
|
||||||
case LVT_F32_P:
|
case LVT_F32_P:
|
||||||
case LVT_BEHAVIORSCRIPT_P:
|
case LVT_BEHAVIORSCRIPT_P:
|
||||||
case LVT_OBJECTANIMPOINTER_P:
|
case LVT_OBJECTANIMPOINTER_P:
|
||||||
valuePointer = smlua_to_cpointer(L, -1, data->valueType);
|
valuePointer = smlua_to_cpointer(L, 4, data->valueType);
|
||||||
if (gSmLuaConvertSuccess) {
|
if (gSmLuaConvertSuccess) {
|
||||||
*(u8**)p = valuePointer;
|
*(u8**)p = valuePointer;
|
||||||
}
|
}
|
||||||
|
@ -234,9 +420,14 @@ static int smlua__set_field(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LUA_STACK_CHECK_END();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// bind //
|
||||||
|
//////////
|
||||||
|
|
||||||
void smlua_cobject_init_globals(void) {
|
void smlua_cobject_init_globals(void) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
|
|
||||||
|
@ -285,9 +476,25 @@ void smlua_cobject_init_globals(void) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void smlua_cobject_init_per_file_globals(char* path) {
|
||||||
|
lua_State* L = gLuaState;
|
||||||
|
|
||||||
|
lua_getfield(L, LUA_REGISTRYINDEX, path); // push per-file globals
|
||||||
|
|
||||||
|
{
|
||||||
|
lua_pushstring(L, "_custom_object_fields");
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pop(L, 1); // pop per-file globals
|
||||||
|
}
|
||||||
|
|
||||||
void smlua_bind_cobject(void) {
|
void smlua_bind_cobject(void) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
|
|
||||||
|
smlua_bind_function(L, "define_custom_obj_fields", smlua_func_define_custom_obj_fields);
|
||||||
|
|
||||||
smlua_bind_function(L, "_get_field", smlua__get_field);
|
smlua_bind_function(L, "_get_field", smlua__get_field);
|
||||||
smlua_bind_function(L, "_set_field", smlua__set_field);
|
smlua_bind_function(L, "_set_field", smlua__set_field);
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct LuaObjectTable {
|
||||||
bool smlua_valid_lot(u16 lot);
|
bool smlua_valid_lot(u16 lot);
|
||||||
bool smlua_valid_lvt(u16 lvt);
|
bool smlua_valid_lvt(u16 lvt);
|
||||||
void smlua_cobject_init_globals(void);
|
void smlua_cobject_init_globals(void);
|
||||||
|
void smlua_cobject_init_per_file_globals(char* path);
|
||||||
void smlua_bind_cobject(void);
|
void smlua_bind_cobject(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,10 +1,10 @@
|
||||||
char gSmluaConstants[] = ""
|
char gSmluaConstants[] = ""
|
||||||
"_CObject = {\n"
|
"_CObject = {\n"
|
||||||
" __index = function (t,k)\n"
|
" __index = function (t,k)\n"
|
||||||
" return _get_field(t['_lot'], t['_pointer'], k)\n"
|
" return _get_field(t['_lot'], t['_pointer'], k, t)\n"
|
||||||
" end,\n"
|
" end,\n"
|
||||||
" __newindex = function (t,k,v)\n"
|
" __newindex = function (t,k,v)\n"
|
||||||
" _set_field(t['_lot'], t['_pointer'], k, v)\n"
|
" _set_field(t['_lot'], t['_pointer'], k, v, t)\n"
|
||||||
" end,\n"
|
" end,\n"
|
||||||
" __eq = function (a, b)\n"
|
" __eq = function (a, b)\n"
|
||||||
" return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil\n"
|
" return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil\n"
|
||||||
|
|
|
@ -79,6 +79,10 @@ int smlua_func_init_mario_after_warp(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// bind //
|
||||||
|
//////////
|
||||||
|
|
||||||
void smlua_bind_functions(void) {
|
void smlua_bind_functions(void) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,19 @@ static u64* sBehaviorOffset = &gPcDebug.bhvOffset;
|
||||||
struct LuaHookedEvent {
|
struct LuaHookedEvent {
|
||||||
int reference[MAX_HOOKED_REFERENCES];
|
int reference[MAX_HOOKED_REFERENCES];
|
||||||
int count;
|
int count;
|
||||||
|
struct ModListEntry* entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 };
|
static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 };
|
||||||
|
|
||||||
|
static int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct ModListEntry* activeEntry) {
|
||||||
|
struct ModListEntry* prev = gLuaActiveEntry;
|
||||||
|
gLuaActiveEntry = activeEntry;
|
||||||
|
int rc = lua_pcall(L, nargs, nresults, errfunc);
|
||||||
|
gLuaActiveEntry = prev;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int smlua_hook_event(lua_State* L) {
|
int smlua_hook_event(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
||||||
|
@ -44,6 +53,7 @@ int smlua_hook_event(lua_State* L) {
|
||||||
|
|
||||||
hook->reference[hook->count] = ref;
|
hook->reference[hook->count] = ref;
|
||||||
hook->count++;
|
hook->count++;
|
||||||
|
hook->entry = gLuaActiveEntry;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +67,7 @@ void smlua_call_event_hooks(enum LuaHookedEventType hookType) {
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 0, 0, 0)) {
|
if (0 != smlua_call_hook(L, 0, 0, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the event_hook callback: %u, %s", hookType, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the event_hook callback: %u, %s", hookType, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -80,7 +90,7 @@ void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct
|
||||||
lua_remove(L, -2);
|
lua_remove(L, -2);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 1, 0, 0)) {
|
if (0 != smlua_call_hook(L, 1, 0, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -109,7 +119,7 @@ void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struc
|
||||||
lua_remove(L, -2);
|
lua_remove(L, -2);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 2, 0, 0)) {
|
if (0 != smlua_call_hook(L, 2, 0, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -141,7 +151,7 @@ void smlua_call_event_hooks_interact_params(enum LuaHookedEventType hookType, st
|
||||||
lua_pushboolean(L, interactValue);
|
lua_pushboolean(L, interactValue);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 4, 0, 0)) {
|
if (0 != smlua_call_hook(L, 4, 0, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -164,7 +174,7 @@ void smlua_call_event_hooks_network_player_param(enum LuaHookedEventType hookTyp
|
||||||
lua_remove(L, -2);
|
lua_remove(L, -2);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 1, 0, 0)) {
|
if (0 != smlua_call_hook(L, 1, 0, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -180,6 +190,7 @@ struct LuaHookedMarioAction {
|
||||||
u32 action;
|
u32 action;
|
||||||
u32 interactionType;
|
u32 interactionType;
|
||||||
int reference;
|
int reference;
|
||||||
|
struct ModListEntry* entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_HOOKED_ACTIONS 128
|
#define MAX_HOOKED_ACTIONS 128
|
||||||
|
@ -190,6 +201,12 @@ static int sHookedMarioActionsCount = 0;
|
||||||
int smlua_hook_mario_action(lua_State* L) {
|
int smlua_hook_mario_action(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_range(L, 2, 3)) { return 0; }
|
if (!smlua_functions_valid_param_range(L, 2, 3)) { return 0; }
|
||||||
|
|
||||||
|
if (gLuaLoadingEntry == NULL) {
|
||||||
|
LOG_LUA("hook_mario_action() can only be called on load.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int paramCount = lua_gettop(L);
|
int paramCount = lua_gettop(L);
|
||||||
|
|
||||||
if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) {
|
if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) {
|
||||||
|
@ -228,6 +245,7 @@ int smlua_hook_mario_action(lua_State* L) {
|
||||||
hooked->action = action;
|
hooked->action = action;
|
||||||
hooked->interactionType = interactionType;
|
hooked->interactionType = interactionType;
|
||||||
hooked->reference = ref;
|
hooked->reference = ref;
|
||||||
|
hooked->entry = gLuaActiveEntry;
|
||||||
if (!gSmLuaConvertSuccess) { return 0; }
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
|
||||||
sHookedMarioActionsCount++;
|
sHookedMarioActionsCount++;
|
||||||
|
@ -238,9 +256,10 @@ bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
if (L == NULL) { return false; }
|
if (L == NULL) { return false; }
|
||||||
for (int i = 0; i < sHookedMarioActionsCount; i++) {
|
for (int i = 0; i < sHookedMarioActionsCount; i++) {
|
||||||
if (sHookedMarioActions[i].action == m->action) {
|
struct LuaHookedMarioAction* hook = &sHookedMarioActions[i];
|
||||||
|
if (hook->action == m->action) {
|
||||||
// push the callback onto the stack
|
// push the callback onto the stack
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sHookedMarioActions[i].reference);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference);
|
||||||
|
|
||||||
// push mario state
|
// push mario state
|
||||||
lua_getglobal(L, "gMarioStates");
|
lua_getglobal(L, "gMarioStates");
|
||||||
|
@ -249,7 +268,7 @@ bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) {
|
||||||
lua_remove(L, -2);
|
lua_remove(L, -2);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 1, 1, 0)) {
|
if (0 != smlua_call_hook(L, 1, 1, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the action callback: %u, %s", m->action, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the action callback: %u, %s", m->action, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -289,6 +308,7 @@ struct LuaHookedBehavior {
|
||||||
BehaviorScript behavior[2];
|
BehaviorScript behavior[2];
|
||||||
int initReference;
|
int initReference;
|
||||||
int loopReference;
|
int loopReference;
|
||||||
|
struct ModListEntry* entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_HOOKED_BEHAVIORS 256
|
#define MAX_HOOKED_BEHAVIORS 256
|
||||||
|
@ -321,6 +341,11 @@ int smlua_hook_behavior(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_count(L, 4)) { return 0; }
|
if (!smlua_functions_valid_param_count(L, 4)) { return 0; }
|
||||||
|
|
||||||
|
if (gLuaLoadingEntry == NULL) {
|
||||||
|
LOG_LUA("hook_behavior() can only be called on load.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
|
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
|
||||||
LOG_LUA("Hooked behaviors exceeded maximum references!");
|
LOG_LUA("Hooked behaviors exceeded maximum references!");
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
|
@ -376,6 +401,7 @@ int smlua_hook_behavior(lua_State* L) {
|
||||||
hooked->behavior[1] = (((unsigned int) (((unsigned int)(0x39) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(customBehaviorId) & ((0x01 << (16)) - 1)) << (0)))); // gross. this is ID(customBehaviorId)
|
hooked->behavior[1] = (((unsigned int) (((unsigned int)(0x39) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(customBehaviorId) & ((0x01 << (16)) - 1)) << (0)))); // gross. this is ID(customBehaviorId)
|
||||||
hooked->initReference = initReference;
|
hooked->initReference = initReference;
|
||||||
hooked->loopReference = loopReference;
|
hooked->loopReference = loopReference;
|
||||||
|
hooked->entry = gLuaActiveEntry;
|
||||||
|
|
||||||
sHookedBehaviorsCount++;
|
sHookedBehaviorsCount++;
|
||||||
|
|
||||||
|
@ -413,7 +439,7 @@ bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* ob
|
||||||
smlua_push_object(L, LOT_OBJECT, object);
|
smlua_push_object(L, LOT_OBJECT, object);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 1, 0, 0)) {
|
if (0 != smlua_call_hook(L, 1, 0, 0, hooked->entry)) {
|
||||||
LOG_LUA("Failed to call the behavior callback: %u, %s", hooked->behaviorId, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the behavior callback: %u, %s", hooked->behaviorId, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
return true;
|
return true;
|
||||||
|
@ -433,6 +459,7 @@ struct LuaHookedChatCommand {
|
||||||
char* command;
|
char* command;
|
||||||
char* description;
|
char* description;
|
||||||
int reference;
|
int reference;
|
||||||
|
struct ModListEntry* entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_HOOKED_CHAT_COMMANDS 64
|
#define MAX_HOOKED_CHAT_COMMANDS 64
|
||||||
|
@ -444,6 +471,11 @@ int smlua_hook_chat_command(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
||||||
|
|
||||||
|
if (gLuaLoadingEntry == NULL) {
|
||||||
|
LOG_LUA("hook_chat_command() can only be called on load.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sHookedChatCommandsCount >= MAX_HOOKED_CHAT_COMMANDS) {
|
if (sHookedChatCommandsCount >= MAX_HOOKED_CHAT_COMMANDS) {
|
||||||
LOG_LUA("Hooked chat command exceeded maximum references!");
|
LOG_LUA("Hooked chat command exceeded maximum references!");
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
|
@ -475,6 +507,7 @@ int smlua_hook_chat_command(lua_State* L) {
|
||||||
hooked->command = strdup(command);
|
hooked->command = strdup(command);
|
||||||
hooked->description = strdup(description);
|
hooked->description = strdup(description);
|
||||||
hooked->reference = ref;
|
hooked->reference = ref;
|
||||||
|
hooked->entry = gLuaActiveEntry;
|
||||||
if (!gSmLuaConvertSuccess) { return 0; }
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
|
||||||
sHookedChatCommandsCount++;
|
sHookedChatCommandsCount++;
|
||||||
|
@ -508,7 +541,7 @@ bool smlua_call_chat_command_hook(char* command) {
|
||||||
lua_pushstring(L, params);
|
lua_pushstring(L, params);
|
||||||
|
|
||||||
// call the callback
|
// call the callback
|
||||||
if (0 != lua_pcall(L, 1, 1, 0)) {
|
if (0 != smlua_call_hook(L, 1, 1, 0, hook->entry)) {
|
||||||
LOG_LUA("Failed to call the chat command callback: %s, %s", command, lua_tostring(L, -1));
|
LOG_LUA("Failed to call the chat command callback: %s, %s", command, lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
continue;
|
continue;
|
||||||
|
@ -537,11 +570,11 @@ void smlua_display_chat_commands(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// hooked sync table change //
|
// hooked sync table change //
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
int smlua_hook_on_sync_table_change(lua_State* L) {
|
int smlua_hook_on_sync_table_change(lua_State* L) {
|
||||||
LUA_STACK_CHECK_BEGIN();
|
LUA_STACK_CHECK_BEGIN();
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
|
@ -552,6 +585,11 @@ int smlua_hook_on_sync_table_change(lua_State* L) {
|
||||||
int tagIndex = 3;
|
int tagIndex = 3;
|
||||||
int funcIndex = 4;
|
int funcIndex = 4;
|
||||||
|
|
||||||
|
if (gLuaLoadingEntry == NULL) {
|
||||||
|
LOG_LUA("hook_on_sync_table_change() can only be called on load.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (lua_type(L, syncTableIndex) != LUA_TTABLE) {
|
if (lua_type(L, syncTableIndex) != LUA_TTABLE) {
|
||||||
LOG_LUA("Tried to attach a non-table to hook_on_sync_table_change: %d", lua_type(L, syncTableIndex));
|
LOG_LUA("Tried to attach a non-table to hook_on_sync_table_change: %d", lua_type(L, syncTableIndex));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
|
|
|
@ -137,11 +137,26 @@ static void smlua_sync_table_call_hook(int syncTableIndex, int keyIndex, int pre
|
||||||
lua_pushvalue(L, prevValueIndex);
|
lua_pushvalue(L, prevValueIndex);
|
||||||
lua_pushvalue(L, valueIndex);
|
lua_pushvalue(L, valueIndex);
|
||||||
|
|
||||||
|
// get entry
|
||||||
|
u16 modRemoteIndex = smlua_get_integer_field(syncTableIndex, "_remoteIndex");
|
||||||
|
struct ModListEntry* setEntry = NULL;
|
||||||
|
for (int i = 0; i < gModTableCurrent->entryCount; i++) {
|
||||||
|
struct ModListEntry* entry = &gModTableCurrent->entries[i];
|
||||||
|
if (!entry->enabled) { continue; }
|
||||||
|
if (entry->remoteIndex == modRemoteIndex) {
|
||||||
|
setEntry = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// call hook
|
// call hook
|
||||||
|
struct ModListEntry* prev = gLuaActiveEntry;
|
||||||
|
gLuaActiveEntry = setEntry;
|
||||||
if (0 != lua_pcall(L, 3, 0, 0)) {
|
if (0 != lua_pcall(L, 3, 0, 0)) {
|
||||||
LOG_LUA("Failed to call the hook_on_changed callback: %s", lua_tostring(L, -1));
|
LOG_LUA("Failed to call the hook_on_changed callback: %s", lua_tostring(L, -1));
|
||||||
smlua_logline();
|
smlua_logline();
|
||||||
}
|
}
|
||||||
|
gLuaActiveEntry = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pop(L, 1); // pop _hook_on_changed's value
|
lua_pop(L, 1); // pop _hook_on_changed's value
|
||||||
|
|
Loading…
Reference in a new issue