mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-26 04:11:18 +00:00
Merge pull request #147 from LJSonik/hook-optimisation
Hook optimisation
This commit is contained in:
commit
fe3916a60d
2 changed files with 293 additions and 31 deletions
|
@ -60,7 +60,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which);
|
|||
#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
|
||||
#define LUAh_MobjThinker(mo) LUAh_MobjHook(mo, hook_MobjThinker) // Hook for P_MobjThinker or P_SceneryThinker 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!)
|
||||
|
|
|
@ -74,12 +74,30 @@ typedef struct hook_s* hook_p;
|
|||
|
||||
#define FMT_HOOKID "hook_%d"
|
||||
|
||||
// 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];
|
||||
|
||||
// For each mobj type, a linked list for other mobj hooks
|
||||
static hook_p mobjhooks[NUMMOBJTYPES];
|
||||
|
||||
// A linked list for player hooks
|
||||
static hook_p playerhooks;
|
||||
|
||||
// A linked list for linedef executor hooks
|
||||
static hook_p linedefexecutorhooks;
|
||||
|
||||
// For other hooks, a unique linked list
|
||||
hook_p roothook;
|
||||
|
||||
// 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;
|
||||
|
||||
hook.type = luaL_checkoption(L, 1, NULL, hookNames);
|
||||
|
@ -109,6 +127,7 @@ static int lib_addHook(lua_State *L)
|
|||
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;
|
||||
|
@ -141,18 +160,49 @@ static int lib_addHook(lua_State *L)
|
|||
|
||||
hooksAvailable[hook.type/8] |= 1<<(hook.type%8);
|
||||
|
||||
// iterate the hook metadata structs
|
||||
// set hook.id to the highest id + 1
|
||||
// set lastp to the last hook struct's "next" pointer.
|
||||
lastp = &roothook;
|
||||
hook.id = 0;
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
hook.id = nextid++;
|
||||
|
||||
// Special cases for some hook types (see the comments above mobjthinkerhooks declaration)
|
||||
switch(hook.type)
|
||||
{
|
||||
if (hookp->id >= hook.id)
|
||||
hook.id = hookp->id+1;
|
||||
lastp = &hookp->next;
|
||||
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:
|
||||
lastp = &playerhooks;
|
||||
break;
|
||||
case hook_LinedefExecute:
|
||||
lastp = &linedefexecutorhooks;
|
||||
break;
|
||||
default:
|
||||
lastp = &roothook;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
@ -183,9 +233,29 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == which
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == mo->type))
|
||||
// Look for all generic mobj hooks
|
||||
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == which)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
LUA_PushUserdata(gL, mo, META_MOBJ);
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -2);
|
||||
if (lua_pcall(gL, 1, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
LUA_PushUserdata(gL, mo, META_MOBJ);
|
||||
|
@ -217,7 +287,7 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
for (hookp = playerhooks; hookp; hookp = hookp->next)
|
||||
if (hookp->type == which)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
|
@ -338,9 +408,38 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == which
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type))
|
||||
// Look for all generic mobj collision hooks
|
||||
for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == which)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, thing1, META_MOBJ);
|
||||
LUA_PushUserdata(gL, thing2, META_MOBJ);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -3);
|
||||
lua_pushvalue(gL, -3);
|
||||
if (lua_pcall(gL, 2, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
@ -372,6 +471,59 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
|
|||
return shouldCollide;
|
||||
}
|
||||
|
||||
// Hook for mobj thinkers
|
||||
boolean LUAh_MobjThinker(mobj_t *mo)
|
||||
{
|
||||
hook_p hookp;
|
||||
boolean hooked = false;
|
||||
if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8))))
|
||||
return false;
|
||||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
// Look for all generic mobj thinker hooks
|
||||
for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
LUA_PushUserdata(gL, mo, META_MOBJ);
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -2);
|
||||
if (lua_pcall(gL, 1, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
LUA_PushUserdata(gL, mo, META_MOBJ);
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -2);
|
||||
if (lua_pcall(gL, 1, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
|
@ -382,9 +534,33 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_TouchSpecial
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == special->type))
|
||||
// Look for all generic touch special hooks
|
||||
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_TouchSpecial)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, special, META_MOBJ);
|
||||
LUA_PushUserdata(gL, toucher, META_MOBJ);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -3);
|
||||
lua_pushvalue(gL, -3);
|
||||
if (lua_pcall(gL, 2, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
@ -421,9 +597,42 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_ShouldDamage
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
|
||||
// Look for all generic should damage hooks
|
||||
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_ShouldDamage)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, target, META_MOBJ);
|
||||
LUA_PushUserdata(gL, inflictor, META_MOBJ);
|
||||
LUA_PushUserdata(gL, source, META_MOBJ);
|
||||
lua_pushinteger(gL, damage);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
if (lua_pcall(gL, 4, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
@ -469,9 +678,37 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_MobjDamage
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
|
||||
// Look for all generic mobj damage hooks
|
||||
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_MobjDamage)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, target, META_MOBJ);
|
||||
LUA_PushUserdata(gL, inflictor, META_MOBJ);
|
||||
LUA_PushUserdata(gL, source, META_MOBJ);
|
||||
lua_pushinteger(gL, damage);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
lua_pushvalue(gL, -5);
|
||||
if (lua_pcall(gL, 4, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
@ -512,9 +749,35 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_MobjDeath
|
||||
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
|
||||
// Look for all generic mobj death hooks
|
||||
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_MobjDeath)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, target, META_MOBJ);
|
||||
LUA_PushUserdata(gL, inflictor, META_MOBJ);
|
||||
LUA_PushUserdata(gL, source, META_MOBJ);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -4);
|
||||
lua_pushvalue(gL, -4);
|
||||
lua_pushvalue(gL, -4);
|
||||
if (lua_pcall(gL, 3, 1, 0)) {
|
||||
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)
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
@ -652,9 +915,8 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
|
|||
|
||||
lua_settop(gL, 0);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_LinedefExecute
|
||||
&& !strcmp(hookp->s.funcname, line->text))
|
||||
for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next)
|
||||
if (!strcmp(hookp->s.funcname, line->text))
|
||||
{
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue