diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3603bb20d..f7755c148 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -85,6 +85,10 @@ tic_t jointimeout = (10*TICRATE); static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? +// Incremented by cv_joindelay when a client joins, decremented each tic. +// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. +static tic_t joindelay = 0; + UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. @@ -3077,6 +3081,8 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_joindelay = {"joindelay", "10", CV_SAVE, joindelay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -3164,6 +3170,8 @@ void SV_ResetServer(void) neededtic = maketic; tictoclear = maketic; + joindelay = 0; + for (i = 0; i < MAXNETNODES; i++) ResetNode(i); @@ -3613,6 +3621,9 @@ static void HandleConnect(SINT8 node) SV_SendRefuse(node, M_GetText("No players from\nthis node.")); else if (luafiletransfers) SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining.")); + else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE) + SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."), + (joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE)); else { #ifndef NONET @@ -3670,6 +3681,7 @@ static void HandleConnect(SINT8 node) DEBFILE("send savegame\n"); } SV_AddWaitingPlayers(names[0], names[1]); + joindelay += cv_joindelay.value * TICRATE; player_joining = true; } #else @@ -5038,12 +5050,21 @@ void NetUpdate(void) hu_resynching = true; } } + Net_AckTicker(); + // Handle timeouts to prevent definitive freezes from happenning if (server) + { for (i = 1; i < MAXNETNODES; i++) if (nodeingame[i] && freezetimeout[i] < I_GetTime()) Net_ConnectionTimeout(i); + + // In case the cvar value was lowered + if (joindelay) + joindelay = min(joindelay - 1, 3 * cv_joindelay.value * TICRATE); + } + nowtime /= NEWTICRATERATIO; if (nowtime > resptime) { @@ -5051,6 +5072,7 @@ void NetUpdate(void) M_Ticker(); CON_Ticker(); } + SV_FileSendTicker(); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 7e5061ff2..463240a2a 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -515,7 +515,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_rejointimeout; +extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout; extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 1fd53499a..dfc7351f5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -573,6 +573,7 @@ void D_RegisterServerCommands(void) // d_clisrv CV_RegisterVar(&cv_maxplayers); + CV_RegisterVar(&cv_joindelay); CV_RegisterVar(&cv_rejointimeout); CV_RegisterVar(&cv_resynchattempts); CV_RegisterVar(&cv_maxsend); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 818e760c9..703b924bb 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -412,9 +412,9 @@ static int libd_cachePatch(lua_State *L) HUDONLY luapat = patchinfohead; - lumpnum = W_CheckNumForName(luaL_checkstring(L, 1)); + lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1)); if (lumpnum == LUMPERROR) - lumpnum = W_GetNumForName("MISSING"); + lumpnum = W_GetNumForLongName("MISSING"); for (i = 0; i < numluapatches; i++) { @@ -454,7 +454,7 @@ static int libd_cachePatch(lua_State *L) numluapatches++; #else HUDONLY - LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); + LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); #endif return 1; } diff --git a/src/lua_script.c b/src/lua_script.c index 7adf62fcc..6b7b122f0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1010,16 +1010,8 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) if (!rover) WRITEUINT8(save_p, ARCH_NULL); else { - ffloor_t *r2; - UINT16 i = 0; - // search for id - for (r2 = rover->target->ffloors; r2; r2 = r2->next) - { - if (r2 == rover) - break; - i++; - } - if (!r2) + UINT16 i = P_GetFFloorID(rover); + if (i == UINT16_MAX) // invalid ID WRITEUINT8(save_p, ARCH_NULL); else { diff --git a/src/m_menu.c b/src/m_menu.c index 1069f0f30..c5f10b2bd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1583,7 +1583,7 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_HEADER, NULL, "General", NULL, 0}, #ifndef NONET {IT_STRING | IT_CVAR | IT_CV_STRING, - NULL, "Server name", &cv_servername, 7}, + NULL, "Server name", &cv_servername, 7}, {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21}, {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31}, @@ -1628,8 +1628,9 @@ static menuitem_t OP_ServerOptionsMenu[] = #ifndef NONET {IT_HEADER, NULL, "Advanced", NULL, 225}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231}, - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 245}, + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231}, + {IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 246}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 251}, #endif }; @@ -10822,7 +10823,8 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server - OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Attempts to resynchronise + OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Minimum delay between joins + OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Attempts to resynchronise } else { @@ -10834,6 +10836,7 @@ static void M_ServerOptions(INT32 choice) ? IT_GRAYEDOUT : (IT_STRING | IT_CVAR | IT_CV_STRING)); OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR; + OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR; } #endif diff --git a/src/p_saveg.c b/src/p_saveg.c index 2f84e97ef..6c8c7f765 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -760,26 +760,102 @@ static void P_NetUnArchiveColormaps(void) #define LD_S2BOTTEX 0x04 #define LD_S2MIDTEX 0x08 -static void P_NetArchiveWorld(void) +#define FD_FLAGS 0x01 +#define FD_ALPHA 0x02 + +// Check if any of the sector's FOFs differ from how they spawned +static boolean CheckFFloorDiff(const sector_t *ss) +{ + ffloor_t *rover; + + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (rover->flags != rover->spawnflags + || rover->alpha != rover->spawnalpha) + { + return true; // we found an FOF that changed! + // don't bother checking for more, we do that later + } + } + return false; +} + +// Special case: save the stats of all modified ffloors along with their ffloor "number"s +// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed +static void ArchiveFFloors(const sector_t *ss) +{ + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + UINT8 fflr_diff; + for (rover = ss->ffloors; rover; rover = rover->next) + { + fflr_diff = 0; // reset diff flags + if (rover->flags != rover->spawnflags) + fflr_diff |= FD_FLAGS; + if (rover->alpha != rover->spawnalpha) + fflr_diff |= FD_ALPHA; + + if (fflr_diff) + { + WRITEUINT16(save_p, j); // save ffloor "number" + WRITEUINT8(save_p, fflr_diff); + if (fflr_diff & FD_FLAGS) + WRITEUINT32(save_p, rover->flags); + if (fflr_diff & FD_ALPHA) + WRITEINT16(save_p, rover->alpha); + } + j++; + } + WRITEUINT16(save_p, 0xffff); +} + +static void UnArchiveFFloors(const sector_t *ss) +{ + UINT16 j = 0; // number of current ffloor in loop + UINT16 fflr_i; // saved ffloor "number" of next modified ffloor + UINT16 fflr_diff; // saved ffloor diff + ffloor_t *rover; + + rover = ss->ffloors; + if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... + I_Error("Sector does not have any ffloors!"); + + fflr_i = READUINT16(save_p); // get first modified ffloor's number ready + for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? + { + if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already + break; + // should NEVER need to be checked + //if (rover == NULL) + //break; + if (j != fflr_i) // this ffloor was not modified + { + j++; + rover = rover->next; + continue; + } + + fflr_diff = READUINT8(save_p); + + if (fflr_diff & FD_FLAGS) + rover->flags = READUINT32(save_p); + if (fflr_diff & FD_ALPHA) + rover->alpha = READINT16(save_p); + + fflr_i = READUINT16(save_p); // get next ffloor "number" ready + + j++; + rover = rover->next; + } +} + +static void ArchiveSectors(void) { size_t i; - INT32 statsec = 0, statline = 0; - const line_t *li = lines; - const line_t *spawnli = spawnlines; - const side_t *si; - const side_t *spawnsi; - UINT8 *put; - const sector_t *ss = sectors; const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; - // initialize colormap vars because paranoia - ClearNetColormaps(); - - WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); - put = save_p; - for (i = 0; i < numsectors; i++, ss++, spawnss++) { diff = diff2 = diff3 = 0; @@ -823,20 +899,8 @@ static void P_NetArchiveWorld(void) if (ss->crumblestate) diff3 |= SD_CRUMBLESTATE; - // Check if any of the sector's FOFs differ from how they spawned - if (ss->ffloors) - { - ffloor_t *rover; - for (rover = ss->ffloors; rover; rover = rover->next) - { - if (rover->flags != rover->spawnflags - || rover->alpha != rover->spawnalpha) - { - diff |= SD_FFLOORS; // we found an FOF that changed! - break; // don't bother checking for more, we do that later - } - } - } + if (ss->ffloors && CheckFFloorDiff(ss)) + diff |= SD_FFLOORS; if (diff3) diff2 |= SD_DIFF3; @@ -846,89 +910,142 @@ static void P_NetArchiveWorld(void) if (diff) { - statsec++; - - WRITEUINT16(put, i); - WRITEUINT8(put, diff); + WRITEUINT16(save_p, i); + WRITEUINT8(save_p, diff); if (diff & SD_DIFF2) - WRITEUINT8(put, diff2); + WRITEUINT8(save_p, diff2); if (diff2 & SD_DIFF3) - WRITEUINT8(put, diff3); + WRITEUINT8(save_p, diff3); if (diff & SD_FLOORHT) - WRITEFIXED(put, ss->floorheight); + WRITEFIXED(save_p, ss->floorheight); if (diff & SD_CEILHT) - WRITEFIXED(put, ss->ceilingheight); + WRITEFIXED(save_p, ss->ceilingheight); if (diff & SD_FLOORPIC) - WRITEMEM(put, levelflats[ss->floorpic].name, 8); + WRITEMEM(save_p, levelflats[ss->floorpic].name, 8); if (diff & SD_CEILPIC) - WRITEMEM(put, levelflats[ss->ceilingpic].name, 8); + WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8); if (diff & SD_LIGHT) - WRITEINT16(put, ss->lightlevel); + WRITEINT16(save_p, ss->lightlevel); if (diff & SD_SPECIAL) - WRITEINT16(put, ss->special); + WRITEINT16(save_p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(put, ss->floor_xoffs); + WRITEFIXED(save_p, ss->floor_xoffs); if (diff2 & SD_FYOFFS) - WRITEFIXED(put, ss->floor_yoffs); + WRITEFIXED(save_p, ss->floor_yoffs); if (diff2 & SD_CXOFFS) - WRITEFIXED(put, ss->ceiling_xoffs); + WRITEFIXED(save_p, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) - WRITEFIXED(put, ss->ceiling_yoffs); + WRITEFIXED(save_p, ss->ceiling_yoffs); if (diff2 & SD_FLOORANG) - WRITEANGLE(put, ss->floorpic_angle); + WRITEANGLE(save_p, ss->floorpic_angle); if (diff2 & SD_CEILANG) - WRITEANGLE(put, ss->ceilingpic_angle); + WRITEANGLE(save_p, ss->ceilingpic_angle); if (diff2 & SD_TAG) // save only the tag - WRITEINT16(put, ss->tag); + WRITEINT16(save_p, ss->tag); if (diff3 & SD_TAGLIST) // save both firsttag and nexttag { // either of these could be changed even if tag isn't - WRITEINT32(put, ss->firsttag); - WRITEINT32(put, ss->nexttag); + WRITEINT32(save_p, ss->firsttag); + WRITEINT32(save_p, ss->nexttag); } if (diff3 & SD_COLORMAP) - WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap)); + WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); // returns existing index if already added, or appends to net_colormaps and returns new index if (diff3 & SD_CRUMBLESTATE) - WRITEINT32(put, ss->crumblestate); - - // Special case: save the stats of all modified ffloors along with their ffloor "number"s - // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed + WRITEINT32(save_p, ss->crumblestate); if (diff & SD_FFLOORS) - { - size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - ffloor_t *rover; - UINT8 fflr_diff; - for (rover = ss->ffloors; rover; rover = rover->next) - { - fflr_diff = 0; // reset diff flags - if (rover->flags != rover->spawnflags) - fflr_diff |= 1; - if (rover->alpha != rover->spawnalpha) - fflr_diff |= 2; - - if (fflr_diff) - { - WRITEUINT16(put, j); // save ffloor "number" - WRITEUINT8(put, fflr_diff); - if (fflr_diff & 1) - WRITEUINT32(put, rover->flags); - if (fflr_diff & 2) - WRITEINT16(put, rover->alpha); - } - j++; - } - WRITEUINT16(put, 0xffff); - } + ArchiveFFloors(ss); } } - WRITEUINT16(put, 0xffff); + WRITEUINT16(save_p, 0xffff); +} + +static void UnArchiveSectors(void) +{ + UINT16 i; + UINT8 diff, diff2, diff3; + for (;;) + { + i = READUINT16(save_p); + + if (i == 0xffff) + break; + + if (i > numsectors) + I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); + + diff = READUINT8(save_p); + if (diff & SD_DIFF2) + diff2 = READUINT8(save_p); + else + diff2 = 0; + if (diff2 & SD_DIFF3) + diff3 = READUINT8(save_p); + else + diff3 = 0; + + if (diff & SD_FLOORHT) + sectors[i].floorheight = READFIXED(save_p); + if (diff & SD_CEILHT) + sectors[i].ceilingheight = READFIXED(save_p); + if (diff & SD_FLOORPIC) + { + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p); + save_p += 8; + } + if (diff & SD_CEILPIC) + { + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p); + save_p += 8; + } + if (diff & SD_LIGHT) + sectors[i].lightlevel = READINT16(save_p); + if (diff & SD_SPECIAL) + sectors[i].special = READINT16(save_p); + + if (diff2 & SD_FXOFFS) + sectors[i].floor_xoffs = READFIXED(save_p); + if (diff2 & SD_FYOFFS) + sectors[i].floor_yoffs = READFIXED(save_p); + if (diff2 & SD_CXOFFS) + sectors[i].ceiling_xoffs = READFIXED(save_p); + if (diff2 & SD_CYOFFS) + sectors[i].ceiling_yoffs = READFIXED(save_p); + if (diff2 & SD_FLOORANG) + sectors[i].floorpic_angle = READANGLE(save_p); + if (diff2 & SD_CEILANG) + sectors[i].ceilingpic_angle = READANGLE(save_p); + if (diff2 & SD_TAG) + sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag + if (diff3 & SD_TAGLIST) + { + sectors[i].firsttag = READINT32(save_p); + sectors[i].nexttag = READINT32(save_p); + } + + if (diff3 & SD_COLORMAP) + sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); + if (diff3 & SD_CRUMBLESTATE) + sectors[i].crumblestate = READINT32(save_p); + + if (diff & SD_FFLOORS) + UnArchiveFFloors(§ors[i]); + } +} + +static void ArchiveLines(void) +{ + size_t i; + const line_t *li = lines; + const line_t *spawnli = spawnlines; + const side_t *si; + const side_t *spawnsi; + UINT8 diff, diff2; // no diff3 - // do lines for (i = 0; i < numlines; i++, spawnli++, li++) { - diff = diff2 = diff3 = 0; + diff = diff2 = 0; if (li->special != spawnli->special) diff |= LD_SPECIAL; @@ -968,52 +1085,109 @@ static void P_NetArchiveWorld(void) if (diff) { - statline++; - WRITEINT16(put, i); - WRITEUINT8(put, diff); + WRITEINT16(save_p, i); + WRITEUINT8(save_p, diff); if (diff & LD_DIFF2) - WRITEUINT8(put, diff2); + WRITEUINT8(save_p, diff2); if (diff & LD_FLAG) - WRITEINT16(put, li->flags); + WRITEINT16(save_p, li->flags); if (diff & LD_SPECIAL) - WRITEINT16(put, li->special); + WRITEINT16(save_p, li->special); if (diff & LD_CLLCOUNT) - WRITEINT16(put, li->callcount); + WRITEINT16(save_p, li->callcount); si = &sides[li->sidenum[0]]; if (diff & LD_S1TEXOFF) - WRITEFIXED(put, si->textureoffset); + WRITEFIXED(save_p, si->textureoffset); if (diff & LD_S1TOPTEX) - WRITEINT32(put, si->toptexture); + WRITEINT32(save_p, si->toptexture); if (diff & LD_S1BOTTEX) - WRITEINT32(put, si->bottomtexture); + WRITEINT32(save_p, si->bottomtexture); if (diff & LD_S1MIDTEX) - WRITEINT32(put, si->midtexture); + WRITEINT32(save_p, si->midtexture); si = &sides[li->sidenum[1]]; if (diff2 & LD_S2TEXOFF) - WRITEFIXED(put, si->textureoffset); + WRITEFIXED(save_p, si->textureoffset); if (diff2 & LD_S2TOPTEX) - WRITEINT32(put, si->toptexture); + WRITEINT32(save_p, si->toptexture); if (diff2 & LD_S2BOTTEX) - WRITEINT32(put, si->bottomtexture); + WRITEINT32(save_p, si->bottomtexture); if (diff2 & LD_S2MIDTEX) - WRITEINT32(put, si->midtexture); + WRITEINT32(save_p, si->midtexture); } } - WRITEUINT16(put, 0xffff); - R_ClearTextureNumCache(false); + WRITEUINT16(save_p, 0xffff); +} - save_p = put; +static void UnArchiveLines(void) +{ + UINT16 i; + line_t *li; + side_t *si; + UINT8 diff, diff2; // no diff3 + + for (;;) + { + i = READUINT16(save_p); + + if (i == 0xffff) + break; + if (i > numlines) + I_Error("Invalid line number %u from server", i); + + diff = READUINT8(save_p); + li = &lines[i]; + + if (diff & LD_DIFF2) + diff2 = READUINT8(save_p); + else + diff2 = 0; + + if (diff & LD_FLAG) + li->flags = READINT16(save_p); + if (diff & LD_SPECIAL) + li->special = READINT16(save_p); + if (diff & LD_CLLCOUNT) + li->callcount = READINT16(save_p); + + si = &sides[li->sidenum[0]]; + if (diff & LD_S1TEXOFF) + si->textureoffset = READFIXED(save_p); + if (diff & LD_S1TOPTEX) + si->toptexture = READINT32(save_p); + if (diff & LD_S1BOTTEX) + si->bottomtexture = READINT32(save_p); + if (diff & LD_S1MIDTEX) + si->midtexture = READINT32(save_p); + + si = &sides[li->sidenum[1]]; + if (diff2 & LD_S2TEXOFF) + si->textureoffset = READFIXED(save_p); + if (diff2 & LD_S2TOPTEX) + si->toptexture = READINT32(save_p); + if (diff2 & LD_S2BOTTEX) + si->bottomtexture = READINT32(save_p); + if (diff2 & LD_S2MIDTEX) + si->midtexture = READINT32(save_p); + } +} + +static void P_NetArchiveWorld(void) +{ + // initialize colormap vars because paranoia + ClearNetColormaps(); + + WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); + + ArchiveSectors(); + ArchiveLines(); + R_ClearTextureNumCache(false); } static void P_NetUnArchiveWorld(void) { UINT16 i; - line_t *li; - side_t *si; - UINT8 *get; - UINT8 diff, diff2, diff3; if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); @@ -1029,161 +1203,8 @@ static void P_NetUnArchiveWorld(void) num_ffloors++; } - get = save_p; - - for (;;) - { - i = READUINT16(get); - - if (i == 0xffff) - break; - - if (i > numsectors) - I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - - diff = READUINT8(get); - if (diff & SD_DIFF2) - diff2 = READUINT8(get); - else - diff2 = 0; - if (diff2 & SD_DIFF3) - diff3 = READUINT8(get); - else - diff3 = 0; - - if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(get); - if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(get); - if (diff & SD_FLOORPIC) - { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get); - get += 8; - } - if (diff & SD_CEILPIC) - { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get); - get += 8; - } - if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(get); - if (diff & SD_SPECIAL) - sectors[i].special = READINT16(get); - - if (diff2 & SD_FXOFFS) - sectors[i].floor_xoffs = READFIXED(get); - if (diff2 & SD_FYOFFS) - sectors[i].floor_yoffs = READFIXED(get); - if (diff2 & SD_CXOFFS) - sectors[i].ceiling_xoffs = READFIXED(get); - if (diff2 & SD_CYOFFS) - sectors[i].ceiling_yoffs = READFIXED(get); - if (diff2 & SD_FLOORANG) - sectors[i].floorpic_angle = READANGLE(get); - if (diff2 & SD_CEILANG) - sectors[i].ceilingpic_angle = READANGLE(get); - if (diff2 & SD_TAG) - sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag - if (diff3 & SD_TAGLIST) - { - sectors[i].firsttag = READINT32(get); - sectors[i].nexttag = READINT32(get); - } - - if (diff3 & SD_COLORMAP) - sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get)); - if (diff3 & SD_CRUMBLESTATE) - sectors[i].crumblestate = READINT32(get); - - if (diff & SD_FFLOORS) - { - UINT16 j = 0; // number of current ffloor in loop - UINT16 fflr_i; // saved ffloor "number" of next modified ffloor - UINT16 fflr_diff; // saved ffloor diff - ffloor_t *rover; - - rover = sectors[i].ffloors; - if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... - I_Error("Sector does not have any ffloors!"); - - fflr_i = READUINT16(get); // get first modified ffloor's number ready - for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? - { - if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already - break; - // should NEVER need to be checked - //if (rover == NULL) - //break; - if (j != fflr_i) // this ffloor was not modified - { - j++; - rover = rover->next; - continue; - } - - fflr_diff = READUINT8(get); - - if (fflr_diff & 1) - rover->flags = READUINT32(get); - if (fflr_diff & 2) - rover->alpha = READINT16(get); - - fflr_i = READUINT16(get); // get next ffloor "number" ready - - j++; - rover = rover->next; - } - } - } - - for (;;) - { - i = READUINT16(get); - - if (i == 0xffff) - break; - if (i > numlines) - I_Error("Invalid line number %u from server", i); - - diff = READUINT8(get); - li = &lines[i]; - - if (diff & LD_DIFF2) - diff2 = READUINT8(get); - else - diff2 = 0; - - diff3 = 0; - - if (diff & LD_FLAG) - li->flags = READINT16(get); - if (diff & LD_SPECIAL) - li->special = READINT16(get); - if (diff & LD_CLLCOUNT) - li->callcount = READINT16(get); - - si = &sides[li->sidenum[0]]; - if (diff & LD_S1TEXOFF) - si->textureoffset = READFIXED(get); - if (diff & LD_S1TOPTEX) - si->toptexture = READINT32(get); - if (diff & LD_S1BOTTEX) - si->bottomtexture = READINT32(get); - if (diff & LD_S1MIDTEX) - si->midtexture = READINT32(get); - - si = &sides[li->sidenum[1]]; - if (diff2 & LD_S2TEXOFF) - si->textureoffset = READFIXED(get); - if (diff2 & LD_S2TOPTEX) - si->toptexture = READINT32(get); - if (diff2 & LD_S2BOTTEX) - si->bottomtexture = READINT32(get); - if (diff2 & LD_S2MIDTEX) - si->midtexture = READINT32(get); - } - - save_p = get; + UnArchiveSectors(); + UnArchiveLines(); } // @@ -1474,42 +1495,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff2 & MD2_FLOORROVER) { - ffloor_t *rover; - size_t i = 0; - UINT32 roverindex = 0; - - for (rover = mobj->floorrover->target->ffloors; rover; rover = rover->next) - { - if (rover == mobj->floorrover) - { - roverindex = i; - break; - } - i++; - } - - WRITEUINT32(save_p, (UINT32)(mobj->floorrover->target - sectors)); - WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref + WRITEUINT32(save_p, SaveSector(mobj->floorrover->target)); + WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover)); } if (diff2 & MD2_CEILINGROVER) { - ffloor_t *rover; - size_t i = 0; - UINT32 roverindex = 0; - - for (rover = mobj->ceilingrover->target->ffloors; rover; rover = rover->next) - { - if (rover == mobj->ceilingrover) - { - roverindex = i; - break; - } - i++; - } - - WRITEUINT32(save_p, (UINT32)(mobj->ceilingrover->target - sectors)); - WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref + WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target)); + WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); } if (diff & MD_SPAWNPOINT) @@ -2431,34 +2424,16 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_FLOORROVER) { - size_t floor_sectornum = (size_t)READUINT32(save_p); - size_t floor_rovernum = (size_t)READUINT32(save_p); - ffloor_t *rover = NULL; - size_t rovernum = 0; - - for (rover = sectors[floor_sectornum].ffloors; rover; rover = rover->next) - { - if (rovernum == floor_rovernum) - break; - rovernum++; - } - floorrover = rover; + sector_t *sec = LoadSector(READUINT32(save_p)); + UINT16 id = READUINT16(save_p); + floorrover = P_GetFFloorByID(sec, id); } if (diff2 & MD2_CEILINGROVER) { - size_t ceiling_sectornum = (size_t)READUINT32(save_p); - size_t ceiling_rovernum = (size_t)READUINT32(save_p); - ffloor_t *rover = NULL; - size_t rovernum = 0; - - for (rover = sectors[ceiling_sectornum].ffloors; rover; rover = rover->next) - { - if (rovernum == ceiling_rovernum) - break; - rovernum++; - } - ceilingrover = rover; + sector_t *sec = LoadSector(READUINT32(save_p)); + UINT16 id = READUINT16(save_p); + ceilingrover = P_GetFFloorByID(sec, id); } if (diff & MD_SPAWNPOINT) @@ -2702,6 +2677,10 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) ht->floorwasheight = READFIXED(save_p); ht->ceilingwasheight = READFIXED(save_p); ht->low = READCHAR(save_p); + + if (ht->sector) + ht->sector->ceilingdata = ht; + return &ht->thinker; } @@ -2715,6 +2694,13 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) ht->floorstartheight = READFIXED(save_p); ht->ceilingstartheight = READFIXED(save_p); ht->destheight = READFIXED(save_p); + + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } @@ -2728,6 +2714,13 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) ht->floorstartheight = READFIXED(save_p); ht->ceilingstartheight = READFIXED(save_p); ht->tag = READINT16(save_p); + + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } @@ -2754,6 +2747,13 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker) ht->delay = READINT32(save_p); ht->tag = READINT16(save_p); ht->sound = READUINT16(save_p); + + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } diff --git a/src/p_spec.c b/src/p_spec.c index 57795f2bf..bfda37381 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5678,6 +5678,35 @@ void P_UpdateSpecials(void) } } +// +// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them +// + +/** Gets the ID number for a 3Dfloor in its target sector. + * + * \param fflr The 3Dfloor we want an ID for. + * \return ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. UINT16_MAX is given if invalid. + * \sa P_GetFFloorByID + */ +UINT16 P_GetFFloorID(ffloor_t *fflr) +{ + ffloor_t *rover; + sector_t *sec; + UINT16 i = 0; + + if (!fflr) + return UINT16_MAX; + + sec = fflr->target; + + if (!sec->ffloors) + return UINT16_MAX; + for (rover = sec->ffloors; rover; rover = rover->next, i++) + if (rover == fflr) + return i; + return UINT16_MAX; +} + /** Gets a 3Dfloor by control sector. * * \param sec Target sector. @@ -5702,7 +5731,7 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) * \param sec Target sector. * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. * \return Pointer to found 3Dfloor, or NULL. - * \sa P_GetFFloorBySec + * \sa P_GetFFloorBySec, P_GetFFloorID */ ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) { @@ -6013,7 +6042,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) * \sa P_SpawnSpecials, T_RaiseSector * \author SSNTails */ -static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, boolean spindash) +static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash) { raise_t *raise; @@ -6025,10 +6054,10 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, raise->sourceline = sourceline; raise->sector = sec; - raise->ceilingtop = P_FindHighestCeilingSurrounding(sec); - raise->ceilingbottom = P_FindLowestCeilingSurrounding(sec); + raise->ceilingtop = ceilingtop; + raise->ceilingbottom = ceilingbottom; - raise->basespeed = FixedDiv(P_AproxDistance(sourceline->dx, sourceline->dy), 4*FRACUNIT); + raise->basespeed = speed; if (lower) raise->flags |= RF_REVERSE; @@ -6938,44 +6967,32 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 190: // Rising Platform FOF (solid, opaque, shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); - break; - case 191: // Rising Platform FOF (solid, opaque, no shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); - break; - case 192: // Rising Platform TL block: FOF (solid, translucent) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); - break; - case 193: // Rising Platform FOF (solid, invisible) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); - break; - case 194: // Rising Platform 'Platform' - You can jump up through it - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); - break; - case 195: // Rising Platform Translucent "platform" - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; + { + fixed_t speed = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT); + fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector); + fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector); + ffloorflags = FF_EXISTS|FF_SOLID; + if (lines[i].special != 193) + ffloorflags |= FF_RENDERALL; + if (lines[i].special <= 191) + ffloorflags |= FF_CUTLEVEL; + if (lines[i].special == 192 || lines[i].special == 195) + ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + if (lines[i].special >= 194) + ffloorflags |= FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; + if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) + ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); + + P_AddRaiseThinker(lines[i].frontsector, &lines[i], speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB)); break; + } case 200: // Double light effect P_AddFakeFloorsByLine(i, FF_EXISTS|FF_CUTSPRITES|FF_DOUBLESHADOW, secthinkers); diff --git a/src/p_spec.h b/src/p_spec.h index f7785125a..74b7ea4f2 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -74,6 +74,7 @@ void P_RunDeNightserizeExecutors(mobj_t *actor); void P_RunNightsLapExecutors(mobj_t *actor); void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres); +UINT16 P_GetFFloorID(ffloor_t *fflr); ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); // diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index c042d141c..ec7bfc1c4 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -372,7 +372,9 @@ static boolean IgnoreMouse(void) return false; if (menuactive) return !M_MouseNeeded(); - if (paused || con_destlines || chat_on || gamestate != GS_LEVEL) + if (paused || con_destlines || chat_on) + return true; + if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION && gamestate != GS_CUTSCENE) return true; return false; } diff --git a/src/w_wad.c b/src/w_wad.c index f273753c8..a81132354 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -920,6 +920,40 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum) // 'startlump' is the lump number to start the search // UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) +{ + UINT16 i; + static char uname[8 + 1]; + + if (!TestValidLump(wad,0)) + return INT16_MAX; + + strlcpy(uname, name, sizeof uname); + strupr(uname); + + // + // scan forward + // start at 'startlump', useful parameter when there are multiple + // resources with the same name + // + if (startlump < wadfiles[wad]->numlumps) + { + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + if (!strncmp(lump_p->name, uname, sizeof(uname) - 1)) + return i; + } + + // not found. + return INT16_MAX; +} + +// +// Like W_CheckNumForNamePwad, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) { UINT16 i; static char uname[256 + 1]; @@ -1025,7 +1059,8 @@ lumpnum_t W_CheckNumForName(const char *name) // most recent entries first for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) { - if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] + && strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) { lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); return lumpnumcache[lumpnumcacheindex].lumpnum; @@ -1045,13 +1080,63 @@ lumpnum_t W_CheckNumForName(const char *name) { // Update the cache. lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); - strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); + strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check; return lumpnumcache[lumpnumcacheindex].lumpnum; } } +// +// Like W_CheckNumForName, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +lumpnum_t W_CheckNumForLongName(const char *name) +{ + INT32 i; + lumpnum_t check = INT16_MAX; + + if (!*name) // some doofus gave us an empty string? + return LUMPERROR; + + // Check the lumpnumcache first. Loop backwards so that we check + // most recent entries first + for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + + // scan wad files backwards so patch lump files take precedence + for (i = numwadfiles - 1; i >= 0; i--) + { + check = W_CheckNumForLongNamePwad(name,(UINT16)i,0); + if (check != INT16_MAX) + break; //found it + } + + if (check == INT16_MAX) return LUMPERROR; + else + { + if (strlen(name) < 32) + { + // Update the cache. + lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); + strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32); + lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check; + } + + return (i << 16) + check; + } +} + // Look for valid map data through all added files in descendant order. // Get a map marker for WADs, and a standalone WAD file lump inside PK3s. // TODO: Make it search through cache first, maybe...? @@ -1100,6 +1185,24 @@ lumpnum_t W_GetNumForName(const char *name) return i; } +// +// Like W_GetNumForName, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +lumpnum_t W_GetNumForLongName(const char *name) +{ + lumpnum_t i; + + i = W_CheckNumForLongName(name); + + if (i == LUMPERROR) + I_Error("W_GetNumForLongName: %s not found!\n", name); + + return i; +} + // // W_CheckNumForNameInBlock // Checks only in blocks from blockstart lump to blockend lump @@ -1139,7 +1242,7 @@ UINT8 W_LumpExists(const char *name) { lumpinfo_t *lump_p = wadfiles[i]->lumpinfo; for (j = 0; j < wadfiles[i]->numlumps; ++j, ++lump_p) - if (fastcmp(lump_p->name,name)) + if (fastcmp(lump_p->longname, name)) return true; } return false; @@ -1680,6 +1783,17 @@ void *W_CachePatchName(const char *name, INT32 tag) return W_CachePatchNum(W_GetNumForName("MISSING"), tag); return W_CachePatchNum(num, tag); } + +void *W_CachePatchLongName(const char *name, INT32 tag) +{ + lumpnum_t num; + + num = W_CheckNumForLongName(name); + + if (num == LUMPERROR) + return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag); + return W_CachePatchNum(num, tag); +} #ifndef NOMD5 #define MD5_LEN 16 diff --git a/src/w_wad.h b/src/w_wad.h index 3af6148f4..88b542fca 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -156,6 +156,7 @@ const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump); const char *W_CheckNameForNum(lumpnum_t lumpnum); UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad +UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump); /* Find the first lump after F_START for instance. */ UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlump); @@ -166,7 +167,9 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForName(const char *name); +lumpnum_t W_CheckNumForLongName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR +lumpnum_t W_GetNumForLongName(const char *name); lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); UINT8 W_LumpExists(const char *name); // Lua uses this. @@ -194,6 +197,7 @@ boolean W_IsPatchCached(lumpnum_t lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); +void *W_CachePatchLongName(const char *name, INT32 tag); // Returns either a Software patch, or an OpenGL patch. // Performs any necessary conversions from PNG images.