From 549112822aea5d9609c090387fc61d7327d32d04 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 20:33:06 +0100 Subject: [PATCH 01/20] port srb2 hooklib refactor (WIP) lol lmao --- src/b_bot.c | 4 +- src/d_clisrv.c | 8 +- src/d_netcmd.c | 2 +- src/doomtype.h | 24 + src/g_game.c | 10 +- src/hu_stuff.c | 2 +- src/k_kart.c | 4 +- src/lua_hook.h | 189 ++-- src/lua_hooklib.c | 2422 ++++++++++++++++----------------------------- src/lua_script.c | 4 +- src/lua_script.h | 2 +- src/p_enemy.c | 2 +- src/p_inter.c | 16 +- src/p_map.c | 4 +- src/p_mobj.c | 16 +- src/p_setup.c | 4 +- src/p_spec.c | 4 +- src/p_tick.c | 12 +- src/p_user.c | 10 +- src/r_patch.c | 1 + src/s_sound.c | 11 +- src/s_sound.h | 10 + src/y_inter.c | 5 +- 23 files changed, 1069 insertions(+), 1697 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index edaf477ad..53f93374e 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -36,7 +36,7 @@ static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cm return; // Lua can handle it! - if (LUAh_BotAI(sonic, tails, cmd)) + if (LUA_HookBotAI(sonic, tails, cmd)) return; if (tails->player->pflags & (PF_MACESPIN|PF_ITEMHANG)) @@ -122,7 +122,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) //CV_SetValue(&cv_analog2, false); // Let Lua scripts build ticcmds - if (LUAh_BotTiccmd(player, cmd)) + if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd))) return; // We don't have any main character AI, sorry. D: diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6efeffc6f..5b1997e90 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3297,7 +3297,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason) } } - LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting + LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting // Reset player data CL_ClearPlayer(playernum); @@ -4472,10 +4472,10 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) D_AddPostloadFiles(); - LUAh_PlayerJoin(newplayernum); + LUA_HookInt(newplayernum, HOOK(PlayerJoin)); - if (newplayernum == consoleplayer) - LUAh_ServerJoin(); + //if (newplayernum == consoleplayer) + //LUA_ServerJoin(); #ifdef HAVE_DISCORDRPC DRPC_UpdatePresence(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 281fb8856..2968b4a65 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3114,7 +3114,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) SetPlayerSkinByNum(0, cv_chooseskin.value-1); //mapnumber = M_MapNumber(mapname[3], mapname[4]); - //LUAh_MapChange(mapnumber); + //LUA_HookInt(mapnumber, HOOK(MapChange)); demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; demo.savebutton = 0; diff --git a/src/doomtype.h b/src/doomtype.h index d7ad320c8..429eba77e 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -365,6 +365,30 @@ typedef UINT32 tic_t; #define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24) #endif +#define TOSTR(x) #x + +typedef UINT8 bitarray_t; + +#define BIT_ARRAY_SIZE(n) (((n) + 7) >> 3) + +static inline int +in_bit_array (const bitarray_t * const array, const int value) +{ + return (array[value >> 3] & (1<<(value & 7))); +} + +static inline void +set_bit_array (bitarray_t * const array, const int value) +{ + array[value >> 3] |= (1<<(value & 7)); +} + +static inline void +unset_bit_array (bitarray_t * const array, const int value) +{ + array[value >> 3] &= ~(1<<(value & 7)); +} + typedef UINT64 precise_t; #endif //__DOOMTYPE__ diff --git a/src/g_game.c b/src/g_game.c index f807b724c..76ea49c17 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1489,7 +1489,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) -Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want! */ if (gamestate == GS_LEVEL) - LUAh_PlayerCmd(player, cmd); + LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); //Reset away view if a command is given. if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) @@ -2727,7 +2727,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) if (starpost) //Don't even bother with looking for a place to spawn. { P_MovePlayerToStarpost(playernum); - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) + LUA_HookPlayer(&players[playernum], HOOK(PlayerSpawn)); // Lua hook for player spawning :) return; } @@ -2783,7 +2783,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) } P_MovePlayerToSpawn(playernum, spawnpoint); - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) + LUA_HookPlayer(&players[playernum], HOOK(PlayerSpawn)); // Lua hook for player spawning :) } mapthing_t *G_FindCTFStart(INT32 playernum) @@ -4384,7 +4384,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); else { - LUAh_MapChange(gamemap); + LUA_HookInt(gamemap, HOOK(MapChange)); S_CheckMap(); G_DoLoadLevel(resetplayer); } @@ -7505,7 +7505,7 @@ void G_DoPlayDemo(char *defdemoname) // didn't start recording right away. demo.deferstart = false; - //LUAh_MapChange(gamemap); + //LUA_HookInt(gamemap, HOOK(MapChange)); displayplayers[0] = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e68888c84..8a999b83f 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1003,7 +1003,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. - if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) + if (LUA_HookPlayerMsg(playernum, target, flags, msg, spam_eatmsg)) return; if (spam_eatmsg) diff --git a/src/k_kart.c b/src/k_kart.c index c27ffec4c..14f9cc580 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -497,10 +497,9 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = { */ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) { - INT32 i; + INT32 i, j; RGBA_t color; UINT8 brightness; - INT32 j; UINT8 colorbrightnesses[16]; UINT16 brightdif; INT32 temp; @@ -523,6 +522,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) color = V_GetColor(i); SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue); brightdif = 256; + for (j = 0; j < 16; j++) { temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]); diff --git a/src/lua_hook.h b/src/lua_hook.h index 921336cd2..a54a09f00 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -13,91 +13,112 @@ #include "r_defs.h" #include "d_player.h" -enum hook { - hook_NetVars=0, - hook_MapChange, - hook_MapLoad, - hook_PlayerJoin, - hook_PreThinkFrame, - hook_ThinkFrame, - hook_PostThinkFrame, - hook_MobjSpawn, - hook_MobjCollide, - hook_MobjMoveCollide, - hook_TouchSpecial, - hook_MobjFuse, - hook_MobjThinker, - hook_BossThinker, - hook_ShouldDamage, - hook_MobjDamage, - hook_MobjDeath, - hook_BossDeath, - hook_MobjRemoved, - hook_JumpSpecial, - hook_AbilitySpecial, - hook_SpinSpecial, - hook_JumpSpinSpecial, - hook_BotTiccmd, - hook_BotAI, - hook_LinedefExecute, - hook_PlayerMsg, - hook_HurtMsg, - hook_PlayerSpawn, - hook_PlayerQuit, - hook_PlayerThink, - hook_MusicChange, - hook_ShouldSpin, //SRB2KART - hook_ShouldExplode, //SRB2KART - hook_ShouldSquish, //SRB2KART - hook_PlayerSpin, //SRB2KART - hook_PlayerExplode, //SRB2KART - hook_PlayerSquish, //SRB2KART - hook_PlayerCmd, //SRB2KART - hook_IntermissionThinker, //SRB2KART - hook_VoteThinker, //SRB2KART - hook_ServerJoin, // SRB2KART - Saturn 32p +/* + * Do you know what an 'X Macro' is? Such a macro is called over each element of + * a list and expands the input. I use it for the hook lists because both an enum + * and array of hook names need to be kept in order. The X Macro handles this + * automatically. + */ + +#define MOBJ_HOOK_LIST(X) \ +X (MobjSpawn),/* P_SpawnMobj */\ +X (MobjCollide),/* PIT_CheckThing */\ +X (MobjMoveCollide),/* tritto */\ +X (TouchSpecial),/* P_TouchSpecialThing */\ +X (MobjFuse),/* when mobj->fuse runs out */\ +X (MobjThinker),/* P_MobjThinker, P_SceneryThinker */\ +X (BossThinker),/* P_GenericBossThinker */\ +X (ShouldDamage),/* P_DamageMobj (Should mobj take damage?) */\ +X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ +X (MobjDeath),/* P_KillMobj */\ +X (BossDeath),/* A_BossDeath */\ +X (MobjRemoved),/* P_RemoveMobj */\ + +#define HOOK_LIST(X) \ +X (NetVars),/* add to archive table (netsave) */\ +X (MapChange),/* (before map load) */\ +X (MapLoad),\ +X (PlayerJoin),/* Got_AddPlayer */\ +X (PreThinkFrame)/* frame (before mobj and player thinkers) */,\ +X (ThinkFrame),/* frame (after mobj and player thinkers) */\ +X (PostThinkFrame),/* frame (at end of tick, ie after overlays, precipitation, specials) */\ +X (JumpSpecial),/* P_DoJumpStuff (Any-jumping) */\ +X (AbilitySpecial),/* P_DoJumpStuff (Double-jumping) */\ +X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ +X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ +X (BotTiccmd),/* B_BuildTiccmd */\ +X (PlayerMsg),/* chat messages */\ +X (HurtMsg),/* imhurttin */\ +X (PlayerSpawn),/* G_SpawnPlayer */\ +X (PlayerQuit),\ +X (IntermissionThinker),/* Y_Ticker */\ +X (PlayerThink),/* P_PlayerThink */\ +X (GameQuit),\ +X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ +X (MusicChange),\ +X (ShouldSpin),/*SRB2KART*/\ +X (ShouldExplode),/*SRB2KART*/\ +X (ShouldSquish),/*SRB2KART*/\ +X (PlayerSpin),/*SRB2KART*/\ +X (PlayerExplode),/*SRB2KART*/\ +X (PlayerSquish),/*SRB2KART*/\ +X (VoteThinker),/*SRB2KART*/\ +X (ServerJoin),/* SRB2KART - Saturn 32p*/\ + +#define STRING_HOOK_LIST(X) \ +X (BotAI),/* B_BuildTailsTiccmd by skin name */\ +X (LinedefExecute),\ + +/* + * I chose to access the hook enums through a macro as well. This could provide + * a hint to lookup the macro's definition instead of the enum's definition. + * (Since each enumeration is not defined in the source code, but by the list + * macros above, it is not greppable.) The name passed to the macro can also be + * grepped and found in the lists above. + */ + +#define MOBJ_HOOK(name) mobjhook_ ## name +#define HOOK(name) hook_ ## name +#define STRING_HOOK(name) stringhook_ ## name + +enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) }; +enum { HOOK_LIST (HOOK) HOOK(MAX) }; +enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) }; + +/* dead simple, LUA_HOOK(GameQuit) */ +#define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) - hook_MAX // last hook -}; -extern const char *const hookNames[]; extern boolean hook_cmd_running; // This is used by PlayerCmd and lua_playerlib to prevent anything from being wirtten to player while we run PlayerCmd. extern int hook_defrosting; -void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) -void LUAh_MapLoad(void); // Hook for map load -void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer -void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) -void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) -void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials) -boolean LUAh_MobjHook(mobj_t *mo, enum hook which); -boolean LUAh_PlayerHook(player_t *plr, enum hook which); -#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); -#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type -#define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type -#define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type -boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type -#define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Hook for P_KillMobj by mobj type -#define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type -#define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type -#define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping) -#define LUAh_AbilitySpecial(player) LUAh_PlayerHook(player, hook_AbilitySpecial) // Hook for P_DoJumpStuff (Double-jumping) -#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinDash (Spin button effect) -#define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air)) -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); // Hook for chat messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages -#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer -void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, - UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes +void LUA_HookVoid(int hook); + +int LUA_HookMobj(mobj_t *, int hook); +int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); +void LUA_HookInt(INT32 integer, int hook); +//void LUA_HookBool(boolean value, int hook); +void LUA_HookBool(int hook); +int LUA_HookPlayer(player_t *, int hook); +int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); + +void LUA_HookThinkFrame(void); +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher); +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); +void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *); +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg, int mute); +int LUA_HookHurtMsg(player_t *, mobj_t *inflictor, mobj_t *source); +int LUA_HookPlayerCanDamage(player_t *, mobj_t *); +void LUA_HookPlayerQuit(player_t *, int); +int LUA_HookPlayerCmd(player_t *, ticcmd_t *); +int LUA_HookMusicChange(const char *oldname, struct MusicChange *); +int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events + + +// No clue what to do about these UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out? UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded? @@ -106,11 +127,3 @@ UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. - -void LUAh_ServerJoin(void); // SRB2KART - Saturn 32p: called by client when joining a server, allows lua to load any sort of config file - -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them. - -void LUAh_IntermissionThinker(void); // Hook for Y_Ticker -void LUAh_VoteThinker(void); // Hook for Y_VoteTicker -#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1aadea9a3..18466bc30 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -24,1663 +24,966 @@ #include "lua_hook.h" #include "lua_hud.h" // hud_running errors -static UINT8 hooksAvailable[(hook_MAX/8)+1]; +#include -const char *const hookNames[hook_MAX+1] = { - "NetVars", - "MapChange", - "MapLoad", - "PlayerJoin", - "PreThinkFrame", - "ThinkFrame", - "PostThinkFrame", - "MobjSpawn", - "MobjCollide", - "MobjMoveCollide", - "TouchSpecial", - "MobjFuse", - "MobjThinker", - "BossThinker", - "ShouldDamage", - "MobjDamage", - "MobjDeath", - "BossDeath", - "MobjRemoved", - "JumpSpecial", - "AbilitySpecial", - "SpinSpecial", - "JumpSpinSpecial", - "BotTiccmd", - "BotAI", - "LinedefExecute", - "PlayerMsg", - "HurtMsg", - "PlayerSpawn", - "PlayerQuit", - "PlayerThink", - "MusicChange", - "ShouldSpin", - "ShouldExplode", - "ShouldSquish", - "PlayerSpin", - "PlayerExplode", - "PlayerSquish", - "PlayerCmd", - "IntermissionThinker", - "VoteThinker", - "ServerJoin", - NULL +/* ========================================================================= + ABSTRACTION + ========================================================================= */ + +static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL }; +static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL }; + +static const char * const stringHookNames[] = { + STRING_HOOK_LIST (TOSTR) NULL }; -// Hook metadata -struct hook_s +typedef struct { + int numHooks; + int *ids; +} hook_t; + +typedef struct { + int numGeneric; + int ref; +} stringhook_t; + +static hook_t hookIds[HOOK(MAX)]; +static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; + +// Lua tables are used to lookup string hook ids. +static stringhook_t stringHooks[STRING_HOOK(MAX)]; + +// This will be indexed by hook id, the value of which fetches the registry. +static int * hookRefs; + +// After a hook errors once, don't print the error again. +static UINT8 * hooksErrored; + +static int errorRef; + +static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) { - struct hook_s *next; - enum hook type; - UINT16 id; - union { - mobjtype_t mt; - char *skinname; - char *funcname; - } s; - boolean error; -}; -typedef struct hook_s* hook_p; + return + ( + mobjHookIds [MT_NULL] [hook_type].numHooks > 0 || + mobjHookIds[mobj_type][hook_type].numHooks > 0 + ); +} -// For each mobj type, a linked list to its thinker and collision hooks. -// That way, we don't have to iterate through all the hooks. -// We could do that with all other mobj hooks, but it would probably just be -// a waste of memory since they are only called occasionally. Probably... -static hook_p mobjthinkerhooks[NUMMOBJTYPES]; -static hook_p mobjcollidehooks[NUMMOBJTYPES]; +static int hook_in_list +( + const char * const name, + const char * const * const list +){ + int type; -// For each mobj type, a linked list for other mobj hooks -static hook_p mobjhooks[NUMMOBJTYPES]; + for (type = 0; list[type] != NULL; ++type) + { + if (strcmp(name, list[type]) == 0) + break; + } -// A linked list for player hooks -static hook_p playerhooks; + return type; +} -// A linked list for linedef executor hooks -static hook_p linedefexecutorhooks; +static void get_table(lua_State *L) +{ + lua_pushvalue(L, -1); + lua_rawget(L, -3); -// For other hooks, a unique linked list -hook_p roothook; + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_createtable(L, 1, 0); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, -5); + } + + lua_remove(L, -2); +} + +static void add_hook_to_table(lua_State *L, int id, int n) +{ + lua_pushnumber(L, id); + lua_rawseti(L, -2, n); +} + +static void add_string_hook(lua_State *L, int type, int id) +{ + stringhook_t * hook = &stringHooks[type]; + + char * string = NULL; + + switch (type) + { + case STRING_HOOK(BotAI): + if (lua_isstring(L, 3)) + { // lowercase copy + string = Z_StrDup(lua_tostring(L, 3)); + strlwr(string); + } + + /*hook.s.skinname = NULL; + if (lua_isstring(L, 2)) + { // lowercase copy + const char *s = lua_tostring(L, 2); + char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1); + do { + *p = tolower(*s); + ++p; + } while(*(++s)); + *p = 0; + }*/ + break; + + case STRING_HOOK(LinedefExecute): + string = Z_StrDup(luaL_checkstring(L, 3)); + strupr(string); + + /*{ // uppercase copy + const char *s = luaL_checkstring(L, 2); + char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1); + do { + *p = toupper(*s); + ++p; + } while(*(++s)); + *p = 0; + }*/ + break; + } + + if (hook->ref > 0) + lua_getref(L, hook->ref); + else + { + lua_newtable(L); + lua_pushvalue(L, -1); + hook->ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + if (string) + { + lua_pushstring(L, string); + get_table(L); + add_hook_to_table(L, id, 1 + lua_objlen(L, -1)); + } + else + add_hook_to_table(L, id, ++hook->numGeneric); +} + +static void add_hook(hook_t *map, int id) +{ + Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids, + PU_STATIC, &map->ids); + map->ids[map->numHooks++] = id; +} + +static void add_mobj_hook(lua_State *L, int hook_type, int id) +{ + mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); + + luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); + + add_hook(&mobjHookIds[mobj_type][hook_type], id); +} // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { - static struct hook_s hook = {NULL, 0, 0, {0}, false}; - static UINT32 nextid; - hook_p hookp, *lastp; + static int nextid; - hook.type = luaL_checkoption(L, 1, NULL, hookNames); - lua_remove(L, 1); - - luaL_checktype(L, 1, LUA_TFUNCTION); + const char * name; + int type; if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); - switch(hook.type) + name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + /* this is a very special case */ + if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX)) { - // Take a mobjtype enum which this hook is specifically for. - case hook_MobjSpawn: - case hook_MobjCollide: - case hook_MobjMoveCollide: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_MobjThinker: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - case hook_HurtMsg: - hook.s.mt = MT_NULL; - if (lua_isnumber(L, 2)) - hook.s.mt = lua_tonumber(L, 2); - luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t"); - break; - case hook_BotAI: - hook.s.skinname = NULL; - if (lua_isstring(L, 2)) - { // lowercase copy - const char *s = lua_tostring(L, 2); - char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1); - do { - *p = tolower(*s); - ++p; - } while(*(++s)); - *p = 0; - } - break; - case hook_LinedefExecute: // Linedef executor functions - { // uppercase copy - const char *s = luaL_checkstring(L, 2); - char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1); - do { - *p = toupper(*s); - ++p; - } while(*(++s)); - *p = 0; - } - break; - case hook_ShouldSpin: - case hook_ShouldExplode: - case hook_ShouldSquish: - case hook_PlayerSpin: - case hook_PlayerExplode: - case hook_PlayerSquish: - default: - break; + add_string_hook(L, type, nextid); } - lua_settop(L, 1); // lua stack contains only the function now. - - hooksAvailable[hook.type/8] |= 1<<(hook.type%8); - - // set hook.id to the highest id + 1 - hook.id = nextid++; - - // Special cases for some hook types (see the comments above mobjthinkerhooks declaration) - switch(hook.type) + else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX)) { - case hook_MobjThinker: - lastp = &mobjthinkerhooks[hook.s.mt]; - break; - case hook_MobjCollide: - case hook_MobjMoveCollide: - lastp = &mobjcollidehooks[hook.s.mt]; - break; - case hook_MobjSpawn: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - lastp = &mobjhooks[hook.s.mt]; - break; - case hook_JumpSpecial: - case hook_AbilitySpecial: - case hook_SpinSpecial: - case hook_JumpSpinSpecial: - case hook_PlayerSpawn: - case hook_PlayerThink: - lastp = &playerhooks; - break; - case hook_LinedefExecute: - lastp = &linedefexecutorhooks; - break; - case hook_ShouldSpin: - case hook_ShouldExplode: - case hook_ShouldSquish: - case hook_PlayerSpin: - case hook_PlayerExplode: - case hook_PlayerSquish: - case hook_ServerJoin: - default: - lastp = &roothook; - break; + add_mobj_hook(L, type, nextid); + } + else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX)) + { + add_hook(&hookIds[type], nextid); + } + else + { + return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); } - // iterate the hook metadata structs - // set lastp to the last hook struct's "next" pointer. - for (hookp = *lastp; hookp; hookp = hookp->next) - lastp = &hookp->next; - // allocate a permanent memory struct to stuff hook. - hookp = ZZ_Alloc(sizeof(struct hook_s)); - memcpy(hookp, &hook, sizeof(struct hook_s)); - // tack it onto the end of the linked list. - *lastp = hookp; + if (!(nextid & 7)) + { + Z_Realloc(hooksErrored, + BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored, + PU_STATIC, &hooksErrored); + hooksErrored[nextid >> 3] = 0; + } + + Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs); // set the hook function in the registry. - lua_getfield(L, LUA_REGISTRYINDEX, "hooks"); - lua_pushvalue(L, 1); - lua_rawseti(L, -2, hook.id); + lua_pushvalue(L, 2);/* the function */ + hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; } int LUA_HookLib(lua_State *L) { - memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1])); - roothook = NULL; - lua_register(L, "addHook", lib_addHook); + lua_pushcfunction(L, LUA_GetErrorMessage); + errorRef = luaL_ref(L, LUA_REGISTRYINDEX); - lua_newtable(L); - lua_setfield(L, LUA_REGISTRYINDEX, "hooks"); + lua_register(L, "addHook", lib_addHook); return 0; } -boolean LUAh_MobjHook(mobj_t *mo, enum hook which) +typedef struct Hook_State Hook_State; +typedef void (*Hook_Callback)(Hook_State *); + +struct Hook_State { + INT32 status;/* return status to calling function */ + void * userdata; + int hook_type; + mobjtype_t mobj_type;/* >0 if mobj hook */ + const char * string;/* used to fetch table, ran first if set */ + int top;/* index of last argument passed to hook */ + int id;/* id to fetch ref */ + int values;/* num arguments passed to hook */ + int results;/* num values returned by hook */ + Hook_Callback results_handler;/* callback when hook successfully returns */ +}; + +enum { + EINDEX = 1,/* error handler */ + SINDEX = 2,/* string itself is pushed in case of string hook */ +}; + +static void push_error_handler(void) { - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) + lua_getref(gL, errorRef); +} + +/* repush hook string */ +static void push_string(void) +{ + lua_pushvalue(gL, SINDEX); +} + +static boolean start_hook_stack(void) +{ + lua_settop(gL, 0); + push_error_handler(); + return true; +} + +static boolean init_hook_type +( + Hook_State * hook, + int status, + int hook_type, + mobjtype_t mobj_type, + const char * string, + int nonzero +){ + hook->status = status; + + if (nonzero) + { + hook->hook_type = hook_type; + hook->mobj_type = mobj_type; + hook->string = string; + return start_hook_stack(); + } + else return false; +} - I_Assert(mo->type < NUMMOBJTYPES); +static boolean prepare_hook +( + Hook_State * hook, + int default_status, + int hook_type +){ + return init_hook_type(hook, default_status, + hook_type, 0, NULL, + hookIds[hook_type].numHooks); +} - if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) +static boolean prepare_mobj_hook +( + Hook_State * hook, + int default_status, + int hook_type, + mobjtype_t mobj_type +){ + return init_hook_type(hook, default_status, + hook_type, mobj_type, NULL, + mobj_hook_available(hook_type, mobj_type)); +} + +static boolean prepare_string_hook +( + Hook_State * hook, + int default_status, + int hook_type, + const char * string +){ + if (init_hook_type(hook, default_status, + hook_type, 0, string, + stringHooks[hook_type].ref)) + { + lua_pushstring(gL, string); + return true; + } + else return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic mobj hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; } -boolean LUAh_PlayerHook(player_t *plr, enum hook which) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = playerhooks; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - LUA_PushUserdata(gL, plr, META_PLAYER); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; +static void init_hook_call +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + hook->top = lua_gettop(gL); + hook->values = values; + hook->results = results; + hook->results_handler = results_handler; } -// Hook for map change (before load) -void LUAh_MapChange(INT16 mapnumber) +static void get_hook(Hook_State *hook, const int *ids, int n) { - hook_p hookp; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - lua_pushinteger(gL, mapnumber); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MapChange) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - } - - lua_settop(gL, 0); + hook->id = ids[n]; + lua_getref(gL, hookRefs[hook->id]); } -// Hook for map load -void LUAh_MapLoad(void) +static void get_hook_from_table(Hook_State *hook, int n) { - hook_p hookp; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - lua_pushinteger(gL, gamemap); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MapLoad) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - } - - lua_settop(gL, 0); + lua_rawgeti(gL, -1, n); + hook->id = lua_tonumber(gL, -1); + lua_pop(gL, 1); + lua_getref(gL, hookRefs[hook->id]); } -// Hook for Got_AddPlayer -void LUAh_PlayerJoin(int playernum) +static int call_single_hook_no_copy(Hook_State *hook) { - hook_p hookp; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - lua_pushinteger(gL, playernum); - - for (hookp = roothook; hookp; hookp = hookp->next) + if (lua_pcall(gL, hook->values, hook->results, EINDEX) == 0) { - if (hookp->type != hook_PlayerJoin) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - } - - lua_settop(gL, 0); -} - -// Hook for frame (before mobj and player thinkers) -void LUAh_PreThinkFrame(void) -{ - hook_p hookp; - int HOOKSINDEX; - // variables used by perf stats - int hook_index = 0; - precise_t time_taken = 0; - if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PreThinkFrame) - continue; - - if (cv_perfstats.value == 4) - time_taken = I_GetPreciseTime(); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - if (cv_perfstats.value == 4) + if (hook->results > 0) { - lua_Debug ar; - time_taken = I_GetPreciseTime() - time_taken; - // we need the function, let's just retrieve it again - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_getinfo(gL, ">S", &ar); - PS_SetPreThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - hook_index++; + (*hook->results_handler)(hook); + lua_pop(gL, hook->results); } } + else + { + /* print the error message once */ + if (cv_debug & DBG_LUA || !in_bit_array(hooksErrored, hook->id)) + { + CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(gL, -1)); + set_bit_array(hooksErrored, hook->id); + } + lua_pop(gL, 1); + } - lua_pop(gL, 2); // Pop error handler and hooks table + return 1; } -// Hook for frame (after mobj and player thinkers) -void LUAh_ThinkFrame(void) +static int call_single_hook(Hook_State *hook) { - hook_p hookp; - int HOOKSINDEX; + int i; + + for (i = -(hook->values) + 1; i <= 0; ++i) + lua_pushvalue(gL, hook->top + i); + + return call_single_hook_no_copy(hook); +} + +static int call_hook_table_for(Hook_State *hook, int n) +{ + int k; + + for (k = 1; k <= n; ++k) + { + get_hook_from_table(hook, k); + call_single_hook(hook); + } + + return n; +} + +static int call_hook_table(Hook_State *hook) +{ + return call_hook_table_for(hook, lua_objlen(gL, -1)); +} + +static int call_mapped(Hook_State *hook, const hook_t *map) +{ + int k; + + for (k = 0; k < map->numHooks; ++k) + { + get_hook(hook, map->ids, k); + call_single_hook(hook); + } + + return map->numHooks; +} + +static int call_string_hooks(Hook_State *hook) +{ + const stringhook_t *map = &stringHooks[hook->hook_type]; + + int calls = 0; + + lua_getref(gL, map->ref); + + /* call generic string hooks first */ + calls += call_hook_table_for(hook, map->numGeneric); + + push_string(); + lua_rawget(gL, -2); + calls += call_hook_table(hook); + + return calls; +} + +static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) +{ + return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); +} + +static int call_hooks +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + int calls = 0; + + init_hook_call(hook, values, results, results_handler); + + if (hook->string) + { + calls += call_string_hooks(hook); + } + else if (hook->mobj_type > 0) + { + /* call generic mobj hooks first */ + calls += call_mobj_type_hooks(hook, MT_NULL); + calls += call_mobj_type_hooks(hook, hook->mobj_type); + + ps_lua_mobjhooks.value.i += calls; + } + else + calls += call_mapped(hook, &hookIds[hook->hook_type]); + + lua_settop(gL, 0); + + return calls; +} + +/* ========================================================================= + COMMON RESULT HANDLERS + ========================================================================= */ + +#define res_none NULL + +static void res_true(Hook_State *hook) +{ + if (lua_toboolean(gL, -1)) + hook->status = true; +} + +static void res_false(Hook_State *hook) +{ + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hook->status = false; +} + +static void res_force(Hook_State *hook) +{ + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + hook->status = 1; // Force yes + else + hook->status = 2; // Force no + } +} + +/* ========================================================================= + GENERALISED HOOKS + ========================================================================= */ + +int LUA_HookMobj(mobj_t *mobj, int hook_type) +{ + Hook_State hook; + if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) + { + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 1, 1, res_true); + } + return hook.status; +} + +int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) +{ + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, t1->type)) + { + LUA_PushUserdata(gL, t1, META_MOBJ); + LUA_PushUserdata(gL, t2, META_MOBJ); + call_hooks(&hook, 2, 1, res_force); + } + return hook.status; +} + +void LUA_HookVoid(int type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, type)) + call_hooks(&hook, 0, 0, res_none); +} + +void LUA_HookInt(INT32 number, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) + { + lua_pushinteger(gL, number); + call_hooks(&hook, 1, 0, res_none); + } +} + +//void LUA_HookBool(boolean value, int hook_type) +void LUA_HookBool(int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) + { + //lua_pushboolean(gL, value); + call_hooks(&hook, 1, 0, res_none); + } +} + +int LUA_HookPlayer(player_t *player, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_true); + } + return hook.status; +} + +int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, cmd, META_TICCMD); + + if (hook_type == HOOK(PlayerCmd)) + hook_cmd_running = true; + + call_hooks(&hook, 2, 1, res_true); + + if (hook_type == HOOK(PlayerCmd)) + hook_cmd_running = false; + } + return hook.status; +} + +/* ========================================================================= + SPECIALIZED HOOKS + ========================================================================= */ + +void LUA_HookThinkFrame(void) +{ + const int type = HOOK(ThinkFrame); + // variables used by perf stats int hook_index = 0; precise_t time_taken = 0; - if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) - return; + Hook_State hook; - lua_pushcfunction(gL, LUA_GetErrorMessage); + const hook_t * map = &hookIds[type]; + int k; - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) + if (prepare_hook(&hook, 0, type)) { - if (hookp->type != hook_ThinkFrame) - continue; + init_hook_call(&hook, 0, 0, res_none); - if (cv_perfstats.value == 3) - time_taken = I_GetPreciseTime(); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - if (cv_perfstats.value == 3) + for (k = 0; k < map->numHooks; ++k) { - lua_Debug ar; - time_taken = I_GetPreciseTime() - time_taken; - // we need the function, let's just retrieve it again - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_getinfo(gL, ">S", &ar); - PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - hook_index++; - } - } + get_hook(&hook, map->ids, k); - lua_pop(gL, 2); // Pop error handler and hooks table -} - -// Hook for frame (at end of tick, ie after overlays, precipitation, specials) -void LUAh_PostThinkFrame(void) -{ - hook_p hookp; - int HOOKSINDEX; - // variables used by perf stats - int hook_index = 0; - precise_t time_taken = 0; - if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PostThinkFrame) - continue; - - if (cv_perfstats.value == 5) - time_taken = I_GetPreciseTime(); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - if (cv_perfstats.value == 5) - { - lua_Debug ar; - time_taken = I_GetPreciseTime() - time_taken; - // we need the function, let's just retrieve it again - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_getinfo(gL, ">S", &ar); - PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - hook_index++; - } - } - - lua_pop(gL, 2); // Pop error handler and hooks table -} - -// Hook for Y_Ticker -void LUAh_IntermissionThinker(void) -{ - hook_p hookp; - int HOOKSINDEX; - - if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage);; - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_IntermissionThinker) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - } - - lua_pop(gL, 2); // Pop error handler and hooks table -} - -// Hook for Y_VoteTicker -void LUAh_VoteThinker(void) -{ - hook_p hookp; - int HOOKSINDEX; - - if (!gL || !(hooksAvailable[hook_VoteThinker/8] & (1<<(hook_VoteThinker%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_VoteThinker) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - } - - lua_pop(gL, 2); // Pop error handler and hooks table -} - - -// Hook for mobj collisions -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) -{ - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; - - I_Assert(thing1->type < NUMMOBJTYPES); - - if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -// Hook for mobj thinkers -boolean LUAh_MobjThinker(mobj_t *mo) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) - return false; - - I_Assert(mo->type < NUMMOBJTYPES); - - if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic mobj thinker hooks - for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_TouchSpecialThing by mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) - return false; - - I_Assert(special->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[special->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic touch special hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_DamageMobj by mobj type (Should mobj take damage?) -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic should damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic mobj damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_KillMobj by mobj type -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // Look for all generic mobj death hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTiccmd -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotTiccmd) - continue; - - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, bot, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for G_BuildTicCmd -boolean hook_cmd_running = false; -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - hook_cmd_running = true; - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerCmd) - continue; - - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - hook_cmd_running = false; - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotAI - || (hookp->s.skinname && strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name))) - continue; - - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 8, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - - // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. - if (lua_istable(gL, -8)) { - boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; -#define CHECKFIELD(field) \ - lua_getfield(gL, -8, #field);\ - if (lua_toboolean(gL, -1))\ - field = true;\ - lua_pop(gL, 1); - - CHECKFIELD(forward) - CHECKFIELD(backward) - CHECKFIELD(left) - CHECKFIELD(right) - CHECKFIELD(strafeleft) - CHECKFIELD(straferight) - CHECKFIELD(jump) - CHECKFIELD(spin) -#undef CHECKFIELD - B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); - } else - B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, -8), lua_toboolean(gL, -7), lua_toboolean(gL, -6), lua_toboolean(gL, -5), lua_toboolean(gL, -4), lua_toboolean(gL, -3), lua_toboolean(gL, -2), lua_toboolean(gL, -1)); - - lua_pop(gL, 8); - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for linedef executors -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) - { - if (strcmp(hookp->s.funcname, line->text)) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, line, META_LINE); - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, sector, META_SECTOR); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for player chat -// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. -// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) -{ - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerMsg) - continue; - - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player - if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c - lua_pushinteger(gL, 3); // type - lua_pushnil(gL); // target - } else if (target == -1) { // sayteam - lua_pushinteger(gL, 1); // type - lua_pushnil(gL); // target - } else if (target == 0) { // say - lua_pushinteger(gL, 0); // type - lua_pushnil(gL); // target - } else { // sayto - lua_pushinteger(gL, 2); // type - LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target + if (cv_perfstats.value == 3) + { + lua_pushvalue(gL, -1);/* need the function again */ + time_taken = I_GetPreciseTime(); } - lua_pushstring(gL, msg); // msg - if (mute) - lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. - else - lua_pushboolean(gL, false); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; + call_single_hook(&hook); + + if (cv_perfstats.value == 3) + { + lua_Debug ar; + time_taken = I_GetPreciseTime() - time_taken; + lua_getinfo(gL, ">S", &ar); + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; + } + } + + lua_settop(gL, 0); + } } -// Hook for hurt messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special->type)) { - if (hookp->type != hook_HurtMsg - || (hookp->s.mt && !(inflictor && hookp->s.mt == inflictor->type))) - continue; + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + call_hooks(&hook, 2, 1, res_true); + } + return hook.status; +} - if (lua_gettop(gL) == 2) +static int damage_hook +( + mobj_t *target, + mobj_t *inflictor, + mobj_t *source, + INT32 damage, + int hook_type, + int values, + Hook_Callback results_handler +){ + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, target->type)) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + if (values == 5) + lua_pushinteger(gL, damage); + call_hooks(&hook, values, 1, results_handler); + } + return hook.status; +} + +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +{ + return damage_hook(target, inflictor, source, damage, + MOBJ_HOOK(ShouldDamage), 5, res_force); +} + +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +{ + return damage_hook(target, inflictor, source, damage, + MOBJ_HOOK(MobjDamage), 5, res_true); +} + +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) +{ + return damage_hook(target, inflictor, source, 0, + MOBJ_HOOK(MobjDeath), 4, res_true); +} + +typedef struct { + mobj_t * tails; + ticcmd_t * cmd; +} BotAI_State; + +static boolean checkbotkey(const char *field) +{ + return lua_toboolean(gL, -1) && strcmp(lua_tostring(gL, -2), field) == 0; +} + +static void res_botai(Hook_State *hook) +{ + BotAI_State *botai = hook->userdata; + + int k[8]; + + int fields = 0; + + // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. + if (lua_istable(gL, -8)) { + lua_pushnil(gL); // key + while (lua_next(gL, -9)) { +#define CHECK(n, f) (checkbotkey(f) ? (k[(n)-1] = 1) : 0) + if ( + CHECK(1, "forward") || CHECK(2, "backward") || + CHECK(3, "left") || CHECK(4, "right") || + CHECK(5, "strafeleft") || CHECK(6, "straferight") || + CHECK(7, "jump") || CHECK(8, "spin") + ){ + if (8 <= ++fields) + { + lua_pop(gL, 2); // pop key and value + break; + } + } + + lua_pop(gL, 1); // pop value +#undef CHECK + } + } else { + while (fields < 8) { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -void LUAh_NetArchiveHook(lua_CFunction archFunc) -{ - hook_p hookp; - int errorhandlerindex; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8)))) - return; - - // stack: tables - I_Assert(lua_gettop(gL) > 0); - I_Assert(lua_istable(gL, -1)); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - errorhandlerindex = lua_gettop(gL); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // tables becomes an upvalue of archFunc - lua_pushvalue(gL, -3); - lua_pushcclosure(gL, archFunc, 1); - // stack: tables, archFunc - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_NetVars) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -2); // archFunc - if (lua_pcall(gL, 1, 0, errorhandlerindex)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); + k[fields] = lua_toboolean(gL, -8 + fields); + fields++; } } - lua_pop(gL, 3); // Pop archFunc, error handler and hooks table - // stack: tables + B_KeysToTiccmd(botai->tails, botai->cmd, + k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]); + + hook->status = true; } -void LUAh_PlayerQuit(player_t *plr, int reason) +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) { - hook_p hookp; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) - return; + const char *skin = ((skin_t *)tails->skin)->name; - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); + Hook_State hook; + BotAI_State botai; - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) + if (prepare_string_hook(&hook, false, STRING_HOOK(BotAI), skin)) { - if (hookp->type != hook_PlayerQuit) - continue; + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); - if (lua_gettop(gL) == 2) + botai.tails = tails; + botai.cmd = cmd; + + hook.userdata = &botai; + + call_hooks(&hook, 2, 8, res_botai); + } + + return hook.status; +} + +void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) +{ + Hook_State hook; + if (prepare_string_hook + (&hook, 0, STRING_HOOK(LinedefExecute), line->text)) + { + LUA_PushUserdata(gL, line, META_LINE); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, sector, META_SECTOR); + ps_lua_mobjhooks.value.i += call_hooks(&hook, 3, 0, res_none); + } +} + +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg, int mute) +{ + Hook_State hook; + if (prepare_hook(&hook, false, HOOK(PlayerMsg))) + { + LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player + if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c + lua_pushinteger(gL, 3); // type + lua_pushnil(gL); // target + } else if (target == -1) { // sayteam + lua_pushinteger(gL, 1); // type + lua_pushnil(gL); // target + } else if (target == 0) { // say + lua_pushinteger(gL, 0); // type + lua_pushnil(gL); // target + } else { // sayto + lua_pushinteger(gL, 2); // type + LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target + } + lua_pushstring(gL, msg); // msg + if (mute) + lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. + else + lua_pushboolean(gL, false); + call_hooks(&hook, 4, 1, res_true); + } + return hook.status; +} + +int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) +{ + Hook_State hook; + if (prepare_hook(&hook, false, HOOK(HurtMsg))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + call_hooks(&hook, 4, 1, res_true); + } + return hook.status; +} + +void LUA_HookNetArchive(lua_CFunction archFunc) +{ + const hook_t * map = &hookIds[HOOK(NetVars)]; + Hook_State hook; + /* this is a remarkable case where the stack isn't reset */ + if (map->numHooks > 0) + { + // stack: tables + I_Assert(lua_gettop(gL) > 0); + I_Assert(lua_istable(gL, -1)); + + push_error_handler(); + lua_insert(gL, EINDEX); + + // tables becomes an upvalue of archFunc + lua_pushvalue(gL, -1); + lua_pushcclosure(gL, archFunc, 1); + // stack: tables, archFunc + + init_hook_call(&hook, 1, 0, res_none); + call_mapped(&hook, map); + + lua_pop(gL, 1); // pop archFunc + lua_remove(gL, EINDEX); // pop error handler + // stack: tables + } +} + +void LUA_HookPlayerQuit(player_t *plr, int reason) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(PlayerQuit))) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + call_hooks(&hook, 2, 0, res_none); + } +} + +boolean hook_cmd_running = false; + +static void update_music_name(struct MusicChange *musicchange) +{ + size_t length; + const char * new = lua_tolstring(gL, -6, &length); + + if (length < 7) + { + strcpy(musicchange->newname, new); + lua_pushvalue(gL, -6);/* may as well keep it for next call */ + } + else + { + memcpy(musicchange->newname, new, 6); + musicchange->newname[6] = '\0'; + lua_pushlstring(gL, new, 6); + } + + lua_replace(gL, -7); +} + +static void res_musicchange(Hook_State *hook) +{ + struct MusicChange *musicchange = hook->userdata; + + // output 1: true, false, or string musicname override + if (lua_isstring(gL, -6)) + update_music_name(musicchange); + else if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) + hook->status = true; + + // output 2: mflags override + if (lua_isnumber(gL, -5)) + *musicchange->mflags = lua_tonumber(gL, -5); + // output 3: looping override + if (lua_isboolean(gL, -4)) + *musicchange->looping = lua_toboolean(gL, -4); + // output 4: position override + if (lua_isnumber(gL, -3)) + *musicchange->position = lua_tonumber(gL, -3); + // output 5: prefadems override + if (lua_isnumber(gL, -2)) + *musicchange->prefadems = lua_tonumber(gL, -2); + // output 6: fadeinms override + if (lua_isnumber(gL, -1)) + *musicchange->fadeinms = lua_tonumber(gL, -1); +} + +int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) +{ + const int type = HOOK(MusicChange); + const hook_t * map = &hookIds[type]; + + Hook_State hook; + + int k; + + if (prepare_hook(&hook, false, type)) + { + init_hook_call(&hook, 7, 6, res_musicchange); + hook.userdata = param; + + lua_pushstring(gL, oldname);/* the only constant value */ + lua_pushstring(gL, param->newname);/* semi constant */ + + for (k = 0; k <= map->numHooks; ++k) { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); + get_hook(&hook, map->ids, k); + + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + lua_pushinteger(gL, *param->mflags); + lua_pushboolean(gL, *param->looping); + lua_pushinteger(gL, *param->position); + lua_pushinteger(gL, *param->prefadems); + lua_pushinteger(gL, *param->fadeinms); + + call_single_hook_no_copy(&hook); } + + lua_settop(gL, 0); } - lua_settop(gL, 0); + return hook.status; } -// Hook for music changes -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, - UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms) +int LUA_HookKey(INT32 keycode, int hooktype) { - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - - if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, hooktype)) { - if (hookp->type != hook_MusicChange) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushstring(gL, oldname); - lua_pushstring(gL, newname); - lua_pushinteger(gL, *mflags); - lua_pushboolean(gL, *looping); - lua_pushinteger(gL, *position); - lua_pushinteger(gL, *prefadems); - lua_pushinteger(gL, *fadeinms); - if (lua_pcall(gL, 7, 6, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); - lua_pop(gL, 1); - continue; - } - - // output 1: true, false, or string musicname override - if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) - hooked = true; - else if (lua_isstring(gL, -6)) - strncpy(newname, lua_tostring(gL, -6), 7); - // output 2: mflags override - if (lua_isnumber(gL, -5)) - *mflags = lua_tonumber(gL, -5); - // output 3: looping override - if (lua_isboolean(gL, -4)) - *looping = lua_toboolean(gL, -4); - // output 4: position override - if (lua_isnumber(gL, -3)) - *position = lua_tonumber(gL, -3); - // output 5: prefadems override - if (lua_isnumber(gL, -2)) - *prefadems = lua_tonumber(gL, -2); - // output 6: fadeinms override - if (lua_isnumber(gL, -1)) - *fadeinms = lua_tonumber(gL, -1); - - lua_pop(gL, 6); + lua_pushinteger(gL, keycode); + call_hooks(&hook, 1, 0, res_true); } - - lua_settop(gL, 0); - newname[6] = 0; - return hooked; + return hook.status; } -// Hook for K_SpinPlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ShouldSpin/8] & (1<<(hook_ShouldSpin%8)))) - return 0; - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldSpin) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} +//// SNED HELP PLS // Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { + /* hook_p hookp; UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. int HOOKSINDEX; @@ -1731,11 +1034,13 @@ UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); return shouldDamage; + */ } // Hook for K_SquishPlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { + /* hook_p hookp; UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. int HOOKSINDEX; @@ -1786,11 +1091,13 @@ UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); return shouldDamage; + */ } // Hook for K_SpinPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) { + /* hook_p hookp; boolean hooked = false; int HOOKSINDEX; @@ -1836,11 +1143,13 @@ boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); return hooked; + */ } // Hook for K_SquishPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { + /* hook_p hookp; boolean hooked = false; int HOOKSINDEX; @@ -1886,11 +1195,13 @@ boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); return hooked; + */ } // Hook for K_ExplodePlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { + /* hook_p hookp; boolean hooked = false; int HOOKSINDEX; @@ -1936,10 +1247,12 @@ boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); return hooked; + */ } void LUAh_ServerJoin(void) { + /* hook_p hookp; int HOOKSINDEX; if (!gL || !(hooksAvailable[hook_ServerJoin/8] & (1<<(hook_ServerJoin%8)))) @@ -1970,4 +1283,5 @@ void LUAh_ServerJoin(void) } lua_settop(gL, 0); + */ } diff --git a/src/lua_script.c b/src/lua_script.c index fb16ad169..b03a34d32 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1659,7 +1659,7 @@ void LUA_Archive(void) } WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. - LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode + LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode ArchiveTables(); if (gL) @@ -1694,7 +1694,7 @@ void LUA_UnArchive(void) } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. - LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode + LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode UnArchiveTables(); if (gL) diff --git a/src/lua_script.h b/src/lua_script.h index 9903315c2..6c8a0c09c 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -65,7 +65,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, int def, int list_ref); int Lua_CreateFieldTable(lua_State *L, const char *const lst[]); -void LUAh_NetArchiveHook(lua_CFunction archFunc); +void LUA_HookNetArchive(lua_CFunction archFunc); // Console wrapper void COM_Lua_f(void); diff --git a/src/p_enemy.c b/src/p_enemy.c index caa85e331..fcd5e4630 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2658,7 +2658,7 @@ void A_BossDeath(mobj_t *mo) } bossjustdie: - if (LUAh_BossDeath(mo)) + if (LUA_HookMobj(mo, MOBJ_HOOK(BossDeath))) return; else if (P_MobjWasRemoved(mo)) return; diff --git a/src/p_inter.c b/src/p_inter.c index 29d7e4739..749568e3c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -284,7 +284,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->flags & MF_BOSS && special->flags2 & MF2_FRET) return; - if (LUAh_TouchSpecial(special, toucher) || P_MobjWasRemoved(special)) + if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) return; if (special->flags & MF_BOSS) @@ -1641,7 +1641,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL); target->health = 0; // This makes it easy to check if something's dead elsewhere. - if (LUAh_MobjDeath(target, inflictor, source) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDeath(target, inflictor, source) || P_MobjWasRemoved(target)) return; // SRB2kart @@ -2397,7 +2397,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Everything above here can't be forced. if (!metalrecording) { - UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage); + UINT8 shouldForce = LUA_HookShouldDamage(target, inflictor, source, damage); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed if (shouldForce == 1) @@ -2438,7 +2438,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && target->fuse) // Invincible return false; - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) return true; if (target->health > 1) @@ -2464,7 +2464,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit return false; - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) return true; if (target->health > 1) @@ -2472,7 +2472,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (target->flags & MF_ENEMY) { - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) return true; } @@ -2501,14 +2501,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Don't run eachother over in special stages and team games and such } - if (LUAh_MobjDamage(target, inflictor, source, damage)) + if (LUA_HookMobjDamage(target, inflictor, source, damage)) return true; P_NiGHTSDamage(target, source); // -5s :( return true; } - if (LUAh_MobjDamage(target, inflictor, source, damage)) + if (LUA_HookMobjDamage(target, inflictor, source, damage)) return true; if (!force && inflictor && (inflictor->flags & MF_FIRE)) diff --git a/src/p_map.c b/src/p_map.c index bd551829d..3d1fc8442 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -449,7 +449,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type + UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -458,7 +458,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // force no collide } { - UINT8 shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type + UINT8 shouldCollide = LUA_Hook2Mobj(tmthing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tmthing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9da7b0235..e29622f22 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6165,7 +6165,7 @@ void P_MobjThinker(mobj_t *mobj) // Special thinker for scenery objects if (mobj->flags & MF_SCENERY) { - if (LUAh_MobjThinker(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker))) return; if (P_MobjWasRemoved(mobj)) @@ -6863,7 +6863,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->fuse--; if (!mobj->fuse) { - if (!LUAh_MobjFuse(mobj)) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -6878,13 +6878,13 @@ void P_MobjThinker(mobj_t *mobj) // Check for a Lua thinker first if (!mobj->player) { - if (LUAh_MobjThinker(mobj) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)) || P_MobjWasRemoved(mobj)) return; } else if (!mobj->player->spectator) { // You cannot short-circuit the player thinker like you can other thinkers. - LUAh_MobjThinker(mobj); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)); if (P_MobjWasRemoved(mobj)) return; } @@ -6909,7 +6909,7 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->flags & MF_BOSS) { - if (LUAh_BossThinker(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(BossThinker))) { if (P_MobjWasRemoved(mobj)) return; @@ -8876,7 +8876,7 @@ void P_MobjThinker(mobj_t *mobj) fixed_t x, y, z; mobj_t *flagmo, *newmobj; - if (!LUAh_MobjFuse(mobj) && !P_MobjWasRemoved(mobj)) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse)) && !P_MobjWasRemoved(mobj)) { switch (mobj->type) { @@ -9467,7 +9467,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! - if (LUAh_MobjSpawn(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjSpawn))) { if (P_MobjWasRemoved(mobj)) return NULL; @@ -10002,7 +10002,7 @@ void P_RemoveMobj(mobj_t *mobj) return; // something already removing this mobj. mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. - LUAh_MobjRemoved(mobj); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! diff --git a/src/p_setup.c b/src/p_setup.c index 93207a3c1..10639e13d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -63,7 +63,7 @@ #include "md5.h" // map MD5 -// for LUAh_MapLoad +// for MapLoad hook #include "lua_script.h" #include "lua_hook.h" @@ -3017,7 +3017,7 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate) } P_PreTicker(2); if (!reloadinggamestate) - LUAh_MapLoad(); + LUA_HookInt(gamemap, HOOK(MapLoad)); } if (rendermode != render_none && !reloadinggamestate) diff --git a/src/p_spec.c b/src/p_spec.c index 5f9ef78a6..cda5f9e63 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -35,7 +35,7 @@ #include "hu_stuff.h" #include "m_misc.h" #include "m_cond.h" //unlock triggers -#include "lua_hook.h" // LUAh_LinedefExecute +#include "lua_hook.h" // LUA_HookLinedefExecute #include "k_kart.h" // SRB2kart #include "console.h" // CON_LogMessage @@ -2856,7 +2856,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 443: // Calls a named Lua function if (line->text) - LUAh_LinedefExecute(line, mo, callsec); + LUA_HookLinedefExecute(line, mo, callsec); else CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(line-lines)); break; diff --git a/src/p_tick.c b/src/p_tick.c index d6243fde9..49d51774e 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -528,7 +528,7 @@ void P_Ticker(boolean run) ps_checkposition_calls.value.i = 0; PS_START_TIMING(ps_lua_prethinkframe_time); - LUAh_PreThinkFrame(); + LUA_HOOK(PreThinkFrame); PS_STOP_TIMING(ps_lua_prethinkframe_time); PS_START_TIMING(ps_playerthink_time); @@ -564,7 +564,7 @@ void P_Ticker(boolean run) } PS_START_TIMING(ps_lua_thinkframe_time); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); PS_STOP_TIMING(ps_lua_thinkframe_time); } @@ -668,7 +668,7 @@ void P_Ticker(boolean run) D_MapChange(gamemap, gametype, encoremode, true, 0, false, false); PS_START_TIMING(ps_lua_postthinkframe_time); - LUAh_PostThinkFrame(); + LUA_HOOK(PostThinkFrame); PS_STOP_TIMING(ps_lua_postthinkframe_time); } @@ -723,7 +723,7 @@ void P_PreTicker(INT32 frames) R_UpdateMobjInterpolators(); - LUAh_PreThinkFrame(); + LUA_HOOK(PreThinkFrame); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -752,7 +752,7 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); P_RunOverlays(); P_RunShadows(); @@ -760,7 +760,7 @@ void P_PreTicker(INT32 frames) P_UpdateSpecials(); P_RespawnSpecials(); - LUAh_PostThinkFrame(); + LUA_HOOK(PostThinkFrame); R_UpdateLevelInterpolators(); R_UpdateViewInterpolation(); diff --git a/src/p_user.c b/src/p_user.c index f8e4de294..027eb5632 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4368,7 +4368,7 @@ void P_PlayerThink(player_t *player) } if (player->playerstate == PST_REBORN) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -4475,7 +4475,7 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -4541,7 +4541,7 @@ void P_PlayerThink(player_t *player) else player->mo->flags2 &= ~MF2_SHADOW; P_DeathThink(player); - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } @@ -4713,7 +4713,7 @@ void P_PlayerThink(player_t *player) if (!player->mo) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // P_MovePlayer removed player->mo. } @@ -4896,7 +4896,7 @@ void P_PlayerThink(player_t *player) if (rendermode != render_none) DoABarrelRoll(player); - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); } // diff --git a/src/r_patch.c b/src/r_patch.c index 37e7a2321..44dd29725 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -14,6 +14,7 @@ #include "byteptr.h" #include "dehacked.h" +#include "doomdef.h" #include "i_video.h" #include "r_data.h" #include "r_draw.h" diff --git a/src/s_sound.c b/src/s_sound.c index 868bccc77..7824051c4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1966,6 +1966,15 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 { char newmusic[7] = {0}; + struct MusicChange hook_param = { + newmusic, + &mflags, + &looping, + &position, + &prefadems, + &fadeinms + }; + if (S_MusicDisabled() || demo.rewinding // Don't mess with music while rewinding! || demo.title) // SRB2Kart: Demos don't interrupt title screen music @@ -1975,7 +1984,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 S_CheckEventMus(newmusic); - if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) + if (LUA_HookMusicChange(music_name, &hook_param)) return; // No Music (empty string) diff --git a/src/s_sound.h b/src/s_sound.h index 887cdd878..9756028d3 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -228,6 +228,16 @@ UINT32 S_GetMusicPosition(void); // Music Playback // +/* this is for the sake of the hook */ +struct MusicChange { + char * newname; + UINT16 * mflags; + boolean * looping; + UINT32 * position; + UINT32 * prefadems; + UINT32 * fadeinms; +}; + // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet diff --git a/src/y_inter.c b/src/y_inter.c index 12fc705ad..456b87168 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -642,7 +642,8 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUAh_IntermissionThinker(); + LUA_HookBool(HOOK(IntermissionThinker)); + intertic++; @@ -1280,7 +1281,7 @@ void Y_VoteTicker(void) if (paused || P_AutoPause() || !voteclient.loaded) return; - LUAh_VoteThinker(); + LUA_HOOK(VoteThinker); votetic++; -- 2.54.0 From 14ec6e067411c0d32f7bae34c1d75a91f6319521 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 18:35:50 +0100 Subject: [PATCH 02/20] serverjoin hook --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5b1997e90..d4b0347ef 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4474,8 +4474,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) LUA_HookInt(newplayernum, HOOK(PlayerJoin)); - //if (newplayernum == consoleplayer) - //LUA_ServerJoin(); + if (newplayernum == consoleplayer) + LUA_HookInt(newplayernum, HOOK(ServerJoin)); #ifdef HAVE_DISCORDRPC DRPC_UpdatePresence(); -- 2.54.0 From 5598526f521f5f2f3329e7dbe916aefe75a5995a Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 18:39:28 +0100 Subject: [PATCH 03/20] delet serverjoin stuff i forgor and add old should spin stuff --- src/lua_hooklib.c | 93 +++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 18466bc30..fcc5662ff 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -980,6 +980,63 @@ int LUA_HookKey(INT32 keycode, int hooktype) //// SNED HELP PLS + +UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) +{ + /* + hook_p hookp; + UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. + int HOOKSINDEX; + if (!gL || !(hooksAvailable[hook_ShouldSpin/8] & (1<<(hook_ShouldSpin%8)))) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); + HOOKSINDEX = lua_gettop(gL); + I_Assert(lua_istable(L, HOOKSINDEX)); + + // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ShouldSpin) + continue; + + ps_lua_mobjhooks.value.i++; + if (lua_gettop(gL) == 2) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + } + lua_rawgeti(gL, HOOKSINDEX, hookp->id); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldDamage; + */ +} + // Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { @@ -1249,39 +1306,3 @@ boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) return hooked; */ } - -void LUAh_ServerJoin(void) -{ - /* - hook_p hookp; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ServerJoin/8] & (1<<(hook_ServerJoin%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ServerJoin) - continue; - - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - } - - lua_settop(gL, 0); - */ -} -- 2.54.0 From 66518ced7538d5769e53a408a63642df86d56a94 Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 21 Nov 2024 20:53:28 +0300 Subject: [PATCH 04/20] Add Should- and Player- Spin/Explode/Squish, and ServerJoin hooks into new hook system --- src/d_clisrv.c | 2 +- src/lua_hooklib.c | 325 ++++------------------------------------------ 2 files changed, 26 insertions(+), 301 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d4b0347ef..2b7e25fd3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4475,7 +4475,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) LUA_HookInt(newplayernum, HOOK(PlayerJoin)); if (newplayernum == consoleplayer) - LUA_HookInt(newplayernum, HOOK(ServerJoin)); + LUA_HookVoid(HOOK(ServerJoin)); #ifdef HAVE_DISCORDRPC DRPC_UpdatePresence(); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index fcc5662ff..05be84b82 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -977,332 +977,57 @@ int LUA_HookKey(INT32 keycode, int hooktype) return hook.status; } +static int kartdamage_hook +( + player_t *player, + mobj_t *inflictor, + mobj_t *source, + int hook_type, + Hook_Callback results_handler +){ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + call_hooks(&hook, 3, 1, results_handler); + } + return hook.status; +} -//// SNED HELP PLS - - +// Hook for K_SpinPlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ShouldSpin/8] & (1<<(hook_ShouldSpin%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldSpin) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; - */ + return kartdamage_hook(player, inflictor, source, HOOK(ShouldSpin), res_force); } // Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ShouldExplode/8] & (1<<(hook_ShouldExplode%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldExplode) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; - */ + return kartdamage_hook(player, inflictor, source, HOOK(ShouldExplode), res_force); } // Hook for K_SquishPlayer. Determines if yes or no we should get damaged reguardless of circumstances. UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_ShouldSquish/8] & (1<<(hook_ShouldSquish%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldSquish) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; - */ + return kartdamage_hook(player, inflictor, source, HOOK(ShouldSquish), res_force); } // Hook for K_SpinPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerSpin/8] & (1<<(hook_PlayerSpin%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerSpin) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; - */ + return kartdamage_hook(player, inflictor, source, HOOK(PlayerSpin), res_true); } // Hook for K_SquishPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerSquish/8] & (1<<(hook_PlayerSquish%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerSquish) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; - */ + return kartdamage_hook(player, inflictor, source, HOOK(PlayerSquish), res_true); } // Hook for K_ExplodePlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { - /* - hook_p hookp; - boolean hooked = false; - int HOOKSINDEX; - if (!gL || !(hooksAvailable[hook_PlayerExplode/8] & (1<<(hook_PlayerExplode%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "hooks"); - HOOKSINDEX = lua_gettop(gL); - I_Assert(lua_istable(L, HOOKSINDEX)); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerExplode) - continue; - - ps_lua_mobjhooks.value.i++; - if (lua_gettop(gL) == 2) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_rawgeti(gL, HOOKSINDEX, hookp->id); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; - */ + return kartdamage_hook(player, inflictor, source, HOOK(PlayerExplode), res_true); } -- 2.54.0 From 3db21bf77810df9b13a523ad9c2ef6038f17634a Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 21 Nov 2024 21:01:00 +0300 Subject: [PATCH 05/20] Fix warning regarding MusicChange hook --- src/lua_hook.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_hook.h b/src/lua_hook.h index a54a09f00..697c6726b 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -12,6 +12,7 @@ #include "r_defs.h" #include "d_player.h" +#include "s_sound.h" /* * Do you know what an 'X Macro' is? Such a macro is called over each element of -- 2.54.0 From a4080980ece7c5038a70e2209ca1d3848d02e2ae Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:03:39 +0100 Subject: [PATCH 06/20] make intermissionthinker use LUA_HookVoid comment out hookbool since unused --- src/lua_hook.h | 1 - src/lua_hooklib.c | 5 ++--- src/y_inter.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 697c6726b..3ca4b8f35 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -99,7 +99,6 @@ int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); void LUA_HookInt(INT32 integer, int hook); //void LUA_HookBool(boolean value, int hook); -void LUA_HookBool(int hook); int LUA_HookPlayer(player_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 05be84b82..2209803e6 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -568,8 +568,7 @@ void LUA_HookInt(INT32 number, int hook_type) } } -//void LUA_HookBool(boolean value, int hook_type) -void LUA_HookBool(int hook_type) +/*void LUA_HookBool(boolean value, int hook_type) { Hook_State hook; if (prepare_hook(&hook, 0, hook_type)) @@ -577,7 +576,7 @@ void LUA_HookBool(int hook_type) //lua_pushboolean(gL, value); call_hooks(&hook, 1, 0, res_none); } -} +}*/ int LUA_HookPlayer(player_t *player, int hook_type) { diff --git a/src/y_inter.c b/src/y_inter.c index 456b87168..be3a6204b 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -642,8 +642,7 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUA_HookBool(HOOK(IntermissionThinker)); - + LUA_HookVoid(HOOK(IntermissionThinker)); intertic++; -- 2.54.0 From f26717954eddcf8407cc796d508fe3252cb00fc0 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:10:49 +0100 Subject: [PATCH 07/20] change those to fit rest of style --- src/k_kart.c | 12 ++++++------ src/lua_hook.h | 20 +++++++++----------- src/lua_hooklib.c | 34 +++++++++++++++++----------------- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 14f9cc580..2950dcccb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2312,7 +2312,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto UINT8 scoremultiply = 1; // PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too. boolean force = false; // Used to check if Lua ShouldSpin should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldSpin(player, inflictor, source); + UINT8 shouldForce = LUA_HookShouldSpin(player, inflictor, source); if (P_MobjWasRemoved(player->mo)) return; // mobj was removed (in theory that shouldn't happen) @@ -2345,7 +2345,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto } } - if (LUAh_PlayerSpin(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. + if (LUA_HookPlayerSpin(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. return; if (source && source != player->mo && source->player) @@ -2453,7 +2453,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) UINT8 scoremultiply = 1; // PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too. boolean force = false; // Used to check if Lua ShouldSquish should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldSquish(player, inflictor, source); + UINT8 shouldForce = LUA_HookShouldSquish(player, inflictor, source); if (P_MobjWasRemoved(player->mo)) return; // mobj was removed (in theory that shouldn't happen) if (shouldForce == 1) @@ -2483,7 +2483,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) } } - if (LUAh_PlayerSquish(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. + if (LUA_HookPlayerSquish(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. return; player->kartstuff[k_sneakertimer] = 0; @@ -2564,7 +2564,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b fixed_t upgoer; UINT8 scoremultiply = 1; boolean force = false; // Used to check if Lua ShouldExplode should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldExplode(player, inflictor, source); + UINT8 shouldForce = LUA_HookShouldExplode(player, inflictor, source); if (P_MobjWasRemoved(player->mo)) return; // mobj was removed (in theory that shouldn't happen) @@ -2597,7 +2597,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b } } - if (LUAh_PlayerExplode(player, inflictor, source)) // Same thing. Also make sure to let Instashield happen blah blah + if (LUA_HookPlayerExplode(player, inflictor, source)) // Same thing. Also make sure to let Instashield happen blah blah return; if (source && source != player->mo && source->player) diff --git a/src/lua_hook.h b/src/lua_hook.h index 3ca4b8f35..4a322d504 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -115,15 +115,13 @@ int LUA_HookPlayerCanDamage(player_t *, mobj_t *); void LUA_HookPlayerQuit(player_t *, int); int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); + +int LUA_HookShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out? +int LUA_HookShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded? +int LUA_HookShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be squished? + +boolean LUA_HookPlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. +boolean LUA_HookPlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. +boolean LUA_HookPlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. + int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events - - -// No clue what to do about these - -UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out? -UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded? -UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be squished? - -boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. -boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. -boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 2209803e6..4e83e23ee 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -965,17 +965,6 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) return hook.status; } -int LUA_HookKey(INT32 keycode, int hooktype) -{ - Hook_State hook; - if (prepare_hook(&hook, 0, hooktype)) - { - lua_pushinteger(gL, keycode); - call_hooks(&hook, 1, 0, res_true); - } - return hook.status; -} - static int kartdamage_hook ( player_t *player, @@ -996,37 +985,48 @@ static int kartdamage_hook } // Hook for K_SpinPlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) +int LUA_HookShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(ShouldSpin), res_force); } // Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) +int LUA_HookShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(ShouldExplode), res_force); } // Hook for K_SquishPlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) +int LUA_HookShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(ShouldSquish), res_force); } // Hook for K_SpinPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) +boolean LUA_HookPlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(PlayerSpin), res_true); } // Hook for K_SquishPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) +boolean LUA_HookPlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(PlayerSquish), res_true); } // Hook for K_ExplodePlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) +boolean LUA_HookPlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) { return kartdamage_hook(player, inflictor, source, HOOK(PlayerExplode), res_true); } + +int LUA_HookKey(INT32 keycode, int hooktype) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hooktype)) + { + lua_pushinteger(gL, keycode); + call_hooks(&hook, 1, 0, res_true); + } + return hook.status; +} -- 2.54.0 From ecae607b5987981608da6663f9c7ea16ee36a7c7 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:17:26 +0100 Subject: [PATCH 08/20] this is unused for now --- src/lua_hooklib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 4e83e23ee..6edbe9488 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -507,11 +507,11 @@ static void res_true(Hook_State *hook) hook->status = true; } -static void res_false(Hook_State *hook) +/*static void res_false(Hook_State *hook) { if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) hook->status = false; -} +}*/ static void res_force(Hook_State *hook) { -- 2.54.0 From da06c84aa4ccd332a9ceef9f4d036ad2c968b521 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:17:36 +0100 Subject: [PATCH 09/20] we dont have key event hooks --- src/lua_hook.h | 2 -- src/lua_hooklib.c | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 4a322d504..9e91c82b9 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -123,5 +123,3 @@ int LUA_HookShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); / boolean LUA_HookPlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUA_HookPlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUA_HookPlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. - -int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 6edbe9488..75533142b 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1019,14 +1019,3 @@ boolean LUA_HookPlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *sourc { return kartdamage_hook(player, inflictor, source, HOOK(PlayerExplode), res_true); } - -int LUA_HookKey(INT32 keycode, int hooktype) -{ - Hook_State hook; - if (prepare_hook(&hook, 0, hooktype)) - { - lua_pushinteger(gL, keycode); - call_hooks(&hook, 1, 0, res_true); - } - return hook.status; -} -- 2.54.0 From 06d0f5b95b277ba756f90a09e85144dc20ab7090 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:37:30 +0100 Subject: [PATCH 10/20] Automatically count hook values --- src/lua_hooklib.c | 71 ++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 75533142b..8bf506236 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -279,11 +279,16 @@ static void push_string(void) lua_pushvalue(gL, SINDEX); } -static boolean start_hook_stack(void) +static boolean begin_hook_values(Hook_State *hook) +{ + hook->top = lua_gettop(gL); + return true; +} + +static void start_hook_stack(void) { lua_settop(gL, 0); push_error_handler(); - return true; } static boolean init_hook_type @@ -299,10 +304,11 @@ static boolean init_hook_type if (nonzero) { + start_hook_stack(); hook->hook_type = hook_type; hook->mobj_type = mobj_type; hook->string = string; - return start_hook_stack(); + return begin_hook_values(hook); } else return false; @@ -343,7 +349,7 @@ static boolean prepare_string_hook stringHooks[hook_type].ref)) { lua_pushstring(gL, string); - return true; + return begin_hook_values(hook); } else return false; @@ -352,12 +358,12 @@ static boolean prepare_string_hook static void init_hook_call ( Hook_State * hook, - int values, int results, Hook_Callback results_handler ){ - hook->top = lua_gettop(gL); - hook->values = values; + const int top = lua_gettop(gL); + hook->values = (top - hook->top); + hook->top = top; hook->results = results; hook->results_handler = results_handler; } @@ -467,13 +473,12 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) static int call_hooks ( Hook_State * hook, - int values, int results, Hook_Callback results_handler ){ int calls = 0; - init_hook_call(hook, values, results, results_handler); + init_hook_call(hook, results, results_handler); if (hook->string) { @@ -534,7 +539,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type) if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) { LUA_PushUserdata(gL, mobj, META_MOBJ); - call_hooks(&hook, 1, 1, res_true); + call_hooks(&hook, 1, res_true); } return hook.status; } @@ -546,7 +551,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) { LUA_PushUserdata(gL, t1, META_MOBJ); LUA_PushUserdata(gL, t2, META_MOBJ); - call_hooks(&hook, 2, 1, res_force); + call_hooks(&hook, 1, res_force); } return hook.status; } @@ -555,7 +560,7 @@ void LUA_HookVoid(int type) { Hook_State hook; if (prepare_hook(&hook, 0, type)) - call_hooks(&hook, 0, 0, res_none); + call_hooks(&hook, 0, res_none); } void LUA_HookInt(INT32 number, int hook_type) @@ -564,7 +569,7 @@ void LUA_HookInt(INT32 number, int hook_type) if (prepare_hook(&hook, 0, hook_type)) { lua_pushinteger(gL, number); - call_hooks(&hook, 1, 0, res_none); + call_hooks(&hook, 0, res_none); } } @@ -574,7 +579,7 @@ void LUA_HookInt(INT32 number, int hook_type) if (prepare_hook(&hook, 0, hook_type)) { //lua_pushboolean(gL, value); - call_hooks(&hook, 1, 0, res_none); + call_hooks(&hook, 0, res_none); } }*/ @@ -584,7 +589,7 @@ int LUA_HookPlayer(player_t *player, int hook_type) if (prepare_hook(&hook, false, hook_type)) { LUA_PushUserdata(gL, player, META_PLAYER); - call_hooks(&hook, 1, 1, res_true); + call_hooks(&hook, 1, res_true); } return hook.status; } @@ -600,7 +605,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) if (hook_type == HOOK(PlayerCmd)) hook_cmd_running = true; - call_hooks(&hook, 2, 1, res_true); + call_hooks(&hook, 1, res_true); if (hook_type == HOOK(PlayerCmd)) hook_cmd_running = false; @@ -627,7 +632,7 @@ void LUA_HookThinkFrame(void) if (prepare_hook(&hook, 0, type)) { - init_hook_call(&hook, 0, 0, res_none); + init_hook_call(&hook, 0, res_none); for (k = 0; k < map->numHooks; ++k) { @@ -662,7 +667,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { LUA_PushUserdata(gL, special, META_MOBJ); LUA_PushUserdata(gL, toucher, META_MOBJ); - call_hooks(&hook, 2, 1, res_true); + call_hooks(&hook, 1, res_true); } return hook.status; } @@ -674,7 +679,6 @@ static int damage_hook mobj_t *source, INT32 damage, int hook_type, - int values, Hook_Callback results_handler ){ Hook_State hook; @@ -683,9 +687,9 @@ static int damage_hook LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); - if (values == 5) + if (hook_type != MOBJ_HOOK(MobjDeath)) lua_pushinteger(gL, damage); - call_hooks(&hook, values, 1, results_handler); + call_hooks(&hook, 1, results_handler); } return hook.status; } @@ -693,19 +697,19 @@ static int damage_hook int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) { return damage_hook(target, inflictor, source, damage, - MOBJ_HOOK(ShouldDamage), 5, res_force); + MOBJ_HOOK(ShouldDamage), res_force); } int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) { return damage_hook(target, inflictor, source, damage, - MOBJ_HOOK(MobjDamage), 5, res_true); + MOBJ_HOOK(MobjDamage), res_true); } int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) { return damage_hook(target, inflictor, source, 0, - MOBJ_HOOK(MobjDeath), 4, res_true); + MOBJ_HOOK(MobjDeath), res_true); } typedef struct { @@ -778,7 +782,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) hook.userdata = &botai; - call_hooks(&hook, 2, 8, res_botai); + call_hooks(&hook, 8, res_botai); } return hook.status; @@ -793,7 +797,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, mo, META_MOBJ); LUA_PushUserdata(gL, sector, META_SECTOR); - ps_lua_mobjhooks.value.i += call_hooks(&hook, 3, 0, res_none); + ps_lua_mobjhooks.value.i += call_hooks(&hook, 0, res_none); } } @@ -821,7 +825,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg, int mute) lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. else lua_pushboolean(gL, false); - call_hooks(&hook, 4, 1, res_true); + call_hooks(&hook, 1, res_true); } return hook.status; } @@ -834,7 +838,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); - call_hooks(&hook, 4, 1, res_true); + call_hooks(&hook, 1, res_true); } return hook.status; } @@ -853,12 +857,14 @@ void LUA_HookNetArchive(lua_CFunction archFunc) push_error_handler(); lua_insert(gL, EINDEX); + begin_hook_values(&hook); + // tables becomes an upvalue of archFunc lua_pushvalue(gL, -1); lua_pushcclosure(gL, archFunc, 1); // stack: tables, archFunc - init_hook_call(&hook, 1, 0, res_none); + init_hook_call(&hook, 0, res_none); call_mapped(&hook, map); lua_pop(gL, 1); // pop archFunc @@ -874,7 +880,7 @@ void LUA_HookPlayerQuit(player_t *plr, int reason) { LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit lua_pushinteger(gL, reason); // Reason for quitting - call_hooks(&hook, 2, 0, res_none); + call_hooks(&hook, 0, res_none); } } @@ -938,7 +944,8 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) if (prepare_hook(&hook, false, type)) { - init_hook_call(&hook, 7, 6, res_musicchange); + init_hook_call(&hook, 6, res_musicchange); + hook.values = 7;/* values pushed later */ hook.userdata = param; lua_pushstring(gL, oldname);/* the only constant value */ @@ -979,7 +986,7 @@ static int kartdamage_hook LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); - call_hooks(&hook, 3, 1, results_handler); + call_hooks(&hook, 1, results_handler); } return hook.status; } -- 2.54.0 From 802979b81d3cf0fdf375492bd8b6d80b3ffea96d Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:39:26 +0100 Subject: [PATCH 11/20] Refactor hook ref allocation --- src/lua_hooklib.c | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 8bf506236..93fc8c198 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -55,6 +55,7 @@ static stringhook_t stringHooks[STRING_HOOK(MAX)]; // This will be indexed by hook id, the value of which fetches the registry. static int * hookRefs; +static int nextid; // After a hook errors once, don't print the error again. static UINT8 * hooksErrored; @@ -103,13 +104,13 @@ static void get_table(lua_State *L) lua_remove(L, -2); } -static void add_hook_to_table(lua_State *L, int id, int n) +static void add_hook_to_table(lua_State *L, int n) { - lua_pushnumber(L, id); + lua_pushnumber(L, nextid); lua_rawseti(L, -2, n); } -static void add_string_hook(lua_State *L, int type, int id) +static void add_string_hook(lua_State *L, int type) { stringhook_t * hook = &stringHooks[type]; @@ -166,33 +167,48 @@ static void add_string_hook(lua_State *L, int type, int id) { lua_pushstring(L, string); get_table(L); - add_hook_to_table(L, id, 1 + lua_objlen(L, -1)); + add_hook_to_table(L, 1 + lua_objlen(L, -1)); } else - add_hook_to_table(L, id, ++hook->numGeneric); + add_hook_to_table(L, ++hook->numGeneric); } -static void add_hook(hook_t *map, int id) +static void add_hook(hook_t *map) { Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids, PU_STATIC, &map->ids); - map->ids[map->numHooks++] = id; + map->ids[map->numHooks++] = nextid; } -static void add_mobj_hook(lua_State *L, int hook_type, int id) +static void add_mobj_hook(lua_State *L, int hook_type) { mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); - add_hook(&mobjHookIds[mobj_type][hook_type], id); + add_hook(&mobjHookIds[mobj_type][hook_type]); +} + +static void add_hook_ref(lua_State *L, int idx) +{ + if (!(nextid & 7)) + { + Z_Realloc(hooksErrored, + BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored, + PU_STATIC, &hooksErrored); + hooksErrored[nextid >> 3] = 0; + } + + Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs); + + // set the hook function in the registry. + lua_pushvalue(L, idx); + hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX); } // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { - static int nextid; - const char * name; int type; @@ -205,34 +221,22 @@ static int lib_addHook(lua_State *L) /* this is a very special case */ if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX)) { - add_string_hook(L, type, nextid); + add_string_hook(L, type); } else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX)) { - add_mobj_hook(L, type, nextid); + add_mobj_hook(L, type); } else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX)) { - add_hook(&hookIds[type], nextid); + add_hook(&hookIds[type]); } else { return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); } - if (!(nextid & 7)) - { - Z_Realloc(hooksErrored, - BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored, - PU_STATIC, &hooksErrored); - hooksErrored[nextid >> 3] = 0; - } - - Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs); - - // set the hook function in the registry. - lua_pushvalue(L, 2);/* the function */ - hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX); + add_hook_ref(L, 2);/* the function */ return 0; } -- 2.54.0 From 11992d2e083e18b5735d6744c6d17c06042f0aa3 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:40:36 +0100 Subject: [PATCH 12/20] MORE MACROS --- src/lua_hook.h | 11 ++++++++--- src/lua_hooklib.c | 12 +++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 9e91c82b9..ea0c29e68 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -82,9 +82,14 @@ X (LinedefExecute),\ #define HOOK(name) hook_ ## name #define STRING_HOOK(name) stringhook_ ## name -enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) }; -enum { HOOK_LIST (HOOK) HOOK(MAX) }; -enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) }; + +#define ENUM(X) enum { X ## _LIST (X) X(MAX) } + +ENUM (MOBJ_HOOK); +ENUM (HOOK); +ENUM (STRING_HOOK); + +#undef ENUM /* dead simple, LUA_HOOK(GameQuit) */ #define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 93fc8c198..49044ffc1 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -30,12 +30,14 @@ ABSTRACTION ========================================================================= */ -static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL }; -static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL }; +#define LIST(id, M) \ + static const char * const id [] = { M (TOSTR) NULL } -static const char * const stringHookNames[] = { - STRING_HOOK_LIST (TOSTR) NULL -}; +LIST (mobjHookNames, MOBJ_HOOK_LIST); +LIST (hookNames, HOOK_LIST); +LIST (stringHookNames, STRING_HOOK_LIST); + +#undef LIST typedef struct { int numHooks; -- 2.54.0 From 4477f5ab937b655f469bb48e1ab7039dd6db8df3 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:41:14 +0100 Subject: [PATCH 13/20] Fix MusicChange hook crashing when called --- src/lua_hooklib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 49044ffc1..ababaf356 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -957,7 +957,7 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) lua_pushstring(gL, oldname);/* the only constant value */ lua_pushstring(gL, param->newname);/* semi constant */ - for (k = 0; k <= map->numHooks; ++k) + for (k = 0; k < map->numHooks; ++k) { get_hook(&hook, map->ids, k); -- 2.54.0 From a4e6b5d177ad82220fbcef84364866ed69c7b43e Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:46:27 +0100 Subject: [PATCH 14/20] Fix HurtMsg inflictor mobj type discriminator https://git.do.srb2.org/STJr/SRB2/-/merge_requests/1903 --- src/lua_hook.h | 2 +- src/lua_hooklib.c | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index ea0c29e68..e465db9bf 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -34,6 +34,7 @@ X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ X (MobjDeath),/* P_KillMobj */\ X (BossDeath),/* A_BossDeath */\ X (MobjRemoved),/* P_RemoveMobj */\ +X (HurtMsg),/* imhurttin */\ #define HOOK_LIST(X) \ X (NetVars),/* add to archive table (netsave) */\ @@ -49,7 +50,6 @@ X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ X (BotTiccmd),/* B_BuildTiccmd */\ X (PlayerMsg),/* chat messages */\ -X (HurtMsg),/* imhurttin */\ X (PlayerSpawn),/* G_SpawnPlayer */\ X (PlayerQuit),\ X (IntermissionThinker),/* Y_Ticker */\ diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ababaf356..817dd333f 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -69,7 +69,7 @@ static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) return ( mobjHookIds [MT_NULL] [hook_type].numHooks > 0 || - mobjHookIds[mobj_type][hook_type].numHooks > 0 + (mobj_type < NUMMOBJTYPES && mobjHookIds[mobj_type][hook_type].numHooks > 0) ); } @@ -336,8 +336,11 @@ static boolean prepare_mobj_hook Hook_State * hook, int default_status, int hook_type, - mobjtype_t mobj_type + mobj_t * primary_mobj ){ + const mobjtype_t mobj_type = + primary_mobj ? primary_mobj->type : NUMMOBJTYPES; + return init_hook_type(hook, default_status, hook_type, mobj_type, NULL, mobj_hook_available(hook_type, mobj_type)); @@ -494,7 +497,9 @@ static int call_hooks { /* call generic mobj hooks first */ calls += call_mobj_type_hooks(hook, MT_NULL); - calls += call_mobj_type_hooks(hook, hook->mobj_type); + + if (hook->mobj_type < NUMMOBJTYPES) + calls += call_mobj_type_hooks(hook, hook->mobj_type); ps_lua_mobjhooks.value.i += calls; } @@ -542,7 +547,7 @@ static void res_force(Hook_State *hook) int LUA_HookMobj(mobj_t *mobj, int hook_type) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) + if (prepare_mobj_hook(&hook, false, hook_type, mobj)) { LUA_PushUserdata(gL, mobj, META_MOBJ); call_hooks(&hook, 1, res_true); @@ -553,7 +558,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type) int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) { Hook_State hook; - if (prepare_mobj_hook(&hook, 0, hook_type, t1->type)) + if (prepare_mobj_hook(&hook, 0, hook_type, t1)) { LUA_PushUserdata(gL, t1, META_MOBJ); LUA_PushUserdata(gL, t2, META_MOBJ); @@ -669,7 +674,7 @@ void LUA_HookThinkFrame(void) int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special)) { LUA_PushUserdata(gL, special, META_MOBJ); LUA_PushUserdata(gL, toucher, META_MOBJ); @@ -688,7 +693,7 @@ static int damage_hook Hook_Callback results_handler ){ Hook_State hook; - if (prepare_mobj_hook(&hook, 0, hook_type, target->type)) + if (prepare_mobj_hook(&hook, 0, hook_type, target)) { LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ); @@ -839,7 +844,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg, int mute) int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) { Hook_State hook; - if (prepare_hook(&hook, false, HOOK(HurtMsg))) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(HurtMsg), inflictor)) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); -- 2.54.0 From 1f6096e3ff4aac49a098206fd3db47eaa16abc1d Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:49:42 +0100 Subject: [PATCH 15/20] fix pre and post thinkframe perfstats pages --- src/lua_hook.h | 2 ++ src/lua_hooklib.c | 31 +++++++++++++++++++++++++------ src/p_tick.c | 4 ++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index e465db9bf..e44140632 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -107,7 +107,9 @@ void LUA_HookInt(INT32 integer, int hook); int LUA_HookPlayer(player_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); +void LUA_HookPreThinkFrame(void); void LUA_HookThinkFrame(void); +void LUA_HookPostThinkFrame(void); int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher); int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 817dd333f..9ea0fdd5f 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -628,10 +628,8 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) SPECIALIZED HOOKS ========================================================================= */ -void LUA_HookThinkFrame(void) +static void hook_think_frame(int type) { - const int type = HOOK(ThinkFrame); - // variables used by perf stats int hook_index = 0; precise_t time_taken = 0; @@ -649,7 +647,7 @@ void LUA_HookThinkFrame(void) { get_hook(&hook, map->ids, k); - if (cv_perfstats.value == 3) + if (cv_perfstats.value >= 3) { lua_pushvalue(gL, -1);/* need the function again */ time_taken = I_GetPreciseTime(); @@ -657,12 +655,18 @@ void LUA_HookThinkFrame(void) call_single_hook(&hook); - if (cv_perfstats.value == 3) + if (cv_perfstats.value >= 3) { lua_Debug ar; time_taken = I_GetPreciseTime() - time_taken; lua_getinfo(gL, ">S", &ar); - PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + if (type == 4) // sorry for magic numbers + PS_SetPreThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + else if (type == 5) + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + else if (type == 6) + PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; } } @@ -671,6 +675,21 @@ void LUA_HookThinkFrame(void) } } +void LUA_HookPreThinkFrame(void) +{ + hook_think_frame(HOOK(PreThinkFrame)); +} + +void LUA_HookThinkFrame(void) +{ + hook_think_frame(HOOK(ThinkFrame)); +} + +void LUA_HookPostThinkFrame(void) +{ + hook_think_frame(HOOK(PostThinkFrame)); +} + int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { Hook_State hook; diff --git a/src/p_tick.c b/src/p_tick.c index 49d51774e..8a12dd6da 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -528,7 +528,7 @@ void P_Ticker(boolean run) ps_checkposition_calls.value.i = 0; PS_START_TIMING(ps_lua_prethinkframe_time); - LUA_HOOK(PreThinkFrame); + LUA_HookPreThinkFrame(); PS_STOP_TIMING(ps_lua_prethinkframe_time); PS_START_TIMING(ps_playerthink_time); @@ -668,7 +668,7 @@ void P_Ticker(boolean run) D_MapChange(gamemap, gametype, encoremode, true, 0, false, false); PS_START_TIMING(ps_lua_postthinkframe_time); - LUA_HOOK(PostThinkFrame); + LUA_HookPostThinkFrame(); PS_STOP_TIMING(ps_lua_postthinkframe_time); } -- 2.54.0 From fb0c88cf5597308839f5394cfe56293d380ed848 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 19:50:35 +0100 Subject: [PATCH 16/20] Fix -Warray-bounds warning in lua_hooklib.c --- src/lua_hooklib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 9ea0fdd5f..6e4f41d63 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -73,12 +73,12 @@ static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) ); } -static int hook_in_list +static unsigned hook_in_list ( const char * const name, const char * const * const list ){ - int type; + unsigned type; for (type = 0; list[type] != NULL; ++type) { @@ -212,7 +212,7 @@ static void add_hook_ref(lua_State *L, int idx) static int lib_addHook(lua_State *L) { const char * name; - int type; + unsigned type; if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); -- 2.54.0 From 2de9a6bb9420e896c9f4bf3d812646bec57565ac Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 21 Nov 2024 22:08:50 +0100 Subject: [PATCH 17/20] forgor to remove those --- src/lua_hook.h | 5 ++--- src/lua_hooklib.c | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index e44140632..ee43b90d2 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -52,10 +52,7 @@ X (BotTiccmd),/* B_BuildTiccmd */\ X (PlayerMsg),/* chat messages */\ X (PlayerSpawn),/* G_SpawnPlayer */\ X (PlayerQuit),\ -X (IntermissionThinker),/* Y_Ticker */\ X (PlayerThink),/* P_PlayerThink */\ -X (GameQuit),\ -X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ X (MusicChange),\ X (ShouldSpin),/*SRB2KART*/\ X (ShouldExplode),/*SRB2KART*/\ @@ -63,6 +60,8 @@ X (ShouldSquish),/*SRB2KART*/\ X (PlayerSpin),/*SRB2KART*/\ X (PlayerExplode),/*SRB2KART*/\ X (PlayerSquish),/*SRB2KART*/\ +X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ +X (IntermissionThinker),/* Y_Ticker */\ X (VoteThinker),/*SRB2KART*/\ X (ServerJoin),/* SRB2KART - Saturn 32p*/\ diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 6e4f41d63..a38be1ca6 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -24,8 +24,6 @@ #include "lua_hook.h" #include "lua_hud.h" // hud_running errors -#include - /* ========================================================================= ABSTRACTION ========================================================================= */ -- 2.54.0 From b40273842893f2ced849e63652fcab57b4c964bb Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 22 Nov 2024 01:31:02 +0300 Subject: [PATCH 18/20] Fix mobj hooks called for mobj type 0 being interpreted as regular hooks --- src/lua_hooklib.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index a38be1ca6..cc9a61695 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -259,6 +259,7 @@ struct Hook_State { void * userdata; int hook_type; mobjtype_t mobj_type;/* >0 if mobj hook */ + boolean force_mobj;// allows mobj_type equal 0 const char * string;/* used to fetch table, ran first if set */ int top;/* index of last argument passed to hook */ int id;/* id to fetch ref */ @@ -324,6 +325,8 @@ static boolean prepare_hook int default_status, int hook_type ){ + hook->force_mobj = false; + return init_hook_type(hook, default_status, hook_type, 0, NULL, hookIds[hook_type].numHooks); @@ -339,6 +342,8 @@ static boolean prepare_mobj_hook const mobjtype_t mobj_type = primary_mobj ? primary_mobj->type : NUMMOBJTYPES; + hook->force_mobj = true; + return init_hook_type(hook, default_status, hook_type, mobj_type, NULL, mobj_hook_available(hook_type, mobj_type)); @@ -351,6 +356,8 @@ static boolean prepare_string_hook int hook_type, const char * string ){ + hook->force_mobj = false; + if (init_hook_type(hook, default_status, hook_type, 0, string, stringHooks[hook_type].ref)) @@ -491,7 +498,7 @@ static int call_hooks { calls += call_string_hooks(hook); } - else if (hook->mobj_type > 0) + else if (hook->force_mobj) { /* call generic mobj hooks first */ calls += call_mobj_type_hooks(hook, MT_NULL); @@ -875,6 +882,7 @@ void LUA_HookNetArchive(lua_CFunction archFunc) { const hook_t * map = &hookIds[HOOK(NetVars)]; Hook_State hook; + hook.force_mobj = false; /* this is a remarkable case where the stack isn't reset */ if (map->numHooks > 0) { -- 2.54.0 From df97bef4b5dd66d39ae8aee7899182a3e26e6a25 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 22 Nov 2024 00:39:53 +0100 Subject: [PATCH 19/20] Refactor HUD hooks too --- src/hu_stuff.c | 2 +- src/lua_hook.h | 97 +++++++++++---------- src/lua_hooklib.c | 55 ++++++++++++ src/lua_hud.h | 5 +- src/lua_hudlib.c | 210 ++++------------------------------------------ src/st_stuff.c | 2 +- src/y_inter.c | 4 +- 7 files changed, 129 insertions(+), 246 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 8a999b83f..6cbb46148 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2274,7 +2274,7 @@ void HU_Drawer(void) if (renderisnewtic) { LUA_HUD_ClearDrawList(luahuddrawlist_scores); - LUAh_ScoresHUD(luahuddrawlist_scores); + LUA_HUDHOOK(scores, luahuddrawlist_scores); } LUA_HUD_DrawList(luahuddrawlist_scores); diff --git a/src/lua_hook.h b/src/lua_hook.h index ee43b90d2..45237aa80 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -13,6 +13,7 @@ #include "r_defs.h" #include "d_player.h" #include "s_sound.h" +#include "lua_hudlib_drawlist.h" /* * Do you know what an 'X Macro' is? Such a macro is called over each element of @@ -22,52 +23,58 @@ */ #define MOBJ_HOOK_LIST(X) \ -X (MobjSpawn),/* P_SpawnMobj */\ -X (MobjCollide),/* PIT_CheckThing */\ -X (MobjMoveCollide),/* tritto */\ -X (TouchSpecial),/* P_TouchSpecialThing */\ -X (MobjFuse),/* when mobj->fuse runs out */\ -X (MobjThinker),/* P_MobjThinker, P_SceneryThinker */\ -X (BossThinker),/* P_GenericBossThinker */\ -X (ShouldDamage),/* P_DamageMobj (Should mobj take damage?) */\ -X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ -X (MobjDeath),/* P_KillMobj */\ -X (BossDeath),/* A_BossDeath */\ -X (MobjRemoved),/* P_RemoveMobj */\ -X (HurtMsg),/* imhurttin */\ + X (MobjSpawn),/* P_SpawnMobj */\ + X (MobjCollide),/* PIT_CheckThing */\ + X (MobjMoveCollide),/* tritto */\ + X (TouchSpecial),/* P_TouchSpecialThing */\ + X (MobjFuse),/* when mobj->fuse runs out */\ + X (MobjThinker),/* P_MobjThinker, P_SceneryThinker */\ + X (BossThinker),/* P_GenericBossThinker */\ + X (ShouldDamage),/* P_DamageMobj (Should mobj take damage?) */\ + X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ + X (MobjDeath),/* P_KillMobj */\ + X (BossDeath),/* A_BossDeath */\ + X (MobjRemoved),/* P_RemoveMobj */\ + X (HurtMsg),/* imhurttin */\ #define HOOK_LIST(X) \ -X (NetVars),/* add to archive table (netsave) */\ -X (MapChange),/* (before map load) */\ -X (MapLoad),\ -X (PlayerJoin),/* Got_AddPlayer */\ -X (PreThinkFrame)/* frame (before mobj and player thinkers) */,\ -X (ThinkFrame),/* frame (after mobj and player thinkers) */\ -X (PostThinkFrame),/* frame (at end of tick, ie after overlays, precipitation, specials) */\ -X (JumpSpecial),/* P_DoJumpStuff (Any-jumping) */\ -X (AbilitySpecial),/* P_DoJumpStuff (Double-jumping) */\ -X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ -X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ -X (BotTiccmd),/* B_BuildTiccmd */\ -X (PlayerMsg),/* chat messages */\ -X (PlayerSpawn),/* G_SpawnPlayer */\ -X (PlayerQuit),\ -X (PlayerThink),/* P_PlayerThink */\ -X (MusicChange),\ -X (ShouldSpin),/*SRB2KART*/\ -X (ShouldExplode),/*SRB2KART*/\ -X (ShouldSquish),/*SRB2KART*/\ -X (PlayerSpin),/*SRB2KART*/\ -X (PlayerExplode),/*SRB2KART*/\ -X (PlayerSquish),/*SRB2KART*/\ -X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ -X (IntermissionThinker),/* Y_Ticker */\ -X (VoteThinker),/*SRB2KART*/\ -X (ServerJoin),/* SRB2KART - Saturn 32p*/\ + X (NetVars),/* add to archive table (netsave) */\ + X (MapChange),/* (before map load) */\ + X (MapLoad),\ + X (PlayerJoin),/* Got_AddPlayer */\ + X (PreThinkFrame)/* frame (before mobj and player thinkers) */,\ + X (ThinkFrame),/* frame (after mobj and player thinkers) */\ + X (PostThinkFrame),/* frame (at end of tick, ie after overlays, precipitation, specials) */\ + X (JumpSpecial),/* P_DoJumpStuff (Any-jumping) */\ + X (AbilitySpecial),/* P_DoJumpStuff (Double-jumping) */\ + X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ + X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ + X (BotTiccmd),/* B_BuildTiccmd */\ + X (PlayerMsg),/* chat messages */\ + X (PlayerSpawn),/* G_SpawnPlayer */\ + X (PlayerQuit),\ + X (PlayerThink),/* P_PlayerThink */\ + X (MusicChange),\ + X (ShouldSpin),/*SRB2KART*/\ + X (ShouldExplode),/*SRB2KART*/\ + X (ShouldSquish),/*SRB2KART*/\ + X (PlayerSpin),/*SRB2KART*/\ + X (PlayerExplode),/*SRB2KART*/\ + X (PlayerSquish),/*SRB2KART*/\ + X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ + X (IntermissionThinker),/* Y_Ticker */\ + X (VoteThinker),/*SRB2KART*/\ + X (ServerJoin),/* SRB2KART - Saturn 32p*/\ #define STRING_HOOK_LIST(X) \ -X (BotAI),/* B_BuildTailsTiccmd by skin name */\ -X (LinedefExecute),\ + X (BotAI),/* B_BuildTailsTiccmd by skin name */\ + X (LinedefExecute),\ + +#define HUD_HOOK_LIST(X) \ + X (game),\ + X (scores),/* emblems/multiplayer list */\ + X (intermission),\ + X (vote),\ /* * I chose to access the hook enums through a macro as well. This could provide @@ -79,25 +86,27 @@ X (LinedefExecute),\ #define MOBJ_HOOK(name) mobjhook_ ## name #define HOOK(name) hook_ ## name +#define HUD_HOOK(name) hudhook_ ## name #define STRING_HOOK(name) stringhook_ ## name - #define ENUM(X) enum { X ## _LIST (X) X(MAX) } ENUM (MOBJ_HOOK); ENUM (HOOK); +ENUM (HUD_HOOK); ENUM (STRING_HOOK); #undef ENUM /* dead simple, LUA_HOOK(GameQuit) */ #define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) - +#define LUA_HUDHOOK(type,drawlist) LUA_HookHUD(HUD_HOOK(type),(drawlist)) extern boolean hook_cmd_running; // This is used by PlayerCmd and lua_playerlib to prevent anything from being wirtten to player while we run PlayerCmd. extern int hook_defrosting; void LUA_HookVoid(int hook); +void LUA_HookHUD(int hook, huddrawlist_h drawlist); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index cc9a61695..8acc418d3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -33,6 +33,7 @@ LIST (mobjHookNames, MOBJ_HOOK_LIST); LIST (hookNames, HOOK_LIST); +LIST (hudHookNames, HUD_HOOK_LIST); LIST (stringHookNames, STRING_HOOK_LIST); #undef LIST @@ -48,6 +49,7 @@ typedef struct { } stringhook_t; static hook_t hookIds[HOOK(MAX)]; +static hook_t hudHookIds[HUD_HOOK(MAX)]; static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; // Lua tables are used to lookup string hook ids. @@ -189,6 +191,12 @@ static void add_mobj_hook(lua_State *L, int hook_type) add_hook(&mobjHookIds[mobj_type][hook_type]); } +static void add_hud_hook(lua_State *L, int idx) +{ + add_hook(&hudHookIds[luaL_checkoption(L, + idx, "game", hudHookNames)]); +} + static void add_hook_ref(lua_State *L, int idx) { if (!(nextid & 7)) @@ -231,6 +239,10 @@ static int lib_addHook(lua_State *L) { add_hook(&hookIds[type]); } + /*else if (strcmp(name, "HUD") == 0) // ehh this is cool and all, but i dont want modders potentially breaking vanilla clients lol + { + add_hud_hook(L, 3); + }*/ else { return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); @@ -251,6 +263,18 @@ int LUA_HookLib(lua_State *L) return 0; } + +int lib_hudadd(lua_State *L);/* yeah compiler */ +int lib_hudadd(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TFUNCTION); + + add_hud_hook(L, 2); + add_hook_ref(L, 1); + + return 0; +} + typedef struct Hook_State Hook_State; typedef void (*Hook_Callback)(Hook_State *); @@ -545,6 +569,14 @@ static void res_force(Hook_State *hook) } } +static void res_hud(Hook_State *hook) +{ + (void)hook; + + hud_interpolate = hud_interpstring = hud_interplatch = false; + hud_interpcounter++; +} + /* ========================================================================= GENERALISED HOOKS ========================================================================= */ @@ -629,6 +661,29 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) return hook.status; } +void LUA_HookHUD(int hook_type, huddrawlist_h list) +{ + const hook_t * map = &hudHookIds[hook_type]; + Hook_State hook; + if (map->numHooks > 0) + { + start_hook_stack(); + begin_hook_values(&hook); + + LUA_SetHudHook(hook_type, list); + + hud_running = true; // local hook + hud_interpcounter = 0; + hud_interpolate = hud_interpstring = hud_interplatch = false; + init_hook_call(&hook, 1, res_hud); + call_mapped(&hook, map); + hud_running = false; + + lua_pushnil(gL); + lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + } +} + /* ========================================================================= SPECIALIZED HOOKS ========================================================================= */ diff --git a/src/lua_hud.h b/src/lua_hud.h index 5d1f41c83..76ce9eb48 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -50,9 +50,6 @@ extern boolean hud_interplatch; // string mode was toggled boolean LUA_HudEnabled(enum hud option); -void LUAh_GameHUD(huddrawlist_h list); -void LUAh_ScoresHUD(huddrawlist_h list); -void LUAh_IntermissionHUD(huddrawlist_h list); -void LUAh_VoteHUD(huddrawlist_h list); +void LUA_SetHudHook(int hook, huddrawlist_h list); #endif // __LUA_HUD_H__ diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 2ee2297ad..235a89cde 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -28,6 +28,7 @@ #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" +#include "lua_hook.h" #define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!"); @@ -40,8 +41,6 @@ boolean hud_interpstring = false; boolean hud_interplatch = false; static UINT8 hud_enabled[(hud_MAX/8)+1]; -static UINT8 hudAvailable; // hud hooks field - static UINT8 camnum = 1; // must match enum hud in lua_hud.h @@ -93,19 +92,6 @@ static const char *const patch_opt[] = { "topoffset", NULL}; -enum hudhook { - hudhook_game = 0, - hudhook_scores = 1, - hudhook_intermission = 2, - hudhook_vote = 3, -}; -static const char *const hudhook_opt[] = { - "game", - "scores", - "intermission", - "vote", - NULL}; - static int patch_fields_ref = LUA_NOREF; // alignment types for v.drawString @@ -1215,6 +1201,8 @@ static luaL_Reg lib_draw[] = { {NULL, NULL} }; +static int lib_draw_ref; + // // lib_hud // @@ -1248,25 +1236,7 @@ static int lib_hudenabled(lua_State *L) } // add a HUD element for rendering -static int lib_hudadd(lua_State *L) -{ - enum hudhook field; - - luaL_checktype(L, 1, LUA_TFUNCTION); - field = luaL_checkoption(L, 2, "game", hudhook_opt); - - lua_getfield(L, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(L, -1)); - lua_rawgeti(L, -1, field+2); // HUD[2+] - I_Assert(lua_istable(L, -1)); - lua_remove(L, -2); - - lua_pushvalue(L, 1); - lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1)); - - hudAvailable |= 1< Date: Fri, 22 Nov 2024 16:04:01 +0100 Subject: [PATCH 20/20] make hud hooks clean up after themselves --- src/lua_hooklib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 8acc418d3..9276e61aa 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -677,6 +677,7 @@ void LUA_HookHUD(int hook_type, huddrawlist_h list) hud_interpolate = hud_interpstring = hud_interplatch = false; init_hook_call(&hook, 1, res_hud); call_mapped(&hook, map); + lua_settop(gL, 0); // destroy le stack!! >:3 hud_running = false; lua_pushnil(gL); -- 2.54.0