mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +00:00
Lunatic: prototypical gamevar serialization, currently very CON-centric.
git-svn-id: https://svn.eduke32.com/eduke32@3796 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
f6ea669613
commit
0d79372216
9 changed files with 257 additions and 17 deletions
|
@ -163,6 +163,7 @@ ifneq (0,$(LUNATIC))
|
|||
$(OBJ)/luaJIT_BC_dump.$o \
|
||||
$(OBJ)/luaJIT_BC_dis_x86.$o \
|
||||
$(OBJ)/luaJIT_BC_dis_x64.$o \
|
||||
$(OBJ)/luaJIT_BC_savegame.$o \
|
||||
# TODO: remove debugging modules from release build
|
||||
|
||||
# now, take care of having the necessary symbols (sector, wall, etc.) in the
|
||||
|
|
|
@ -43,6 +43,8 @@ enum rendmode_t {
|
|||
|
||||
#ifdef LUNATIC
|
||||
# define NEW_MAP_FORMAT
|
||||
// Merely a marker for LuaJIT C function callbacks:
|
||||
# define LUNATIC_CB
|
||||
#else
|
||||
# ifdef NEW_MAP_FORMAT
|
||||
# error "New map format can only be used with Lunatic"
|
||||
|
|
|
@ -9795,7 +9795,7 @@ static void check_sprite(int32_t i)
|
|||
|
||||
#ifdef NEW_MAP_FORMAT
|
||||
// Returns the number of sprites, or <0 on error.
|
||||
int32_t (*loadboard_maptext)(int32_t fil, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
|
||||
LUNATIC_CB int32_t (*loadboard_maptext)(int32_t fil, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
|
||||
#endif
|
||||
|
||||
// flags: 1, 2: former parameter "fromwhere"
|
||||
|
@ -10501,7 +10501,7 @@ int32_t loadmaphack(const char *filename)
|
|||
|
||||
|
||||
#ifdef NEW_MAP_FORMAT
|
||||
int32_t (*saveboard_maptext)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
|
||||
LUNATIC_CB int32_t (*saveboard_maptext)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
|
||||
#endif
|
||||
|
||||
//
|
||||
|
|
|
@ -217,6 +217,8 @@ local mt = {
|
|||
__gc = function(s)
|
||||
anchor[tostring(s.arptr)] = nil
|
||||
end,
|
||||
|
||||
__metatable = true,
|
||||
}
|
||||
|
||||
ffi.metatype(bitar_ct, mt)
|
||||
|
|
|
@ -11,6 +11,8 @@ local CF = CF
|
|||
local bit = require("bit")
|
||||
local io = require("io")
|
||||
local math = require("math")
|
||||
local table = require("table")
|
||||
|
||||
local geom = require("geom")
|
||||
local bcheck = require("bcheck")
|
||||
local con_lang = require("con_lang")
|
||||
|
@ -21,6 +23,7 @@ local setmetatable = setmetatable
|
|||
local assert = assert
|
||||
local error = error
|
||||
local ipairs = ipairs
|
||||
local pairs = pairs
|
||||
local print = print
|
||||
local rawget = rawget
|
||||
local rawset = rawset
|
||||
|
@ -38,6 +41,9 @@ local inside = dc.inside
|
|||
local sector, wall, sprite = dc.sector, dc.wall, dc.sprite
|
||||
local spritesofsect, spritesofstat = dc.spritesofsect, dc.spritesofstat
|
||||
|
||||
local OUR_NAME = "_con"
|
||||
local OUR_REQUIRE_STRING = "local "..OUR_NAME.."=require'con'"
|
||||
|
||||
|
||||
module(...)
|
||||
|
||||
|
@ -1762,6 +1768,19 @@ local function kopen4load(fn, searchfirst)
|
|||
end
|
||||
|
||||
|
||||
-- Common serialization function for gamearray and peractorvar.
|
||||
local function serialize_array(ar, strtab)
|
||||
for i,v in pairs(ar) do
|
||||
if (type(i)=="number") then
|
||||
assert(type(v)=="number") -- XXX: not enforced by public API
|
||||
strtab[#strtab+1] = "["..i.."]="..tostring(v)..","
|
||||
end
|
||||
end
|
||||
strtab[#strtab+1] = "})"
|
||||
|
||||
return table.concat(strtab)
|
||||
end
|
||||
|
||||
--- Game arrays ---
|
||||
|
||||
local function moddir_filename(cstr_fn)
|
||||
|
@ -1907,7 +1926,19 @@ local gamearray_methods = {
|
|||
f:write(GAR_FOOTER)
|
||||
|
||||
f:close()
|
||||
end
|
||||
end,
|
||||
|
||||
|
||||
--- Serialization ---
|
||||
|
||||
_get_require = function(gar)
|
||||
return OUR_REQUIRE_STRING
|
||||
end,
|
||||
|
||||
_serialize = function(gar)
|
||||
local strtab = { OUR_NAME..".peractorvar(", tostring(gar._size), ",{" }
|
||||
return serialize_array(gar, strtab)
|
||||
end,
|
||||
}
|
||||
|
||||
local gamearray_mt = {
|
||||
|
@ -1935,15 +1966,29 @@ local gamearray_mt = {
|
|||
end
|
||||
end,
|
||||
|
||||
__metatable = true,
|
||||
__metatable = "serializeable",
|
||||
}
|
||||
|
||||
function _gamearray(size)
|
||||
return setmetatable({ _size=size }, gamearray_mt)
|
||||
-- Common constructor helper for gamearray and peractorvar.
|
||||
local function set_values_from_table(ar, values)
|
||||
if (values ~= nil) then
|
||||
for i,v in pairs(values) do
|
||||
ar[i] = v
|
||||
end
|
||||
end
|
||||
return ar
|
||||
end
|
||||
|
||||
-- NOTE: Gamearrays are internal because users are encouraged to use tables
|
||||
-- from Lua code.
|
||||
-- <values>: optional, a table of <index>=value
|
||||
function _gamearray(size, values)
|
||||
local gar = setmetatable({ _size=size }, gamearray_mt)
|
||||
return set_values_from_table(gar, values)
|
||||
end
|
||||
|
||||
|
||||
--- Exported functions ---
|
||||
--- More functions of the official API ---
|
||||
|
||||
-- Non-local control flow. These ones call the original error(), not our
|
||||
-- redefinition in defs.ilua.
|
||||
|
@ -1957,12 +2002,29 @@ function killit()
|
|||
end
|
||||
|
||||
|
||||
-- Per-actor variable
|
||||
-- TODO: serialization
|
||||
-- Per-actor variable.
|
||||
local peractorvar_methods = {
|
||||
--- Serialization ---
|
||||
|
||||
_get_require = function(acv)
|
||||
return OUR_REQUIRE_STRING
|
||||
end,
|
||||
|
||||
_serialize = function(acv)
|
||||
local strtab = { OUR_NAME..".peractorvar(", tostring(acv._defval), ",{" }
|
||||
return serialize_array(acv, strtab)
|
||||
end,
|
||||
}
|
||||
|
||||
-- XXX: How about types other than numbers?
|
||||
local peractorvar_mt = {
|
||||
__index = function(acv, idx)
|
||||
check_sprite_idx(idx)
|
||||
return acv._defval
|
||||
if (type(idx)=="number") then
|
||||
check_sprite_idx(idx)
|
||||
return acv._defval
|
||||
else
|
||||
return peractorvar_methods[idx]
|
||||
end
|
||||
end,
|
||||
|
||||
__newindex = function(acv, idx, val)
|
||||
|
@ -1981,9 +2043,12 @@ local peractorvar_mt = {
|
|||
end
|
||||
end,
|
||||
|
||||
__metatable = true,
|
||||
__metatable = "serializeable",
|
||||
}
|
||||
|
||||
function peractorvar(initval)
|
||||
return setmetatable({ _defval=initval }, peractorvar_mt)
|
||||
-- <initval>: default value for per-actor variable.
|
||||
-- <values>: optional, a table of <spritenum>=value
|
||||
function peractorvar(initval, values)
|
||||
local acv = setmetatable({ _defval=initval }, peractorvar_mt)
|
||||
return set_values_from_table(acv, values)
|
||||
end
|
||||
|
|
|
@ -570,6 +570,8 @@ int32_t g_elCONSize;
|
|||
char *g_elCON;
|
||||
void El_SetCON(const char *conluacode);
|
||||
|
||||
const char *(*El_SerializeGamevars)(int32_t *slenptr);
|
||||
|
||||
const char *s_buildRev;
|
||||
const char *g_sizes_of_what[];
|
||||
int32_t g_sizes_of[];
|
||||
|
@ -1273,7 +1275,9 @@ do
|
|||
end
|
||||
|
||||
|
||||
local package_loaded = {} -- false/true/table
|
||||
---=== Module stuff ===---
|
||||
|
||||
local package_loaded = {} -- [<modname>] = false/true/table
|
||||
local modname_stack = {} -- [<depth>]=string
|
||||
local module_gamevars = {} -- [<modname>] = { <gvname1>, <gvname2>, ... }
|
||||
|
||||
|
@ -1722,6 +1726,64 @@ do
|
|||
set_tweak_traceback_internal(tweak_traceback_msg)
|
||||
end
|
||||
|
||||
-- XXX: May still be require'd from user code, we don't want that (at least not
|
||||
-- under this name).
|
||||
local CON_MODULE_NAME = "_CON\0"
|
||||
|
||||
-- Set up Lunatic gamevar serialization.
|
||||
do
|
||||
local savegame = require("savegame")
|
||||
|
||||
-- Callback for: const char *(int32_t *slenptr);
|
||||
ffiC.El_SerializeGamevars = function(slenptr)
|
||||
local sb = savegame.savebuffer()
|
||||
|
||||
sb:addraw("local M")
|
||||
|
||||
-- XXX: System gamevars?
|
||||
for modname, modvars in pairs(module_gamevars) do
|
||||
sb:addrawf("M=require%q", modname)
|
||||
for i=1,#modvars do
|
||||
local varname = modvars[i]
|
||||
-- Serialize gamevar named 'varname' from module named 'modname'.
|
||||
-- XXX: May error. This will terminate EDuke32 since this callback
|
||||
-- is run unprotected.
|
||||
if (sb:add("M."..varname, package_loaded[modname][varname])) then
|
||||
-- We couldn't serialize that gamevar.
|
||||
slenptr[0] = -1
|
||||
-- Signal which gamevar that was.
|
||||
return (modname==CON_MODULE_NAME and "<CON>" or modname).."."..varname
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get the whole code as a string.
|
||||
local savecode = sb:getcode()
|
||||
|
||||
if (ffiC._DEBUG_LUNATIC ~= 0) then
|
||||
-- Dump the code if Lunatic debugging is enabled and there is a
|
||||
-- LUNATIC_SAVECODE_FN variable in the environment.
|
||||
local os = require("os")
|
||||
local fn = os.getenv("LUNATIC_SAVECODE_FN")
|
||||
|
||||
if (fn ~= nil) then
|
||||
local io = require("io")
|
||||
local f = io.open(fn, "w")
|
||||
|
||||
if (f ~= nil) then
|
||||
f:write(savecode)
|
||||
f:close()
|
||||
printf("Wrote Lunatic gamevar restoration code to \"%s\".", fn)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the size of the code and return the code to C.
|
||||
slenptr[0] = #savecode
|
||||
return savecode
|
||||
end
|
||||
end
|
||||
|
||||
-- change the environment of this chunk to the table G_
|
||||
-- NOTE: all references to global variables from this point on
|
||||
-- (also in functions created after this point) refer to G_ !
|
||||
|
@ -1839,7 +1901,9 @@ if (concode) then
|
|||
if (confunc == nil) then
|
||||
error("Failure loading translated CON code: "..conerrmsg, 0)
|
||||
end
|
||||
confunc()
|
||||
|
||||
package_loaded[CON_MODULE_NAME] = confunc()
|
||||
module_gamevars[CON_MODULE_NAME] = { "A", "V" } -- See CON_GAMEVARS is lunacon.lua.
|
||||
end
|
||||
|
||||
-- When starting a map, load Lua modules given on the command line.
|
||||
|
|
|
@ -90,6 +90,8 @@ g_elCONSize;
|
|||
g_elCON;
|
||||
El_SetCON;
|
||||
|
||||
El_SerializeGamevars;
|
||||
|
||||
s_buildRev;
|
||||
g_sizes_of_what;
|
||||
g_sizes_of;
|
||||
|
@ -163,6 +165,7 @@ luaJIT_BC_v;
|
|||
luaJIT_BC_dump;
|
||||
luaJIT_BC_dis_x86;
|
||||
luaJIT_BC_dis_x64;
|
||||
luaJIT_BC_savegame;
|
||||
|
||||
rand_jkiss_u32;
|
||||
rand_jkiss_dbl;
|
||||
|
|
|
@ -3139,6 +3139,9 @@ end
|
|||
|
||||
-- <lineinfop>: Get line info?
|
||||
local function get_code_string(codetab, lineinfop)
|
||||
-- Finalize translated code: return table containing gamevar and gamearray
|
||||
-- tables. CON_GAMEVARS.
|
||||
codetab[#codetab+1] = "return { V=_V, A=_A }"
|
||||
local flatcode = flatten_codetab(codetab)
|
||||
local lineinfo = lineinfop and get_lineinfo(flatcode)
|
||||
return table.concat(flatcode, "\n"), lineinfo
|
||||
|
|
|
@ -25,6 +25,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "menus.h" // menutext
|
||||
#include "prlights.h"
|
||||
#include "savegame.h"
|
||||
#ifdef LUNATIC
|
||||
# include "lunatic_game.h"
|
||||
static int32_t g_savedOK;
|
||||
const char *g_failedVarname;
|
||||
#endif
|
||||
|
||||
extern char *bitptr;
|
||||
|
||||
|
@ -354,7 +359,12 @@ int32_t G_SavePlayer(int32_t spot)
|
|||
|
||||
if (!g_netServer && ud.multimode < 2)
|
||||
{
|
||||
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "Game Saved");
|
||||
#ifdef LUNATIC
|
||||
if (!g_savedOK)
|
||||
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "^10Failed Saving Game");
|
||||
else
|
||||
#endif
|
||||
Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "Game Saved");
|
||||
P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
|
||||
}
|
||||
|
||||
|
@ -1205,6 +1215,15 @@ int32_t sv_saveandmakesnapshot(FILE *fil, int8_t spot, int8_t recdiffsp, int8_t
|
|||
{
|
||||
// savegame
|
||||
dosaveplayer2(fil, NULL);
|
||||
#ifdef LUNATIC
|
||||
if (!g_savedOK)
|
||||
{
|
||||
OSD_Printf("sv_saveandmakesnapshot: failed serializing Lunatic gamevar %s.\n",
|
||||
g_failedVarname);
|
||||
g_failedVarname = NULL;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1313,6 +1332,11 @@ int32_t sv_loadsnapshot(int32_t fil, int32_t spot, savehead_t *h)
|
|||
|
||||
savegame_comprthres = h->comprthres;
|
||||
|
||||
#ifdef LUNATIC
|
||||
El_CreateGameState();
|
||||
G_PostCreateGameState();
|
||||
#endif
|
||||
|
||||
if (spot >= 0)
|
||||
{
|
||||
// savegame
|
||||
|
@ -1650,6 +1674,10 @@ static void sv_restload()
|
|||
# define PRINTSIZE(name) do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef LUNATIC
|
||||
LUNATIC_CB const char *(*El_SerializeGamevars)(int32_t *slenptr);
|
||||
#endif
|
||||
|
||||
static uint8_t *dosaveplayer2(FILE *fil, uint8_t *mem)
|
||||
{
|
||||
#ifdef DEBUGGINGAIDS
|
||||
|
@ -1669,6 +1697,27 @@ static uint8_t *dosaveplayer2(FILE *fil, uint8_t *mem)
|
|||
Gv_WriteSave(fil, 1); // gamevars
|
||||
mem=writespecdata(svgm_vars, 0, mem);
|
||||
PRINTSIZE("vars");
|
||||
#else
|
||||
{
|
||||
int32_t slen, slen_ext;
|
||||
const char *svcode = El_SerializeGamevars(&slen);
|
||||
|
||||
if (slen < 0)
|
||||
{
|
||||
// Serialization failed.
|
||||
g_savedOK = 0;
|
||||
g_failedVarname = svcode;
|
||||
return mem;
|
||||
}
|
||||
|
||||
// TODO: compress text.
|
||||
fwrite("\0\1LunaGVAR\3\4", 12, 1, fil);
|
||||
slen_ext = B_LITTLE32(slen);
|
||||
fwrite(&slen_ext, sizeof(slen_ext), 1, fil);
|
||||
fwrite(svcode, slen, 1, fil);
|
||||
|
||||
g_savedOK = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
|
@ -1708,6 +1757,57 @@ static int32_t doloadplayer2(int32_t fil, uint8_t **memptr)
|
|||
}
|
||||
}
|
||||
PRINTSIZE("vars");
|
||||
#else
|
||||
{
|
||||
// Read Lua code to restore gamevar values from the savegame and run it.
|
||||
|
||||
char header[12];
|
||||
int32_t slen;
|
||||
|
||||
if (kread(fil, header, 12) != 12)
|
||||
{
|
||||
OSD_Printf("doloadplayer2: failed reading Lunatic gamevar header.\n");
|
||||
return -100;
|
||||
}
|
||||
|
||||
if (Bmemcmp(header, "\0\1LunaGVAR\3\4", 12))
|
||||
{
|
||||
OSD_Printf("doloadplayer2: Lunatic gamevar header doesn't match.\n");
|
||||
return -101;
|
||||
}
|
||||
|
||||
if (kread(fil, &slen, sizeof(slen)) != sizeof(slen))
|
||||
{
|
||||
OSD_Printf("doloadplayer2: failed reading Lunatic gamevar string size.\n");
|
||||
return -102;
|
||||
}
|
||||
|
||||
slen = B_LITTLE32(slen);
|
||||
if (slen < 0)
|
||||
{
|
||||
OSD_Printf("doloadplayer2: invalid Lunatic gamevar string size %d.\n", slen);
|
||||
return -103;
|
||||
}
|
||||
|
||||
if (slen > 0)
|
||||
{
|
||||
char *svcode = Bmalloc(slen);
|
||||
if (svcode == NULL)
|
||||
G_GameExit("OUT OF MEMORY in doloadplayer2().");
|
||||
|
||||
if (kread(fil, svcode, slen) != slen)
|
||||
{
|
||||
OSD_Printf("doloadplayer2: failed reading Lunatic gamevar restoration code.\n");
|
||||
return -104;
|
||||
}
|
||||
|
||||
if (L_RunString(&g_ElState, svcode, 0, slen, "luaload"))
|
||||
{
|
||||
OSD_Printf("doloadplayer2: failed restoring Lunatic gamevars.\n");
|
||||
return -105;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (memptr)
|
||||
|
|
Loading…
Reference in a new issue