Lunatic: rework weapondata_t __newindex handling for the sound members.

Also, in test.elua, add a currently failing must-fail test (i.e. it wrongly
succeeds where it should not!).

git-svn-id: https://svn.eduke32.com/eduke32@3954 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-07-13 21:04:59 +00:00
parent d7ad2c36d4
commit 9ecbd633aa
3 changed files with 46 additions and 19 deletions

View file

@ -309,6 +309,8 @@ end
wdata_members =
{
-- NOTE: they are lowercased for Lunatic
-- NOTE: members _*sound*, _spawn and _shoots assume *zero* to mean "none"
-- (-1 would be more logical).
"const int32_t _workslike",
"int32_t clip",
"int32_t reload",

View file

@ -194,6 +194,7 @@ local check_sprite_idx = bcheck.sprite_idx
local check_weapon_idx, check_inventory_idx = bcheck.weapon_idx, bcheck.inventory_idx
local check_sound_idx = bcheck.sound_idx
local check_number = bcheck.number
local check_type = bcheck.type
bcarray.new("int16_t", 64, "loogie", "int16_x_64") -- TODO: randomize member names
bcarray.new("int16_t", ffiC.MAX_WEAPONS, "weapon", "int16_x_MAX_WEAPONS", WEAPON_NAMES)
@ -967,6 +968,8 @@ end
local actor_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(ACTOR_STRUCT)))
local player_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(DUKEPLAYER_STRUCT)))
local projectile_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(PROJECTILE_STRUCT)))
-- An unrestricted weapondata_t pointer, but with the member names stripped of
-- the leading underscore, too:
local weapondata_ptr_ct = ffi.typeof("$ *", ffi.typeof((strip_const(WEAPONDATA_STRUCT):gsub(" _"," "))))
local con_action_ct = ffi.typeof("const con_action_t")
@ -1185,6 +1188,17 @@ ffi.metatype("actor_t", actor_mt)
--- PER-PLAYER WEAPON SETTINGS
local wd_sound_member = {}
for _, declstr in pairs(con_lang.wdata_members) do
local member = declstr:match("const int32_t _(.*sound)$")
if (member) then
wd_sound_member[member] = true
if (ffiC._DEBUG_LUNATIC ~= 0) then
printf("weapondata_t member %s denotes a sound", member)
end
end
end
local weapondata_mt = {
__index = function(wd, member)
-- Handle protected members that are renamed (e.g. shoots/_shoots).
@ -1195,11 +1209,12 @@ local weapondata_mt = {
-- Set to 'true' if we set a tile or sound member.
local didit = false
check_type(member, "string") -- MEMBER_IS_STRING
check_number(val)
if (string.match(member, "sound")) then
if (wd_sound_member[member]) then -- XXX: sound2time is a time, not a sound
if (val < 0) then
val = 0 -- Set to 0 if oob (e.g. CrackDown).
val = 0 -- Set to 0 if negative (e.g. CrackDown).
else
check_sound_idx(val)
end
@ -1218,7 +1233,13 @@ local weapondata_mt = {
didit = true
end
ffi.cast(weapondata_ptr_ct, wd)[0][member] = val
-- DEBUG:
-- printf("assigning %s to weapon's %s", tostring(val), member)
-- NOTE: we're indexing a *pointer* with the user-supplied 'member',
-- which could be dangerouns if it could be a number. However, we have
-- assured that is is not in MEMBER_IS_STRING above.
ffi.cast(weapondata_ptr_ct, wd)[member] = val
if (didit and ffiC.g_elCallDepth==0) then
-- Signal that we overrode this member at CON translation time.

View file

@ -1,7 +1,5 @@
-- test script for ELua/Lunatic Interpreter
--do return end
-- error=nil -- must not affect "require"
local string = require("string")
local bit = require("bit")
@ -31,14 +29,6 @@ local function checkfail(funcstr, expectedmsg)
end
end
--[[
---- check serialization ----
-- test nans, infs, precision, subnorms, booleans
ourvar2 = { "asd"; 0/0, 1/0, -1/0, 0.12345678901234567, 1e-314, true }
ourvar = { ourvar2; 1, 2, 3, "qwe"; [true]=0, [false]=1 }
ourvar[#ourvar+1] = ourvar;
--]]
gameevent
{
"ENTERLEVEL",
@ -47,13 +37,8 @@ gameevent
local vol, lev = gv.currentEpisode()+1, gv.currentLevel()+1
printf('volume=%d, level=%d', vol, lev)
---[[
if (vol ~= 4) then
-- Tweak some sector pals.
-- NOTE: you're not really supposed to modify game state from Lua file
-- scope! This is for testing only! E.g. it will fail if a savegame is
-- loaded from the menu when no other level is loaded.
print('tweaking sector pals')
print('numsectors: ' .. gv.numsectors .. ' of ' .. gv.MAXSECTORS)
@ -109,7 +94,6 @@ gameevent
local unsafe = pcall(function() string.UNSAFE=true; end)
--]]
--tostring = nil -- REMEMBER
--DBG_.printkv('_G in test.elua', _G)
@ -195,9 +179,25 @@ 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")
-- NOTE: player[0] is forbidden at file scope, this is just for testing purposes.
player[0].wackedbyactor = -1 -- should succeed
checkfail("player[0].curr_weapon = -1", "Invalid weapon ID")
player[0].curr_weapon = 1
checkfail("local w = player[0].weapon[-1]", "out-of-bounds weapon read access")
-- XXX: This gives a very strange error message: "attempt to write to constant location". Why?
-- (note how I forgot to index weapon with a weapon index or name)
--player[0].weapon.firesound = 1e5
checkfail("player[0].weapon.SHOTGUN.firesound = 1e5", "invalid sound number")
checkfail("player[0].weapon.SHOTGUN.firesound = 0/0", "must be a non-NaN number")
-- XXX XXX XXX: FAILS!
-- inf=1/0; inf >= 1ull <- yields FALSE on x86_64 (inf->uint64_t conversion: undefined!)
-- Related (Mike used 0ULL here): http://www.freelists.org/post/luajit/Stack-trace-on-SIGSEGV,4
checkfail("player[0].weapon.SHOTGUN.firesound = 1/0", "invalid sound number")
-- NOTE: It should only be relied on that setting e.g. .firesound to -1 sets it
-- to 0, not other negative values.
player[0].weapon.SHOTGUN.firesound = -1/0
assert(player[0].weapon.SHOTGUN.firesound == 0)
gameevent{gv.EVENT_JUMP,
function(actori, playeri, dist)
@ -246,6 +246,10 @@ gameevent
end
ps.weapon[gv.PISTOL_WEAPON].firesound = D.LIGHTNING_SLAP
-- This succeeds, because sound2time is a time, not a sound.
ps.weapon.SHOTGUN.sound2time = 5000
printf("set shotgun's sound2time to %d", ps.weapon.SHOTGUN.sound2time)
-- Set pipebomb and tripbomb to timed mode.
-- XXX: Provide either named constants or methods?
-- XXX: These are probably reset to default on new game.