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
|
||||
|
||||
-- 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
|
||||
|
||||
local STR = {
|
||||
|
@ -516,17 +520,17 @@ local PlayerLabels = {
|
|||
oang = PL".oang",
|
||||
angvel = PL".angvel",
|
||||
|
||||
cursectnum = { PL".cursectnum", PL":set_cursectnum(%%s)" },
|
||||
cursectnum = PL".cursectnum",
|
||||
|
||||
look_ang = PL".look_ang",
|
||||
last_extra = PL".last_extra",
|
||||
subweapon = PL".subweapon",
|
||||
|
||||
max_ammo_amount = PL".max_ammo_amount[%s]" ,
|
||||
ammo_amount = PL".ammo_amount[%s]" ,
|
||||
max_ammo_amount = PL".max_ammo_amount[%s]",
|
||||
ammo_amount = PL".ammo_amount[%s]",
|
||||
-- NOTE: no direct access for .inv_amount (but see end)
|
||||
|
||||
wackedbyactor = { PL".wackedbyactor", PL":set_wackedbyactor(%%s)" },
|
||||
wackedbyactor = PL".wackedbyactor",
|
||||
pyoff = PL".pyoff",
|
||||
opyoff = PL".opyoff",
|
||||
|
||||
|
@ -541,7 +545,7 @@ local PlayerLabels = {
|
|||
airleft = PL".airleft",
|
||||
|
||||
fta = PL".fta",
|
||||
ftq = { PL".ftq", PL":set_ftq(%%s)" },
|
||||
ftq = PL".ftq",
|
||||
access_wallnum = { PL".access_wallnum" },
|
||||
access_spritenum = { PL".access_spritenum" },
|
||||
|
||||
|
@ -559,7 +563,7 @@ local PlayerLabels = {
|
|||
random_club_frame = PL".random_club_frame",
|
||||
one_eighty_count = PL".one_eighty_count",
|
||||
|
||||
dummyplayersprite = { PL".dummyplayersprite", PL":set_dummyplayersprite(%%s)" },
|
||||
dummyplayersprite = PL".dummyplayersprite",
|
||||
extra_extra8 = PL".extra_extra8",
|
||||
|
||||
actorsqu = PL".actorsqu",
|
||||
|
@ -568,7 +572,7 @@ local PlayerLabels = {
|
|||
|
||||
last_pissed_time = PL".last_pissed_time",
|
||||
|
||||
weaprecs = PL".weaprecs[%s]" ,
|
||||
weaprecs = PL".weaprecs[%s]",
|
||||
|
||||
weapon_sway = PL".weapon_sway",
|
||||
crack_time = PL".crack_time",
|
||||
|
@ -649,12 +653,12 @@ local PlayerLabels = {
|
|||
loogcnt = PL".loogcnt",
|
||||
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",
|
||||
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",
|
||||
|
||||
|
|
|
@ -1130,7 +1130,7 @@ end
|
|||
|
||||
function _endofgame(pli, timebeforeexit)
|
||||
player[pli].timebeforeexit = timebeforeexit
|
||||
player[pli]:set_customexitsound(-1)
|
||||
player[pli].customexitsound = -1
|
||||
ffiC.ud.eog = 1
|
||||
end
|
||||
|
||||
|
|
|
@ -210,28 +210,29 @@ __attribute__((packed)) struct {
|
|||
int16_t sbs, sound_pitch;
|
||||
|
||||
int16_t ang, oang, angvel;
|
||||
const int16_t cursectnum;
|
||||
const<S> int16_t cursectnum;
|
||||
int16_t look_ang, last_extra, subweapon;
|
||||
int16_x_MAX_WEAPONS max_ammo_amount;
|
||||
int16_x_MAX_WEAPONS ammo_amount;
|
||||
int16_x_GET_MAX inv_amount;
|
||||
const int16_t wackedbyactor;
|
||||
const<I-> int16_t wackedbyactor;
|
||||
int16_t pyoff, opyoff;
|
||||
|
||||
int16_t horiz, horizoff, ohoriz, ohorizoff;
|
||||
const int16_t newowner;
|
||||
int16_t jumping_counter, airleft;
|
||||
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 somethingonplayer, on_crane;
|
||||
const int16_t i;
|
||||
const int16_t one_parallax_sectnum;
|
||||
int16_t random_club_frame, one_eighty_count;
|
||||
const int16_t dummyplayersprite;
|
||||
const<I-> int16_t dummyplayersprite;
|
||||
int16_t extra_extra8;
|
||||
int16_t actorsqu, timebeforeexit;
|
||||
const int16_t customexitsound;
|
||||
const<X-> int16_t customexitsound;
|
||||
int16_t last_pissed_time;
|
||||
|
||||
int16_x_MAX_WEAPONS weaprecs;
|
||||
|
@ -248,7 +249,7 @@ __attribute__((packed)) struct {
|
|||
const uint8_t weapreccnt;
|
||||
uint8_t aim_mode, auto_aim, weaponswitch, movement_lock, team;
|
||||
uint8_t tipincs, hbomb_hold_delay;
|
||||
const uint8_t frag_ps;
|
||||
const<P> uint8_t frag_ps;
|
||||
uint8_t kickback_pic;
|
||||
|
||||
uint8_t gm;
|
||||
|
@ -278,9 +279,10 @@ __attribute__((packed)) struct {
|
|||
uint8_t walking_snd_toggle, palookup, hard_landing, fist_incs;
|
||||
|
||||
int8_t numloogs, loogcnt, scream_voice;
|
||||
const int8_t last_weapon;
|
||||
const<W-> int8_t last_weapon;
|
||||
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;
|
||||
palette_t _pals;
|
||||
|
@ -337,15 +339,44 @@ local function ma_replace_array(typestr, neltstr)
|
|||
return table.concat(strtab)
|
||||
end
|
||||
|
||||
-- Converts a template struct definition to an external one, in which arrays
|
||||
-- have been substituted by randomly named scalar fields.
|
||||
local function mangle_arrays(structstr)
|
||||
ma_count = 0
|
||||
-- NOTE: regexp only works for non-nested arrays and for one array per line.
|
||||
return (string.gsub(structstr, "const%s+([%w_]+)[^\n]+%[([%w_]+)%];", ma_replace_array))
|
||||
---=== Protection of scalars in (currently only) DukePlayer_t struct. ===---
|
||||
-- This is more convenient than writing dozens of set-member methods.
|
||||
local prot_scalar_chkfunc = {
|
||||
S = check_sector_idx,
|
||||
I = check_sprite_idx,
|
||||
|
||||
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
|
||||
|
||||
--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.
|
||||
local con_lang = require("con_lang")
|
||||
|
@ -365,7 +396,7 @@ typedef
|
|||
actor_t;
|
||||
|
||||
typedef
|
||||
]].. mangle_arrays(DUKEPLAYER_STRUCT) ..[[
|
||||
]].. mangle_arrays(DUKEPLAYER_STRUCT, true) ..[[
|
||||
DukePlayer_t;
|
||||
|
||||
typedef __attribute__((packed)) struct {
|
||||
|
@ -963,7 +994,7 @@ ffi.metatype("actor_t", actor_mt)
|
|||
local weapondata_mt = {
|
||||
__index = function(wd, member)
|
||||
-- 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,
|
||||
|
||||
__newindex = function(wd, member, val)
|
||||
|
@ -986,7 +1017,7 @@ local weapondata_mt = {
|
|||
end
|
||||
end
|
||||
|
||||
ffi.cast(weapondata_ptr_ct, wd)[member] = val
|
||||
ffi.cast(weapondata_ptr_ct, wd)[0][member] = val
|
||||
end,
|
||||
}
|
||||
ffi.metatype("weapondata_t", weapondata_mt)
|
||||
|
@ -1007,50 +1038,6 @@ ffi.metatype("weaponaccess_t", weaponaccess_mt)
|
|||
|
||||
local player_mt = {
|
||||
__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
|
||||
-- (returns true if weapon's ammo was at the max. instead).
|
||||
addammo = con._addammo,
|
||||
|
@ -1099,12 +1086,27 @@ local player_mt = {
|
|||
pals.r, pals.g, pals.b = r, g, b
|
||||
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)
|
||||
if (key=="_input") then
|
||||
return ffiC.g_player[p.weapon._p].sync[0]
|
||||
end
|
||||
|
||||
-- Read access to protected player members.
|
||||
return ffi.cast(player_ptr_ct, p)[0][key]
|
||||
end
|
||||
|
||||
setmtonce(player_mt.__index, { __index = player_index_index })
|
||||
|
|
|
@ -166,8 +166,9 @@ struct {
|
|||
}]]
|
||||
|
||||
-- Converts a template struct definition to an internal, unrestricted one.
|
||||
-- NOTE: "[^ ]*" for const decorations in defs.ilua.
|
||||
function strip_const(structstr)
|
||||
return (string.gsub(structstr, "const ", ""));
|
||||
return (string.gsub(structstr, "const[^ ]* ", ""));
|
||||
end
|
||||
|
||||
-- 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("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))
|
||||
|
||||
gameevent(gv.EVENT_JUMP,
|
||||
|
|
|
@ -3570,7 +3570,7 @@ void P_FragPlayer(int32_t snum)
|
|||
if (actor[p->i].picnum != APLAYERTOP)
|
||||
{
|
||||
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]);
|
||||
else if (actor[p->i].picnum == NUKEBUTTON)
|
||||
Bsprintf(tempbuf,"^02%s^02 tried to leave",&g_player[snum].user_name[0]);
|
||||
|
|
|
@ -161,7 +161,7 @@ typedef struct {
|
|||
// * int16_t --> int8_t
|
||||
// * char --> int8_t
|
||||
// Need to carefully think about implications!
|
||||
// TODO: rearrange this is the opportunity arises!
|
||||
// TODO: rearrange this if the opportunity arises!
|
||||
// KEEPINSYNC lunatic/defs.ilua
|
||||
typedef struct {
|
||||
vec3_t pos, opos, vel, npos;
|
||||
|
|
Loading…
Reference in a new issue