diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 8c4739b02..f5930cdbe 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -176,6 +176,7 @@ static const struct { {META_SECTORLINES, "sector_t.lines"}, {META_SIDENUM, "line_t.sidenum"}, {META_LINEARGS, "line_t.args"}, + {META_LINESTRINGARGS, "line_t.stringargs"}, #ifdef HAVE_LUA_SEGS {META_NODEBBOX, "node_t.bbox"}, {META_NODECHILDREN, "node_t.children"}, diff --git a/src/lua_libs.h b/src/lua_libs.h index 155c34eaa..1110e93c2 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -57,6 +57,7 @@ extern lua_State *gL; #define META_SECTORLINES "SECTOR_T*LINES" #define META_SIDENUM "LINE_T*SIDENUM" #define META_LINEARGS "LINE_T*ARGS" +#define META_LINESTRINGARGS "LINE_T*STRINGARGS" #ifdef HAVE_LUA_SEGS #define META_NODEBBOX "NODE_T*BBOX" #define META_NODECHILDREN "NODE_T*CHILDREN" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 03da0a2e0..4cb316313 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -95,6 +95,7 @@ enum line_e { line_special, line_tag, line_args, + line_stringargs, line_sidenum, line_frontside, line_backside, @@ -117,6 +118,7 @@ static const char *const line_opt[] = { "special", "tag", "args", + "stringargs", "sidenum", "frontside", "backside", @@ -721,6 +723,24 @@ static int lineargs_len(lua_State* L) return 1; } +// stringargs, i -> stringargs[i] +static int linestringargs_get(lua_State *L) +{ + char **stringargs = *((char***)luaL_checkudata(L, 1, META_LINESTRINGARGS)); + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMLINESTRINGARGS) + return luaL_error(L, LUA_QL("line_t.stringargs") " index cannot be %d", i); + lua_pushstring(L, stringargs[i]); + return 1; +} + +// #stringargs -> NUMLINESTRINGARGS +static int linestringargs_len(lua_State *L) +{ + lua_pushinteger(L, NUMLINESTRINGARGS); + return 1; +} + static int line_get(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); @@ -764,6 +784,9 @@ static int line_get(lua_State *L) case line_args: LUA_PushUserdata(L, line->args, META_LINEARGS); return 1; + case line_stringargs: + LUA_PushUserdata(L, line->stringargs, META_LINESTRINGARGS); + return 1; case line_sidenum: LUA_PushUserdata(L, line->sidenum, META_SIDENUM); return 1; @@ -2168,6 +2191,14 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_LINESTRINGARGS); + lua_pushcfunction(L, linestringargs_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, linestringargs_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_SIDENUM); lua_pushcfunction(L, sidenum_get); lua_setfield(L, -2, "__index"); diff --git a/src/p_saveg.c b/src/p_saveg.c index 1e6451164..0cf5ed2e8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -764,17 +764,28 @@ static void P_NetUnArchiveColormaps(void) #define LD_DIFF2 0x80 // diff2 flags -#define LD_S2TEXOFF 0x01 -#define LD_S2TOPTEX 0x02 -#define LD_S2BOTTEX 0x04 -#define LD_S2MIDTEX 0x08 -#define LD_ARGS 0x10 +#define LD_S2TEXOFF 0x01 +#define LD_S2TOPTEX 0x02 +#define LD_S2BOTTEX 0x04 +#define LD_S2MIDTEX 0x08 +#define LD_ARGS 0x10 +#define LD_STRINGARGS 0x20 -static boolean P_AreArgsEqual(const INT32 args[NUMLINEARGS], const INT32 spawnargs[NUMLINEARGS]) +static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) { UINT8 i; for (i = 0; i < NUMLINEARGS; i++) - if (args[i] != spawnargs[i]) + if (li->args[i] != spawnli->args[i]) + return false; + + return true; +} + +static boolean P_AreStringArgsEqual(const line_t *li, const line_t *spawnli) +{ + UINT8 i; + for (i = 0; i < NUMLINESTRINGARGS; i++) + if (strcmp(li->stringargs[i], spawnli->stringargs[i])) return false; return true; @@ -955,9 +966,12 @@ static void P_NetArchiveWorld(void) if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved diff |= LD_CLLCOUNT; - if (!P_AreArgsEqual(li->args, spawnli->args)) + if (!P_AreArgsEqual(li, spawnli)) diff2 |= LD_ARGS; + if (!P_AreStringArgsEqual(li, spawnli)) + diff2 |= LD_STRINGARGS; + if (li->sidenum[0] != 0xffff) { si = &sides[li->sidenum[0]]; @@ -1028,6 +1042,25 @@ static void P_NetArchiveWorld(void) for (j = 0; j < NUMLINEARGS; j++) WRITEINT32(put, li->args[j]); } + if (diff2 & LD_STRINGARGS) + { + UINT8 j; + for (j = 0; j < NUMLINESTRINGARGS; j++) + { + size_t len, k; + + if (!li->stringargs[j]) + { + WRITEINT32(put, 0); + continue; + } + + len = strlen(li->stringargs[j]); + WRITEINT32(put, len); + for (k = 0; k < len; k++) + WRITECHAR(put, li->stringargs[j][k]); + } + } } } WRITEUINT16(put, 0xffff); @@ -1217,7 +1250,27 @@ static void P_NetUnArchiveWorld(void) for (j = 0; j < NUMLINEARGS; j++) li->args[j] = READINT32(get); } + if (diff2 & LD_STRINGARGS) + { + UINT8 j; + for (j = 0; j < NUMLINESTRINGARGS; j++) + { + size_t len = READINT32(get); + size_t k; + if (!len) + { + Z_Free(li->stringargs[j]); + li->stringargs[j] = NULL; + continue; + } + + li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); + for (k = 0; k < len; k++) + li->stringargs[j][k] = READCHAR(get); + li->stringargs[j][len] = '\0'; + } + } } save_p = get; diff --git a/src/p_setup.c b/src/p_setup.c index 892323382..67cd11740 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1053,6 +1053,7 @@ static void P_LoadLinedefs(UINT8 *data) ld->special = SHORT(mld->special); ld->tag = SHORT(mld->tag); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); + memset(ld->stringargs, (int)NULL, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); P_SetLinedefV1(i, SHORT(mld->v1)); P_SetLinedefV2(i, SHORT(mld->v2)); @@ -1430,10 +1431,21 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) P_SetLinedefV2(i, atol(val)); else if (fastncmp(param, "arg", 3) && strlen(param) > 3) { - size_t argnum = atol(param + 3); - if (argnum >= NUMLINEARGS) - return; - lines[i].args[argnum] = atol(val); + if (fastcmp(param + 4, "str")) + { + size_t argnum = param[3] - '0'; + if (argnum >= NUMLINESTRINGARGS) + return; + lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[argnum], val, strlen(val) + 1); + } + else + { + size_t argnum = atol(param + 3); + if (argnum >= NUMLINEARGS) + return; + lines[i].args[argnum] = atol(val); + } } else if (fastcmp(param, "sidefront")) lines[i].sidenum[0] = atol(val); @@ -1623,6 +1635,7 @@ static void P_LoadTextmap(void) ld->special = 0; ld->tag = 0; memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); + memset(ld->stringargs, (int)NULL, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); ld->sidenum[0] = 0xffff; ld->sidenum[1] = 0xffff; diff --git a/src/r_defs.h b/src/r_defs.h index 2fc862de8..88d045d09 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -402,6 +402,7 @@ typedef enum #define HORIZONSPECIAL 41 #define NUMLINEARGS 6 +#define NUMLINESTRINGARGS 2 typedef struct line_s { @@ -416,6 +417,7 @@ typedef struct line_s INT16 special; INT16 tag; INT32 args[NUMLINEARGS]; + char *stringargs[NUMLINESTRINGARGS]; // Visual appearance: sidedefs. UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided