/** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ UINT8 *PutFileNeeded(void) { size_t i, count = 0; UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; for (i = 0; i < numwadfiles; i++) { // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) continue; filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) filestatus += (1 << 4); // Will send if requested // else // filestatus += (0 << 4); -- Won't send, too big WRITEUINT8(p, filestatus); count++; WRITEUINT32(p, wadfiles[i]->filesize); nameonly(strcpy(wadfilename, wadfiles[i]->filename)); WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITEMEM(p, wadfiles[i]->md5sum, 16); } netbuffer->u.serverinfo.fileneedednum = (UINT8)count; return p; }
void LUA_Archive(void) { INT32 i; thinker_t *th; if (gL) lua_newtable(gL); // tables to be archived. for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) continue; // all players in game will be archived, even if they just add a 0. ArchiveExtVars(&players[i], "player"); } for (th = thinkercap.next; th != &thinkercap; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) { // archive function will determine when to skip mobjs, // and write mobjnum in otherwise. ArchiveExtVars(th, "mobj"); } WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode ArchiveTables(); if (gL) lua_pop(gL, 1); // pop tables }
static void ArchiveExtVars(void *pointer, const char *ptype) { int TABLESINDEX; UINT16 i; if (!gL) { if (fastcmp(ptype,"player")) // players must always be included, even if no vars WRITEUINT16(save_p, 0); return; } TABLESINDEX = lua_gettop(gL); lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(gL, -1)); lua_pushlightuserdata(gL, pointer); lua_rawget(gL, -2); lua_remove(gL, -2); // pop LREG_EXTVARS if (!lua_istable(gL, -1)) { // no extra values table lua_pop(gL, 1); if (fastcmp(ptype,"player")) // players must always be included, even if no vars WRITEUINT16(save_p, 0); return; } lua_pushnil(gL); for (i = 0; lua_next(gL, -2); i++) lua_pop(gL, 1); if (i == 0 && !fastcmp(ptype,"player")) // skip anything that has an empty table and isn't a player. return; if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum); WRITEUINT16(save_p, i); lua_pushnil(gL); while (lua_next(gL, -2)) { I_Assert(lua_type(gL, -2) == LUA_TSTRING); WRITESTRING(save_p, lua_tostring(gL, -2)); if (ArchiveValue(TABLESINDEX, -1) == 2) CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1)); lua_pop(gL, 1); } lua_pop(gL, 1); }
/** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. * */ UINT8 *PutFileNeeded(void) { size_t i, count = 0; UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; size_t bytesused = 0; for (i = 0; i < numwadfiles; i++) { // If it has only music/sound lumps, mark it as unimportant if (W_VerifyNMUSlumps(wadfiles[i]->filename)) filestatus = 0; else filestatus = 1; // Important // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)) filestatus += (0 << 4); // Won't send else filestatus += (1 << 4); // Will send if requested bytesused += (nameonlylength(wadfilename) + 22); // Don't write too far... if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded)) I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename); WRITEUINT8(p, filestatus); count++; WRITEUINT32(p, wadfiles[i]->filesize); nameonly(strcpy(wadfilename, wadfiles[i]->filename)); WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITEMEM(p, wadfiles[i]->md5sum, 16); } netbuffer->u.serverinfo.fileneedednum = (UINT8)count; return p; }
static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { if (myindex < 0) myindex = lua_gettop(gL)+1+myindex; switch (lua_type(gL, myindex)) { case LUA_TNONE: case LUA_TNIL: WRITEUINT8(save_p, ARCH_NULL); break; // This might be a problem. D: case LUA_TLIGHTUSERDATA: case LUA_TTHREAD: case LUA_TFUNCTION: WRITEUINT8(save_p, ARCH_NULL); return 2; case LUA_TBOOLEAN: WRITEUINT8(save_p, ARCH_BOOLEAN); WRITEUINT8(save_p, lua_toboolean(gL, myindex)); break; case LUA_TNUMBER: { lua_Integer number = lua_tointeger(gL, myindex); if (number < 0) { WRITEUINT8(save_p, ARCH_SIGNED); WRITEFIXED(save_p, number); } else { WRITEUINT8(save_p, ARCH_UNSIGNED); WRITEANGLE(save_p, number); } break; } case LUA_TSTRING: WRITEUINT8(save_p, ARCH_STRING); WRITESTRING(save_p, lua_tostring(gL, myindex)); break; case LUA_TTABLE: { boolean found = false; INT32 i; UINT16 t = (UINT16)lua_objlen(gL, TABLESINDEX); for (i = 1; i <= t && !found; i++) { lua_rawgeti(gL, TABLESINDEX, i); if (lua_rawequal(gL, myindex, -1)) { t = i; found = true; } lua_pop(gL, 1); } if (!found) t++; WRITEUINT8(save_p, ARCH_TABLE); WRITEUINT16(save_p, t); if (!found) { lua_pushvalue(gL, myindex); lua_rawseti(gL, TABLESINDEX, t); return 1; } break; } case LUA_TUSERDATA: switch (GetUserdataArchType()) { case ARCH_MOBJINFO: { mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_MOBJINFO); WRITEUINT8(save_p, info - mobjinfo); break; } case ARCH_STATE: { state_t *state = *((state_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_STATE); WRITEUINT8(save_p, state - states); break; } case ARCH_MOBJ: { mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); if (!mobj) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_MOBJ); WRITEUINT32(save_p, mobj->mobjnum); } break; } case ARCH_PLAYER: { player_t *player = *((player_t **)lua_touserdata(gL, myindex)); if (!player) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_PLAYER); WRITEUINT8(save_p, player - players); } break; } case ARCH_MAPTHING: { mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); if (!mapthing) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_MAPTHING); WRITEUINT16(save_p, mapthing - mapthings); } break; } case ARCH_VERTEX: { vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); if (!vertex) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_VERTEX); WRITEUINT16(save_p, vertex - vertexes); } break; } case ARCH_LINE: { line_t *line = *((line_t **)lua_touserdata(gL, myindex)); if (!line) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_LINE); WRITEUINT16(save_p, line - lines); } break; } case ARCH_SIDE: { side_t *side = *((side_t **)lua_touserdata(gL, myindex)); if (!side) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_SIDE); WRITEUINT16(save_p, side - sides); } break; } case ARCH_SUBSECTOR: { subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); if (!subsector) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_SUBSECTOR); WRITEUINT16(save_p, subsector - subsectors); } break; } case ARCH_SECTOR: { sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); if (!sector) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_SECTOR); WRITEUINT16(save_p, sector - sectors); } break; } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); if (!header) WRITEUINT8(save_p, ARCH_NULL); else { WRITEUINT8(save_p, ARCH_MAPHEADER); WRITEUINT16(save_p, header - *mapheaderinfo); } break; } default: WRITEUINT8(save_p, ARCH_NULL); return 2; } break; } return 0; }