sm64coopdx/src/pc/lua/smlua.c
MysterD b364493807 Even more Lua improvements
Reorganized autogenerated lua functions into their own file
Grouped up COBJECT LVTs
Partially implemented: struct MarioBodyState, Object, ObjectNode, GraphNodeObject
Reimplemented lua function wrappers for: camera.h, mario.h, mario_actions_*.c, mario_step.h
2022-01-19 19:20:57 -08:00

207 lines
5.5 KiB
C

#include "smlua.h"
lua_State* gLuaState = NULL;
///////////////////
// hooked events //
///////////////////
#define MAX_HOOKED_REFERENCES 64
struct LuaHookedEvent {
int reference[MAX_HOOKED_REFERENCES];
int count;
};
static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 };
int smlua_hook_event(lua_State* L) {
u16 hookType = lua_tointeger(L, -2);
if (hookType >= HOOK_MAX) {
LOG_LUA("LUA: Hook Type: %d exceeds max!", hookType);
return 0;
}
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
if (hook->count >= MAX_HOOKED_REFERENCES) {
LOG_LUA("LUA: Hook Type: %d exceeded maximum references!", hookType);
return 0;
}
hook->reference[hook->count] = luaL_ref(L, LUA_REGISTRYINDEX);
hook->count++;
return 1;
}
void smlua_call_event_hooks(enum LuaHookedEventType hookType) {
lua_State* L = gLuaState;
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
// push the callback onto the stack
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
// call the callback
if (0 != lua_pcall(L, 0, 0, 0)) {
LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1));
continue;
}
}
}
void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m) {
lua_State* L = gLuaState;
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
// push the callback onto the stack
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
// push mario state
lua_getglobal(L, "gMarioStates");
lua_pushinteger(L, m->playerIndex);
lua_gettable(L, -2);
lua_remove(L, -2);
// call the callback
if (0 != lua_pcall(L, 1, 0, 0)) {
LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1));
continue;
}
}
}
////////////////////
// hooked actions //
////////////////////
struct LuaHookedMarioAction {
u32 action;
int reference;
};
#define MAX_HOOKED_ACTIONS 64
static struct LuaHookedMarioAction sHookedMarioActions[MAX_HOOKED_ACTIONS] = { 0 };
static int sHookedMarioActionsCount = 0;
int smlua_hook_mario_action(lua_State* L) {
if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) {
LOG_LUA("LUA: Hooked mario actions exceeded maximum references!");
return 0;
}
struct LuaHookedMarioAction* hooked = &sHookedMarioActions[sHookedMarioActionsCount];
hooked->action = lua_tointeger(L, -2);
hooked->reference = luaL_ref(L, LUA_REGISTRYINDEX);
sHookedMarioActionsCount++;
return 1;
}
bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) {
lua_State* L = gLuaState;
for (int i = 0; i < sHookedMarioActionsCount; i++) {
if (sHookedMarioActions[i].action == m->action) {
// push the callback onto the stack
lua_rawgeti(L, LUA_REGISTRYINDEX, sHookedMarioActions[i].reference);
// push mario state
lua_getglobal(L, "gMarioStates");
lua_pushinteger(L, m->playerIndex);
lua_gettable(L, -2);
lua_remove(L, -2);
// call the callback
if (0 != lua_pcall(L, 1, 1, 0)) {
LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1));
continue;
}
// output the return value
*returnValue = lua_tointeger(L, -1);
lua_pop(L, 1);
return true;
}
}
return false;
}
//////////
// main //
//////////
static void smlua_execfile(char* path) {
lua_State* L = gLuaState;
if (luaL_dofile(L, path) != LUA_OK) {
LOG_LUA("LUA: Failed to load lua file.");
puts(lua_tostring(L, lua_gettop(L)));
}
lua_pop(L, lua_gettop(L));
}
static void smlua_init_mario_states(void) {
lua_State* L = gLuaState;
lua_newtable(L);
int t = lua_gettop(gLuaState);
for (int i = 0; i < MAX_PLAYERS; i++) {
lua_pushinteger(L, i);
smlua_push_object(L, LOT_MARIO_STATE, &gMarioStates[i]);
lua_settable(L, t);
}
lua_setglobal(L, "gMarioStates");
}
void smlua_init(void) {
gLuaState = luaL_newstate();
lua_State* L = gLuaState;
// load libraries
luaopen_base(L);
//luaopen_coroutine(L);
//luaopen_debug(L);
//luaopen_io(L);
luaL_requiref(L, "math", luaopen_math, 1);
//luaopen_os(L);
//luaopen_package(L);
luaL_requiref(L, "string", luaopen_string, 1);
luaL_requiref(L, "table", luaopen_table, 1);
//luaopen_utf8(L);
lua_pushcfunction(L, smlua_hook_event);
lua_setglobal(L, "hook_event");
lua_pushcfunction(L, smlua_hook_mario_action);
lua_setglobal(L, "hook_mario_action");
smlua_bind_cobject();
smlua_bind_functions();
smlua_bind_functions_autogen();
smlua_execfile("mods/constants.lua");
smlua_init_mario_states();
smlua_execfile("mods/test.lua");
}
void smlua_update(void) {
smlua_call_event_hooks(HOOK_UPDATE);
}
void smlua_shutdown(void) {
lua_State* L = gLuaState;
lua_close(L);
for (int i = 0; i < HOOK_MAX; i++) {
for (int j = 0; j < sHookedEvents[i].count; j++) {
sHookedEvents[i].reference[j] = 0;
}
sHookedEvents[i].count = 0;
}
for (int i = 0; i < sHookedMarioActionsCount; i++) {
sHookedMarioActions[i].action = 0;
sHookedMarioActions[i].reference = 0;
}
sHookedMarioActionsCount = 0;
}