From bbdc035335e8bf113b435aff047c0caa3c5578ab Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 7 Apr 2013 15:20:41 +0000 Subject: [PATCH] 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 --- polymer/eduke32/source/lunatic/con_lang.lua | 26 ++-- polymer/eduke32/source/lunatic/control.lua | 2 +- polymer/eduke32/source/lunatic/defs.ilua | 126 +++++++++--------- .../eduke32/source/lunatic/defs_common.lua | 3 +- polymer/eduke32/source/lunatic/test.elua | 4 + polymer/eduke32/source/player.c | 2 +- polymer/eduke32/source/player.h | 2 +- 7 files changed, 88 insertions(+), 77 deletions(-) diff --git a/polymer/eduke32/source/lunatic/con_lang.lua b/polymer/eduke32/source/lunatic/con_lang.lua index 2e14bc729..0b81a360e 100644 --- a/polymer/eduke32/source/lunatic/con_lang.lua +++ b/polymer/eduke32/source/lunatic/con_lang.lua @@ -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", diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index d352bca70..299995052 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -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 diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index 9b56db5cc..c26a3d39e 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -210,28 +210,29 @@ __attribute__((packed)) struct { int16_t sbs, sound_pitch; int16_t ang, oang, angvel; - const int16_t cursectnum; + const 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 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 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 int16_t dummyplayersprite; int16_t extra_extra8; int16_t actorsqu, timebeforeexit; - const int16_t customexitsound; + const 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

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 int8_t last_weapon; int8_t cheat_phase, weapon_pos; - const int8_t wantweaponfire, curr_weapon; + const int8_t wantweaponfire; + const 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 = {} -- [] = true if setting <0 allowed +local DukePlayer_prot_chkfunc = {} -- [] = + +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 handle protected scalars like "const ..." 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 }) diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua index 0b468b85c..00212a0ac 100644 --- a/polymer/eduke32/source/lunatic/defs_common.lua +++ b/polymer/eduke32/source/lunatic/defs_common.lua @@ -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 diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua index f5787c571..9a2ca96b7 100644 --- a/polymer/eduke32/source/lunatic/test.elua +++ b/polymer/eduke32/source/lunatic/test.elua @@ -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, diff --git a/polymer/eduke32/source/player.c b/polymer/eduke32/source/player.c index fbf27478d..ab075a325 100644 --- a/polymer/eduke32/source/player.c +++ b/polymer/eduke32/source/player.c @@ -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]); diff --git a/polymer/eduke32/source/player.h b/polymer/eduke32/source/player.h index 61913b612..a55001916 100644 --- a/polymer/eduke32/source/player.h +++ b/polymer/eduke32/source/player.h @@ -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;