mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-15 17:01:28 +00:00
Lunatic: first prototype of map-text saving.
git-svn-id: https://svn.eduke32.com/eduke32@3733 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
65a10afbc8
commit
3b65dc3a78
7 changed files with 333 additions and 35 deletions
|
@ -143,8 +143,9 @@ MISCEDITORDEPS=
|
|||
|
||||
## Lunatic devel
|
||||
ifneq (0,$(LUNATIC))
|
||||
EDITOROBJS+= $(OBJ)/lunatic_m32.$o $(OBJ)/luaJIT_BC_defs_common.$o
|
||||
GAMEOBJS+= $(OBJ)/lunatic_game.$o $(OBJ)/luaJIT_BC_defs_common.$o
|
||||
LUNATIC_COMMON_OBJS = $(OBJ)/luaJIT_BC_defs_common.$o $(OBJ)/luaJIT_BC_engine_maptext.$o
|
||||
EDITOROBJS+= $(OBJ)/lunatic_m32.$o $(LUNATIC_COMMON_OBJS)
|
||||
GAMEOBJS+= $(OBJ)/lunatic_game.$o $(LUNATIC_COMMON_OBJS)
|
||||
|
||||
GAMEOBJS+= $(OBJ)/../lpeg.$o # TEMP
|
||||
GAMEOBJS+= $(OBJ)/luaJIT_BC_con_lang.$o \
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
|
||||
#include "engine_priv.h"
|
||||
|
||||
#ifdef LUNATIC
|
||||
# include "lunatic.h"
|
||||
L_State g_engState;
|
||||
#endif
|
||||
|
||||
#define CACHEAGETIME 16
|
||||
//#define CLASSIC_NONPOW2_YSIZE_WALLS
|
||||
#define CLASSIC_NONPOW2_YSIZE_SPRITES
|
||||
|
@ -8610,6 +8615,18 @@ int32_t initengine(void)
|
|||
if (!mdinited) mdinit();
|
||||
#endif
|
||||
|
||||
#ifdef LUNATIC
|
||||
if (L_CreateState(&g_engState, "eng", NULL))
|
||||
return loadpalette_err("Failed creating engine Lua state!");
|
||||
|
||||
{
|
||||
char *luastr = "_LUNATIC_AUX=true; decl=require('ffi').cdef; require'defs_common'";
|
||||
|
||||
if (L_RunString(&g_engState, luastr, 0, -1, "eng"))
|
||||
return loadpalette_err("Failed setting up engine Lua state");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10447,6 +10464,10 @@ 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);
|
||||
#endif
|
||||
|
||||
//
|
||||
// saveboard
|
||||
//
|
||||
|
@ -10455,18 +10476,7 @@ int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int1
|
|||
int16_t numsprites, ts;
|
||||
int32_t i, j, fil, tl;
|
||||
|
||||
#ifdef NEW_MAP_FORMAT
|
||||
// Writing new-format (Lunatic) maps not yet implemented; V9 not available then.
|
||||
if (numyaxbunches > 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if ((fil = Bopen(filename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
|
||||
{
|
||||
initprintf("Couldn't open \"%s\" for writing: %s\n", filename, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// First, some checking.
|
||||
for (j=0; j<MAXSPRITES; j++)
|
||||
{
|
||||
if ((unsigned)sprite[j].statnum > MAXSTATUS)
|
||||
|
@ -10496,6 +10506,19 @@ int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int1
|
|||
// and the engine-reported number of sprites 'Numsprites'.
|
||||
Bassert(numsprites == Numsprites);
|
||||
|
||||
#ifdef NEW_MAP_FORMAT
|
||||
if (numyaxbunches > 0)
|
||||
return saveboard_maptext(filename, dapos, daang, dacursectnum);
|
||||
#endif
|
||||
|
||||
fil = Bopen(filename, BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY, BS_IREAD|BS_IWRITE);
|
||||
|
||||
if (fil == -1)
|
||||
{
|
||||
initprintf("Couldn't open \"%s\" for writing: %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine the map version.
|
||||
#ifdef YAX_ENABLE
|
||||
if (numyaxbunches > 0)
|
||||
|
@ -10649,11 +10672,11 @@ int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int1
|
|||
}
|
||||
|
||||
Bclose(fil);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bclose(fil);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
-- environment.
|
||||
-- See the included license file "BUILDLIC.TXT" for license info.
|
||||
|
||||
-- Will be 'true' if running from engine Lua state:
|
||||
local _LUNATIC_AUX = _LUNATIC_AUX
|
||||
|
||||
local ffi = require("ffi")
|
||||
local ffiC = ffi.C
|
||||
local bit = require("bit")
|
||||
|
@ -19,10 +22,12 @@ if (bit.band(ffiC._DEBUG_LUNATIC, 2)~=0) then
|
|||
require("jit").off()
|
||||
end
|
||||
|
||||
if (bit.band(ffiC._DEBUG_LUNATIC, 8)~=0) then
|
||||
require("dump").on("+rs")
|
||||
elseif (bit.band(ffiC._DEBUG_LUNATIC, 4)~=0) then
|
||||
require("v").on()
|
||||
if (not _LUNATIC_AUX) then
|
||||
if (bit.band(ffiC._DEBUG_LUNATIC, 8)~=0) then
|
||||
require("dump").on("+rs")
|
||||
elseif (bit.band(ffiC._DEBUG_LUNATIC, 4)~=0) then
|
||||
require("v").on()
|
||||
end
|
||||
end
|
||||
|
||||
local math = require("math")
|
||||
|
@ -37,7 +42,7 @@ local setmetatable = setmetatable
|
|||
local tostring = tostring
|
||||
local type = type
|
||||
|
||||
local decl = decl
|
||||
local decl = assert(decl)
|
||||
local getfenv = getfenv
|
||||
|
||||
decl "void OSD_Printf(const char *fmt, ...);"
|
||||
|
@ -180,6 +185,10 @@ function strip_const(structstr)
|
|||
return (string.gsub(structstr, "const[^ ]* ", ""));
|
||||
end
|
||||
|
||||
local function maybe_strip_const(str)
|
||||
return _LUNATIC_AUX and strip_const(str) or str
|
||||
end
|
||||
|
||||
-- NOTE for FFI definitions: we're compiling EDuke32 with -funsigned-char, so
|
||||
-- we need to take care to declare chars as unsigned whenever it matters, for
|
||||
-- example if it represents a palette index. (I think it's harmless for stuff
|
||||
|
@ -218,22 +227,29 @@ typedef struct {
|
|||
int16_t sprite, wall, sect;
|
||||
} hitdata_t;
|
||||
]],
|
||||
ffi.typeof(SECTOR_STRUCT), ffi.typeof(WALL_STRUCT),
|
||||
ffi.typeof(SPRITE_STRUCT))
|
||||
ffi.typeof(maybe_strip_const(SECTOR_STRUCT)),
|
||||
ffi.typeof(maybe_strip_const(WALL_STRUCT)),
|
||||
ffi.typeof(maybe_strip_const(SPRITE_STRUCT)))
|
||||
|
||||
-- Define the "palette_t" type, which for us has .{r,g,b} fields and a
|
||||
-- bound-checking array of length 3 overlaid.
|
||||
local rgbarray_t = require("bcarray").new("uint8_t", 3, "RGB array", "palette_t",
|
||||
{ "r", "g", "b", "f" })
|
||||
ffi.cdef("typedef union { \
|
||||
struct { uint8_t r, g, b, f; }; \
|
||||
$ col; \
|
||||
} palette_t", rgbarray_t)
|
||||
assert(ffi.alignof("palette_t")==1)
|
||||
if (not _LUNATIC_AUX) then
|
||||
-- Define the "palette_t" type, which for us has .{r,g,b} fields and a
|
||||
-- bound-checking array of length 3 overlaid.
|
||||
local rgbarray_t = require("bcarray").new("uint8_t", 3, "RGB array", "palette_t",
|
||||
{ "r", "g", "b", "f" })
|
||||
ffi.cdef("typedef union { \
|
||||
struct { uint8_t r, g, b, f; }; \
|
||||
$ col; \
|
||||
} palette_t", rgbarray_t)
|
||||
|
||||
assert(ffi.alignof("palette_t")==1)
|
||||
end
|
||||
|
||||
local vec3_ct = ffi.typeof("vec3_t") -- will be metatype'd in geom.lua:
|
||||
require("geom")
|
||||
local hitdata_ct = ffi.typeof("hitdata_t")
|
||||
|
||||
if (not _LUNATIC_AUX) then
|
||||
require("geom")
|
||||
local hitdata_ct = ffi.typeof("hitdata_t")
|
||||
end
|
||||
|
||||
decl[[
|
||||
const int32_t engine_main_arrays_are_static;
|
||||
|
@ -311,6 +327,12 @@ const int32_t xdim, ydim;
|
|||
const int32_t windowx1, windowy1, windowx2, windowy2;
|
||||
]]
|
||||
|
||||
if (_LUNATIC_AUX) then
|
||||
require "engine_maptext"
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
decl[[
|
||||
int32_t yxaspect;
|
||||
int32_t viewingrange;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
engine_main_arrays_are_static;
|
||||
engine_v8;
|
||||
|
||||
saveboard_maptext;
|
||||
|
||||
sector;
|
||||
wall;
|
||||
sprite;
|
||||
|
@ -78,6 +80,7 @@ gethitickms;
|
|||
OSD_Printf;
|
||||
|
||||
luaJIT_BC_defs_common;
|
||||
luaJIT_BC_engine_maptext;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
engine_main_arrays_are_static;
|
||||
engine_v8;
|
||||
|
||||
saveboard_maptext;
|
||||
|
||||
sector;
|
||||
wall;
|
||||
sprite;
|
||||
|
@ -78,6 +80,7 @@ gethitickms;
|
|||
OSD_Printf;
|
||||
|
||||
luaJIT_BC_defs_common;
|
||||
luaJIT_BC_engine_maptext;
|
||||
|
||||
|
||||
|
||||
|
|
246
polymer/eduke32/source/lunatic/engine_maptext.lua
Normal file
246
polymer/eduke32/source/lunatic/engine_maptext.lua
Normal file
|
@ -0,0 +1,246 @@
|
|||
-- MAPTEXT
|
||||
-- Lunatic: routines for reading and writing map-text.
|
||||
|
||||
local ffi = require("ffi")
|
||||
local ffiC = ffi.C
|
||||
|
||||
local print = print
|
||||
local tonumber = tonumber
|
||||
local type = type
|
||||
|
||||
local io = require("io")
|
||||
local string = require("string")
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
int32_t (*saveboard_maptext)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
|
||||
]]
|
||||
|
||||
|
||||
--== COMMON ==--
|
||||
|
||||
local sector_members = {
|
||||
-- Mandatory positional members first, [pos]=<name>.
|
||||
"wallnum",
|
||||
"ceilingz", "floorz",
|
||||
"ceilingpicnum", "floorpicnum",
|
||||
"ceilingshade", "floorshade";
|
||||
|
||||
-- If other positional members are to be added, they must be optional
|
||||
-- for backwards compatibility.
|
||||
|
||||
-- Optional key/value members next.
|
||||
B = { "ceilingbunch", -1 }, b = { "floorbunch", -1 }, -- default: -1
|
||||
F = "ceilingstat", f = "floorstat", -- default: 0
|
||||
H = "ceilingheinum", h = "floorheinum",
|
||||
P = "ceilingpal", p = "floorpal",
|
||||
X = "ceilingxpanning", x = "floorxpanning",
|
||||
Y = "ceilingypanning", y = "floorypanning",
|
||||
|
||||
v = "visibility",
|
||||
_ = "filler",
|
||||
o = "lotag", i = "hitag", e = { "extra", -1 }
|
||||
}
|
||||
|
||||
-- Defines the order in which the members are written out. A space denotes that
|
||||
-- a newline should appear in the output.
|
||||
local sector_ord = { mand="1 23 45 67 ", opt="Bb Ff Hh Pp Xx Yy v _ oie" }
|
||||
|
||||
|
||||
local wall_members = {
|
||||
-- mandatory
|
||||
"point2", -- special: 0 or 1 in map-text
|
||||
"x", "y",
|
||||
"nextwall",
|
||||
"picnum",
|
||||
"shade",
|
||||
"xrepeat", "yrepeat",
|
||||
"xpanning", "ypanning";
|
||||
|
||||
-- optional
|
||||
f = "cstat",
|
||||
m = "overpicnum",
|
||||
p = "pal",
|
||||
o = "lotag", i = "hitag", e = { "extra", -1 }
|
||||
}
|
||||
|
||||
local wall_ord = { mand="1 23 4 5 6 78 90 ", opt="f m p oie" }
|
||||
|
||||
|
||||
local sprite_members = {
|
||||
-- mandatory
|
||||
"x", "y", "z",
|
||||
"ang",
|
||||
"sectnum",
|
||||
"picnum",
|
||||
"cstat",
|
||||
"shade",
|
||||
"xrepeat", "yrepeat",
|
||||
|
||||
-- optional
|
||||
p = "pal",
|
||||
c = { "clipdist", 32 },
|
||||
_ = "filler",
|
||||
x = "xoffset", y = "yoffset",
|
||||
s = "statnum",
|
||||
w = { "owner", -1 },
|
||||
X = "xvel", Y = "yvel", Z = "zvel",
|
||||
o = "lotag", i = "hitag", e = { "extra", -1 }
|
||||
}
|
||||
|
||||
local sprite_ord = { mand="123 4 5 6 7 8 90 ", opt="p c _ xy s w XYZ oie" }
|
||||
|
||||
|
||||
--== SAVING ==--
|
||||
|
||||
local function write_struct(f, struct, members, ord)
|
||||
-- Write mandatory members first.
|
||||
local str = ord.mand:gsub(".",
|
||||
function(s)
|
||||
local num = (s=="0") and 10 or tonumber(s)
|
||||
return (s==" ") and "\n" or (struct[members[num]]..",")
|
||||
end)
|
||||
f:write("{"..str)
|
||||
|
||||
local havesth = false
|
||||
|
||||
-- Write optional members next.
|
||||
str = ord.opt:gsub(".",
|
||||
function(s)
|
||||
if (s==" ") then
|
||||
local ohavesth = havesth
|
||||
havesth = false
|
||||
return ohavesth and "\n" or ""
|
||||
end
|
||||
|
||||
local memb = members[s]
|
||||
local mname = (type(memb)=="table") and memb[1] or memb
|
||||
local mdefault = (type(memb)=="table") and memb[2] or 0
|
||||
|
||||
local val = struct[mname]
|
||||
|
||||
if (val~=mdefault) then
|
||||
havesth = true
|
||||
return s.."="..val..","
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end)
|
||||
|
||||
f:write(str.."},\n")
|
||||
end
|
||||
|
||||
-- In map-text, instead of saving wall[].point2, we store whether a particular
|
||||
-- wall is the last one in its loop instead.
|
||||
local function save_tweak_point2()
|
||||
local lastloopstart = 0
|
||||
|
||||
-- Check first.
|
||||
for i=0,ffiC.numwalls-1 do
|
||||
local p2 = ffiC.wall[i].point2
|
||||
|
||||
if (not (p2 == i+1 or (p2 ~= i and p2 == lastloopstart))) then
|
||||
-- If we hit this, the map is seriously corrupted!
|
||||
print(string.format("INTERNAL ERROR: wall[%d].point2=%d invalid", i, p2))
|
||||
return true
|
||||
end
|
||||
|
||||
if (p2 ~= i+1) then
|
||||
lastloopstart = i+1
|
||||
end
|
||||
end
|
||||
|
||||
-- Do it for real.
|
||||
lastloopstart = 0
|
||||
|
||||
for i=0,ffiC.numwalls-1 do
|
||||
local wal = ffiC.wall[i]
|
||||
|
||||
if (wal.point2 == i+1) then
|
||||
wal.point2 = 0
|
||||
else
|
||||
wal.point2 = 1 -- last point in loop
|
||||
lastloopstart = i+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function save_restore_point2()
|
||||
local lastloopstart = 0
|
||||
|
||||
for i=0,ffiC.numwalls-1 do
|
||||
local wal = ffiC.wall[i]
|
||||
local islast = (wal.point2~=0)
|
||||
|
||||
if (not islast) then
|
||||
wal.point2 = i+1
|
||||
else
|
||||
wal.point2 = lastloopstart
|
||||
lastloopstart = i+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function saveboard_maptext(filename, pos, ang, cursectnum)
|
||||
-- First, temporarily tweak wall[].point2.
|
||||
if (save_tweak_point2()) then
|
||||
return -1
|
||||
end
|
||||
|
||||
-- We open in binary mode so that newlines get written out as one byte even
|
||||
-- on Windows.
|
||||
local f, msg = io.open(ffi.string(filename), "wb")
|
||||
|
||||
if (f == nil) then
|
||||
print(string.format("Couldn't open \"%s\" for writing: %s\n", filename, msg))
|
||||
save_restore_point2()
|
||||
return -1
|
||||
end
|
||||
|
||||
-- Write header.
|
||||
f:write(string.format("--EDuke32 map\n"..
|
||||
"return {\n"..
|
||||
"version=10,\n\n"..
|
||||
|
||||
"pos={%d,%d,%d},\n"..
|
||||
"sectnum=%d,\n"..
|
||||
"ang=%d,\n\n",
|
||||
|
||||
pos.x, pos.y, pos.z,
|
||||
cursectnum,
|
||||
ang))
|
||||
|
||||
-- Sectors.
|
||||
f:write("sector={\n")
|
||||
for i=0,ffiC.numsectors-1 do
|
||||
write_struct(f, ffiC.sector[i], sector_members, sector_ord)
|
||||
end
|
||||
f:write("}\n\n")
|
||||
|
||||
-- Walls.
|
||||
f:write("wall={\n")
|
||||
for i=0,ffiC.numwalls-1 do
|
||||
write_struct(f, ffiC.wall[i], wall_members, wall_ord)
|
||||
end
|
||||
f:write("}\n\n")
|
||||
|
||||
-- Sprites.
|
||||
f:write("sprite={\n")
|
||||
for i=0,ffiC.MAXSPRITES-1 do
|
||||
if (ffiC.sprite[i].statnum ~= ffiC.MAXSTATUS) then
|
||||
write_struct(f, ffiC.sprite[i], sprite_members, sprite_ord)
|
||||
end
|
||||
end
|
||||
f:write("}\n\n")
|
||||
|
||||
f:write("}\n");
|
||||
|
||||
-- Done.
|
||||
f:close()
|
||||
save_restore_point2()
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-- Register our Lua functions as callbacks from C.
|
||||
ffiC.saveboard_maptext = saveboard_maptext
|
|
@ -14,7 +14,7 @@
|
|||
-- message is printed to stderr.
|
||||
-- Finally, if there is a .finish field in the module, it is run with no args.
|
||||
|
||||
-- forxcode example: print sprite numbers with lotag < -1 (interpreting lotag it as signed),
|
||||
-- forxcode example: print sprite numbers with lotag < -1 (lotag is signed for us),
|
||||
-- and for each matching sprite also print its lotag and picnum:
|
||||
-- $ ./findmaps.sh ~/.eduke32/ "sprite: .lotag < -1 :: io. write(', '.. .lotag .. ' ' .. .picnum)"
|
||||
|
||||
|
|
Loading…
Reference in a new issue