mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-16 01:11:28 +00:00
Lunatic: replace DukePlayer_t set-member methods with metatable magic.
So that members needing it are checked when they're assigned to using the usual syntax. What kind of check to perform (sector, player, ... x whether negative values are allowed) is written in a declarative fashion inside the C declaration. Also, make Lunatic's MAXQUOTES be C's OBITQUOTEINDEX and bound-check an access of sprite[p->wackedbyplayer] in the C code. git-svn-id: https://svn.eduke32.com/eduke32@3653 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
fb41d91a50
commit
bbdc035335
7 changed files with 88 additions and 77 deletions
|
@ -20,7 +20,11 @@ MAXEVENTS = 95 -- KEEPINSYNC with EVENT_* list
|
||||||
MAXSOUNDS = 4096
|
MAXSOUNDS = 4096
|
||||||
|
|
||||||
-- KEEPINSYNC quotes.h
|
-- KEEPINSYNC quotes.h
|
||||||
MAXQUOTES = 16384
|
|
||||||
|
-- For Lunatic, MAXQUOTES is OBITQUOTEINDEX because starting from that index
|
||||||
|
-- are obituary and suicide quotes which are passed as *format strings* to
|
||||||
|
-- sprintf() in C.
|
||||||
|
MAXQUOTES = 16384-128
|
||||||
MAXQUOTELEN = 128
|
MAXQUOTELEN = 128
|
||||||
|
|
||||||
local STR = {
|
local STR = {
|
||||||
|
@ -516,17 +520,17 @@ local PlayerLabels = {
|
||||||
oang = PL".oang",
|
oang = PL".oang",
|
||||||
angvel = PL".angvel",
|
angvel = PL".angvel",
|
||||||
|
|
||||||
cursectnum = { PL".cursectnum", PL":set_cursectnum(%%s)" },
|
cursectnum = PL".cursectnum",
|
||||||
|
|
||||||
look_ang = PL".look_ang",
|
look_ang = PL".look_ang",
|
||||||
last_extra = PL".last_extra",
|
last_extra = PL".last_extra",
|
||||||
subweapon = PL".subweapon",
|
subweapon = PL".subweapon",
|
||||||
|
|
||||||
max_ammo_amount = PL".max_ammo_amount[%s]" ,
|
max_ammo_amount = PL".max_ammo_amount[%s]",
|
||||||
ammo_amount = PL".ammo_amount[%s]" ,
|
ammo_amount = PL".ammo_amount[%s]",
|
||||||
-- NOTE: no direct access for .inv_amount (but see end)
|
-- NOTE: no direct access for .inv_amount (but see end)
|
||||||
|
|
||||||
wackedbyactor = { PL".wackedbyactor", PL":set_wackedbyactor(%%s)" },
|
wackedbyactor = PL".wackedbyactor",
|
||||||
pyoff = PL".pyoff",
|
pyoff = PL".pyoff",
|
||||||
opyoff = PL".opyoff",
|
opyoff = PL".opyoff",
|
||||||
|
|
||||||
|
@ -541,7 +545,7 @@ local PlayerLabels = {
|
||||||
airleft = PL".airleft",
|
airleft = PL".airleft",
|
||||||
|
|
||||||
fta = PL".fta",
|
fta = PL".fta",
|
||||||
ftq = { PL".ftq", PL":set_ftq(%%s)" },
|
ftq = PL".ftq",
|
||||||
access_wallnum = { PL".access_wallnum" },
|
access_wallnum = { PL".access_wallnum" },
|
||||||
access_spritenum = { PL".access_spritenum" },
|
access_spritenum = { PL".access_spritenum" },
|
||||||
|
|
||||||
|
@ -559,7 +563,7 @@ local PlayerLabels = {
|
||||||
random_club_frame = PL".random_club_frame",
|
random_club_frame = PL".random_club_frame",
|
||||||
one_eighty_count = PL".one_eighty_count",
|
one_eighty_count = PL".one_eighty_count",
|
||||||
|
|
||||||
dummyplayersprite = { PL".dummyplayersprite", PL":set_dummyplayersprite(%%s)" },
|
dummyplayersprite = PL".dummyplayersprite",
|
||||||
extra_extra8 = PL".extra_extra8",
|
extra_extra8 = PL".extra_extra8",
|
||||||
|
|
||||||
actorsqu = PL".actorsqu",
|
actorsqu = PL".actorsqu",
|
||||||
|
@ -568,7 +572,7 @@ local PlayerLabels = {
|
||||||
|
|
||||||
last_pissed_time = PL".last_pissed_time",
|
last_pissed_time = PL".last_pissed_time",
|
||||||
|
|
||||||
weaprecs = PL".weaprecs[%s]" ,
|
weaprecs = PL".weaprecs[%s]",
|
||||||
|
|
||||||
weapon_sway = PL".weapon_sway",
|
weapon_sway = PL".weapon_sway",
|
||||||
crack_time = PL".crack_time",
|
crack_time = PL".crack_time",
|
||||||
|
@ -649,12 +653,12 @@ local PlayerLabels = {
|
||||||
loogcnt = PL".loogcnt",
|
loogcnt = PL".loogcnt",
|
||||||
scream_voice = PL".scream_voice",
|
scream_voice = PL".scream_voice",
|
||||||
|
|
||||||
last_weapon = { PL".last_weapon", PL":set_last_weapon(%%s)" },
|
last_weapon = PL".last_weapon",
|
||||||
cheat_phase = PL".cheat_phase",
|
cheat_phase = PL".cheat_phase",
|
||||||
weapon_pos = PL".weapon_pos",
|
weapon_pos = PL".weapon_pos",
|
||||||
wantweaponfire = { PL".wantweaponfire" },
|
wantweaponfire = PL".wantweaponfire",
|
||||||
|
|
||||||
curr_weapon = { PL".curr_weapon", PL":set_curr_weapon(%%s)" },
|
curr_weapon = PL".curr_weapon",
|
||||||
|
|
||||||
palette = PL".palette",
|
palette = PL".palette",
|
||||||
|
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ end
|
||||||
|
|
||||||
function _endofgame(pli, timebeforeexit)
|
function _endofgame(pli, timebeforeexit)
|
||||||
player[pli].timebeforeexit = timebeforeexit
|
player[pli].timebeforeexit = timebeforeexit
|
||||||
player[pli]:set_customexitsound(-1)
|
player[pli].customexitsound = -1
|
||||||
ffiC.ud.eog = 1
|
ffiC.ud.eog = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -210,28 +210,29 @@ __attribute__((packed)) struct {
|
||||||
int16_t sbs, sound_pitch;
|
int16_t sbs, sound_pitch;
|
||||||
|
|
||||||
int16_t ang, oang, angvel;
|
int16_t ang, oang, angvel;
|
||||||
const int16_t cursectnum;
|
const<S> int16_t cursectnum;
|
||||||
int16_t look_ang, last_extra, subweapon;
|
int16_t look_ang, last_extra, subweapon;
|
||||||
int16_x_MAX_WEAPONS max_ammo_amount;
|
int16_x_MAX_WEAPONS max_ammo_amount;
|
||||||
int16_x_MAX_WEAPONS ammo_amount;
|
int16_x_MAX_WEAPONS ammo_amount;
|
||||||
int16_x_GET_MAX inv_amount;
|
int16_x_GET_MAX inv_amount;
|
||||||
const int16_t wackedbyactor;
|
const<I-> int16_t wackedbyactor;
|
||||||
int16_t pyoff, opyoff;
|
int16_t pyoff, opyoff;
|
||||||
|
|
||||||
int16_t horiz, horizoff, ohoriz, ohorizoff;
|
int16_t horiz, horizoff, ohoriz, ohorizoff;
|
||||||
const int16_t newowner;
|
const int16_t newowner;
|
||||||
int16_t jumping_counter, airleft;
|
int16_t jumping_counter, airleft;
|
||||||
int16_t fta;
|
int16_t fta;
|
||||||
const int16_t ftq, access_wallnum, access_spritenum;
|
const<Q> int16_t ftq;
|
||||||
|
const int16_t access_wallnum, access_spritenum;
|
||||||
int16_t got_access, weapon_ang, visibility;
|
int16_t got_access, weapon_ang, visibility;
|
||||||
int16_t somethingonplayer, on_crane;
|
int16_t somethingonplayer, on_crane;
|
||||||
const int16_t i;
|
const int16_t i;
|
||||||
const int16_t one_parallax_sectnum;
|
const int16_t one_parallax_sectnum;
|
||||||
int16_t random_club_frame, one_eighty_count;
|
int16_t random_club_frame, one_eighty_count;
|
||||||
const int16_t dummyplayersprite;
|
const<I-> int16_t dummyplayersprite;
|
||||||
int16_t extra_extra8;
|
int16_t extra_extra8;
|
||||||
int16_t actorsqu, timebeforeexit;
|
int16_t actorsqu, timebeforeexit;
|
||||||
const int16_t customexitsound;
|
const<X-> int16_t customexitsound;
|
||||||
int16_t last_pissed_time;
|
int16_t last_pissed_time;
|
||||||
|
|
||||||
int16_x_MAX_WEAPONS weaprecs;
|
int16_x_MAX_WEAPONS weaprecs;
|
||||||
|
@ -248,7 +249,7 @@ __attribute__((packed)) struct {
|
||||||
const uint8_t weapreccnt;
|
const uint8_t weapreccnt;
|
||||||
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
|
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
|
||||||
uint8_t tipincs, hbomb_hold_delay;
|
uint8_t tipincs, hbomb_hold_delay;
|
||||||
const uint8_t frag_ps;
|
const<P> uint8_t frag_ps;
|
||||||
uint8_t kickback_pic;
|
uint8_t kickback_pic;
|
||||||
|
|
||||||
uint8_t gm;
|
uint8_t gm;
|
||||||
|
@ -278,9 +279,10 @@ __attribute__((packed)) struct {
|
||||||
uint8_t walking_snd_toggle, palookup, hard_landing, fist_incs;
|
uint8_t walking_snd_toggle, palookup, hard_landing, fist_incs;
|
||||||
|
|
||||||
int8_t numloogs, loogcnt, scream_voice;
|
int8_t numloogs, loogcnt, scream_voice;
|
||||||
const int8_t last_weapon;
|
const<W-> int8_t last_weapon;
|
||||||
int8_t cheat_phase, weapon_pos;
|
int8_t cheat_phase, weapon_pos;
|
||||||
const int8_t wantweaponfire, curr_weapon;
|
const<W-> int8_t wantweaponfire;
|
||||||
|
const<W> int8_t curr_weapon;
|
||||||
|
|
||||||
uint8_t palette;
|
uint8_t palette;
|
||||||
palette_t _pals;
|
palette_t _pals;
|
||||||
|
@ -337,15 +339,44 @@ local function ma_replace_array(typestr, neltstr)
|
||||||
return table.concat(strtab)
|
return table.concat(strtab)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Converts a template struct definition to an external one, in which arrays
|
---=== Protection of scalars in (currently only) DukePlayer_t struct. ===---
|
||||||
-- have been substituted by randomly named scalar fields.
|
-- This is more convenient than writing dozens of set-member methods.
|
||||||
local function mangle_arrays(structstr)
|
local prot_scalar_chkfunc = {
|
||||||
ma_count = 0
|
S = check_sector_idx,
|
||||||
-- NOTE: regexp only works for non-nested arrays and for one array per line.
|
I = check_sprite_idx,
|
||||||
return (string.gsub(structstr, "const%s+([%w_]+)[^\n]+%[([%w_]+)%];", ma_replace_array))
|
|
||||||
|
P = bcheck.player_idx,
|
||||||
|
W = check_weapon_idx,
|
||||||
|
X = check_sound_idx,
|
||||||
|
Q = bcheck.quote_idx,
|
||||||
|
}
|
||||||
|
|
||||||
|
local DukePlayer_prot_allowneg = {} -- [<member name>] = true if setting <0 allowed
|
||||||
|
local DukePlayer_prot_chkfunc = {} -- [<member name>] = <checking function>
|
||||||
|
|
||||||
|
local function ma_replace_scalar(what, typestr, membname)
|
||||||
|
DukePlayer_prot_chkfunc[membname] = assert(prot_scalar_chkfunc[what:sub(1,1)])
|
||||||
|
DukePlayer_prot_allowneg[membname] = (what:sub(2)=="-")
|
||||||
|
return ma_replace_array(typestr, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
--print(mangle_arrays(ACTOR_STRUCT))
|
-- Converts a template struct definition to an external one, in which arrays
|
||||||
|
-- have been substituted by randomly named scalar fields.
|
||||||
|
-- <also_scalars>: also handle protected scalars like "const<W-> ..." etc.
|
||||||
|
local function mangle_arrays(structstr, also_scalars)
|
||||||
|
ma_count = 0
|
||||||
|
-- NOTE: regexp only works for non-nested arrays and for one array per line.
|
||||||
|
structstr = structstr:gsub("const%s+([%w_]+)[^\n]+%[([%w_]+)%];", ma_replace_array)
|
||||||
|
|
||||||
|
if (also_scalars) then
|
||||||
|
-- One protected scalar per line, too.
|
||||||
|
structstr = structstr:gsub("const<(.-)>%s+([%w_]-)%s+([%w_]-);", ma_replace_scalar)
|
||||||
|
end
|
||||||
|
|
||||||
|
return structstr
|
||||||
|
end
|
||||||
|
|
||||||
|
--print(mangle_arrays(DUKEPLAYER_STRUCT, true))
|
||||||
|
|
||||||
--- default defines etc.
|
--- default defines etc.
|
||||||
local con_lang = require("con_lang")
|
local con_lang = require("con_lang")
|
||||||
|
@ -365,7 +396,7 @@ typedef
|
||||||
actor_t;
|
actor_t;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
]].. mangle_arrays(DUKEPLAYER_STRUCT) ..[[
|
]].. mangle_arrays(DUKEPLAYER_STRUCT, true) ..[[
|
||||||
DukePlayer_t;
|
DukePlayer_t;
|
||||||
|
|
||||||
typedef __attribute__((packed)) struct {
|
typedef __attribute__((packed)) struct {
|
||||||
|
@ -963,7 +994,7 @@ ffi.metatype("actor_t", actor_mt)
|
||||||
local weapondata_mt = {
|
local weapondata_mt = {
|
||||||
__index = function(wd, member)
|
__index = function(wd, member)
|
||||||
-- Handle protected members that are renamed (e.g. shoots/_shoots).
|
-- Handle protected members that are renamed (e.g. shoots/_shoots).
|
||||||
return ffi.cast(weapondata_ptr_ct, wd)[member]
|
return ffi.cast(weapondata_ptr_ct, wd)[0][member]
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__newindex = function(wd, member, val)
|
__newindex = function(wd, member, val)
|
||||||
|
@ -986,7 +1017,7 @@ local weapondata_mt = {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ffi.cast(weapondata_ptr_ct, wd)[member] = val
|
ffi.cast(weapondata_ptr_ct, wd)[0][member] = val
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
ffi.metatype("weapondata_t", weapondata_mt)
|
ffi.metatype("weapondata_t", weapondata_mt)
|
||||||
|
@ -1007,50 +1038,6 @@ ffi.metatype("weaponaccess_t", weaponaccess_mt)
|
||||||
|
|
||||||
local player_mt = {
|
local player_mt = {
|
||||||
__index = {
|
__index = {
|
||||||
--- Getters/setters
|
|
||||||
set_curr_weapon = function(p, weap)
|
|
||||||
check_weapon_idx(weap)
|
|
||||||
ffi.cast(player_ptr_ct, p).curr_weapon = weap
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_last_weapon = function(p, weap)
|
|
||||||
if (not (weap < 0)) then
|
|
||||||
check_weapon_idx(weap)
|
|
||||||
end
|
|
||||||
ffi.cast(player_ptr_ct, p).last_weapon = weap
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_ftq = function(p, ftq)
|
|
||||||
bcheck.quote_idx(ftq)
|
|
||||||
ffi.cast(player_ptr_ct, p).ftq = ftq
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_cursectnum = function(p, sectnum)
|
|
||||||
check_sector_idx(sectnum)
|
|
||||||
ffi.cast(player_ptr_ct, p).cursectnum = sectnum
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_customexitsound = function(p, soundnum)
|
|
||||||
if (not (soundnum < 0)) then
|
|
||||||
check_sound_idx(soundnum)
|
|
||||||
end
|
|
||||||
ffi.cast(player_ptr_ct, p).customexitsound = soundnum
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_dummyplayersprite = function(p, spritenum)
|
|
||||||
if (not (spritenum < 0)) then
|
|
||||||
check_sprite_idx(spritenum)
|
|
||||||
end
|
|
||||||
ffi.cast(player_ptr_ct, p).dummyplayersprite = spritenum
|
|
||||||
end,
|
|
||||||
|
|
||||||
set_wackedbyactor = function(p, spritenum)
|
|
||||||
if (not (spritenum < 0)) then
|
|
||||||
check_sprite_idx(spritenum)
|
|
||||||
end
|
|
||||||
ffi.cast(player_ptr_ct, p).wackedbyactor = spritenum
|
|
||||||
end,
|
|
||||||
|
|
||||||
-- CON-like addammo/addweapon, but without the non-local control flow
|
-- CON-like addammo/addweapon, but without the non-local control flow
|
||||||
-- (returns true if weapon's ammo was at the max. instead).
|
-- (returns true if weapon's ammo was at the max. instead).
|
||||||
addammo = con._addammo,
|
addammo = con._addammo,
|
||||||
|
@ -1099,12 +1086,27 @@ local player_mt = {
|
||||||
pals.r, pals.g, pals.b = r, g, b
|
pals.r, pals.g, pals.b = r, g, b
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
__newindex = function(p, key, val)
|
||||||
|
-- Write access to protected player members.
|
||||||
|
|
||||||
|
local allowneg = DukePlayer_prot_allowneg[key]
|
||||||
|
assert(type(allowneg)=="boolean")
|
||||||
|
|
||||||
|
if (allowneg==false or not (val < 0)) then
|
||||||
|
DukePlayer_prot_chkfunc[key](val)
|
||||||
|
end
|
||||||
|
ffi.cast(player_ptr_ct, p)[key] = val
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function player_index_index(p, key)
|
local function player_index_index(p, key)
|
||||||
if (key=="_input") then
|
if (key=="_input") then
|
||||||
return ffiC.g_player[p.weapon._p].sync[0]
|
return ffiC.g_player[p.weapon._p].sync[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Read access to protected player members.
|
||||||
|
return ffi.cast(player_ptr_ct, p)[0][key]
|
||||||
end
|
end
|
||||||
|
|
||||||
setmtonce(player_mt.__index, { __index = player_index_index })
|
setmtonce(player_mt.__index, { __index = player_index_index })
|
||||||
|
|
|
@ -166,8 +166,9 @@ struct {
|
||||||
}]]
|
}]]
|
||||||
|
|
||||||
-- Converts a template struct definition to an internal, unrestricted one.
|
-- Converts a template struct definition to an internal, unrestricted one.
|
||||||
|
-- NOTE: "[^ ]*" for const decorations in defs.ilua.
|
||||||
function strip_const(structstr)
|
function strip_const(structstr)
|
||||||
return (string.gsub(structstr, "const ", ""));
|
return (string.gsub(structstr, "const[^ ]* ", ""));
|
||||||
end
|
end
|
||||||
|
|
||||||
-- NOTE for FFI definitions: we're compiling EDuke32 with -funsigned-char, so
|
-- NOTE for FFI definitions: we're compiling EDuke32 with -funsigned-char, so
|
||||||
|
|
|
@ -190,6 +190,10 @@ checkfail("gv.g_sizes_of=nil; print(gv.g_sizes_of[0])", "write access forbidden"
|
||||||
checkfail("gv.cam.sect=-1", "invalid sector number")
|
checkfail("gv.cam.sect=-1", "invalid sector number")
|
||||||
checkfail("local flag=gv.SFLAG_NULL", "missing declaration")
|
checkfail("local flag=gv.SFLAG_NULL", "missing declaration")
|
||||||
|
|
||||||
|
player[0].wackedbyactor = -1 -- should succeed
|
||||||
|
checkfail("player[0].curr_weapon = -1", "Invalid weapon ID")
|
||||||
|
player[0].curr_weapon = 1
|
||||||
|
|
||||||
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
||||||
|
|
||||||
gameevent(gv.EVENT_JUMP,
|
gameevent(gv.EVENT_JUMP,
|
||||||
|
|
|
@ -3570,7 +3570,7 @@ void P_FragPlayer(int32_t snum)
|
||||||
if (actor[p->i].picnum != APLAYERTOP)
|
if (actor[p->i].picnum != APLAYERTOP)
|
||||||
{
|
{
|
||||||
p->fraggedself++;
|
p->fraggedself++;
|
||||||
if (A_CheckEnemyTile(sprite[p->wackedbyactor].picnum))
|
if ((unsigned)p->wackedbyactor < MAXTILES && A_CheckEnemyTile(sprite[p->wackedbyactor].picnum))
|
||||||
Bsprintf(tempbuf,ScriptQuotes[OBITQUOTEINDEX+(krand()%g_numObituaries)],"A monster",&g_player[snum].user_name[0]);
|
Bsprintf(tempbuf,ScriptQuotes[OBITQUOTEINDEX+(krand()%g_numObituaries)],"A monster",&g_player[snum].user_name[0]);
|
||||||
else if (actor[p->i].picnum == NUKEBUTTON)
|
else if (actor[p->i].picnum == NUKEBUTTON)
|
||||||
Bsprintf(tempbuf,"^02%s^02 tried to leave",&g_player[snum].user_name[0]);
|
Bsprintf(tempbuf,"^02%s^02 tried to leave",&g_player[snum].user_name[0]);
|
||||||
|
|
|
@ -161,7 +161,7 @@ typedef struct {
|
||||||
// * int16_t --> int8_t
|
// * int16_t --> int8_t
|
||||||
// * char --> int8_t
|
// * char --> int8_t
|
||||||
// Need to carefully think about implications!
|
// Need to carefully think about implications!
|
||||||
// TODO: rearrange this is the opportunity arises!
|
// TODO: rearrange this if the opportunity arises!
|
||||||
// KEEPINSYNC lunatic/defs.ilua
|
// KEEPINSYNC lunatic/defs.ilua
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec3_t pos, opos, vel, npos;
|
vec3_t pos, opos, vel, npos;
|
||||||
|
|
Loading…
Reference in a new issue