diff --git a/CMakeLists.txt b/CMakeLists.txt index 23b768a70..f9364fdd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0) project(SRB2 - VERSION 2.1.18 + VERSION 2.1.19 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/appveyor.yml b/appveyor.yml index c1f6894ef..cc073ff01 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.18.{branch}-{build} +version: 2.1.19.{branch}-{build} os: MinGW environment: diff --git a/src/Makefile b/src/Makefile index 76f013c52..426dc2289 100644 --- a/src/Makefile +++ b/src/Makefile @@ -511,13 +511,11 @@ OBJS:=$(i_main_o) \ # For reference, this is the command I use to build a srb2.pot file from the source code. # (The listed source files are the ones containing translated strings). # FILES=""; for file in `find ./ | grep "\.c" | grep -v svn`; do [ "`grep "M_GetText(" $file`" ] && FILES="$FILES $file"; done; xgettext -d srb2 -o locale/srb2.pot -kM_GetText -F --no-wrap $FILES -ifndef NOGETTEXT ifdef GETTEXT POS:=$(BIN)/en.mo OPTS+=-DGETTEXT endif -endif ifdef DJGPPDOS all: pre-build $(BIN)/$(EXENAME) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 80d018c4b..5bf7f247d 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -283,9 +283,6 @@ else ifdef LINUX NASMFORMAT=elf -DLINUX SDL=1 -ifndef NOGETTEXT - GETTEXT=1 -endif ifdef LINUX64 OBJDIR:=$(OBJDIR)/Linux64 BIN:=$(BIN)/Linux64 @@ -321,9 +318,6 @@ else ifdef MINGW64 INTERFACE=win32 #NASMFORMAT=win64 -ifndef NOGETTEXT - #GETTEXT=1 -endif OBJDIR:=$(OBJDIR)/Mingw64 BIN:=$(BIN)/Mingw64 else @@ -354,9 +348,6 @@ else ifdef MINGW INTERFACE=win32 NASMFORMAT=win32 -ifndef NOGETTEXT - GETTEXT=1 -endif OBJDIR:=$(OBJDIR)/Mingw BIN:=$(BIN)/Mingw else diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 929b821eb..19b58b0d3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1740,9 +1740,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) { #ifndef NONET INT32 i; -#endif -#ifndef NONET // serverlist is updated by GetPacket function if (serverlistcount > 0) { @@ -1776,7 +1774,20 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) serverlist[i].info.fileneeded); CONS_Printf(M_GetText("Checking files...\n")); i = CL_CheckFiles(); - if (i == 2) // cannot join for some reason + if (i == 3) // too many files + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have too many WAD files loaded\n" + "to add ones the server is using.\n" + "Please restart SRB2 before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 2) // cannot join for some reason { D_QuitNetGame(); CL_Reset(); @@ -3404,17 +3415,42 @@ static void HandlePacketFromAwayNode(SINT8 node) if (node != servernode) DEBFILE(va("Received packet from unknown host %d\n", node)); +// macro for packets that should only be sent by the server +// if it is NOT from the server, bail out and close the connection! +#define SERVERONLY \ + if (node != servernode) \ + { \ + Net_CloseConnection(node); \ + break; \ + } switch (netbuffer->packettype) { case PT_ASKINFOVIAMS: +#if 0 if (server && serverrunning) { - INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr); - SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); - SV_SendPlayerInfo(clientnode); // Send extra info - Net_CloseConnection(clientnode); - // Don't close connection to MS. + INT32 clientnode; + if (ms_RoomId < 0) // ignore if we're not actually on the MS right now + { + Net_CloseConnection(node); // and yes, close connection + return; + } + clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr); + if (clientnode != -1) + { + SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); + SV_SendPlayerInfo(clientnode); // Send extra info + Net_CloseConnection(clientnode); + // Don't close connection to MS... + } + else + Net_CloseConnection(node); // ...unless the IP address is not valid } + else + Net_CloseConnection(node); // you're not supposed to get it, so ignore it +#else + Net_CloseConnection(node); +#endif break; case PT_ASKINFO: @@ -3422,8 +3458,8 @@ static void HandlePacketFromAwayNode(SINT8 node) { SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); SV_SendPlayerInfo(node); // Send extra info - Net_CloseConnection(node); } + Net_CloseConnection(node); break; case PT_SERVERREFUSE: // Negative response of client join request @@ -3432,6 +3468,7 @@ static void HandlePacketFromAwayNode(SINT8 node) Net_CloseConnection(node); break; } + SERVERONLY if (cl_mode == CL_WAITJOINRESPONSE) { // Save the reason so it can be displayed after quitting the netgame @@ -3463,6 +3500,7 @@ static void HandlePacketFromAwayNode(SINT8 node) Net_CloseConnection(node); break; } + SERVERONLY /// \note how would this happen? and is it doing the right thing if it does? if (cl_mode != CL_WAITJOINRESPONSE) break; @@ -3528,13 +3566,18 @@ static void HandlePacketFromAwayNode(SINT8 node) Net_CloseConnection(node); break; } - else - Got_Filetxpak(); + SERVERONLY + Got_Filetxpak(); break; case PT_REQUESTFILE: if (server) - Got_RequestFilePak(node); + { + if (!cv_downloading.value || !Got_RequestFilePak(node)) + Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway + } + else + Net_CloseConnection(node); // nope break; case PT_NODETIMEOUT: @@ -3557,6 +3600,7 @@ static void HandlePacketFromAwayNode(SINT8 node) break; // Ignore it } +#undef SERVERONLY } /** Handles a packet received from a node that is in game @@ -3589,6 +3633,8 @@ FILESTAMP { // -------------------------------------------- SERVER RECEIVE ---------- case PT_RESYNCHGET: + if (client) + break; SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); break; case PT_CLIENTCMD: @@ -3655,7 +3701,8 @@ FILESTAMP } // Splitscreen cmd - if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0) + if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) + && nodetoplayer2[node] >= 0) G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); @@ -3714,6 +3761,27 @@ FILESTAMP tic_t tic = maketic; UINT8 *textcmd; + // ignore if the textcmd has a reported size of zero + // this shouldn't be sent at all + if (!netbuffer->u.textcmd[0]) + { + DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", + node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + + // ignore if the textcmd size var is actually larger than it should be + // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) + { + DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), + node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + // check if tic that we are making isn't too large else we cannot send it :( // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time j = software_MAXPACKETLENGTH @@ -3917,6 +3985,21 @@ FILESTAMP case PT_SERVERCFG: break; case PT_FILEFRAGMENT: + // Only accept PT_FILEFRAGMENT from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); + + if (server) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } if (client) Got_Filetxpak(); break; diff --git a/src/d_net.c b/src/d_net.c index 60a423ffa..48c1d60ea 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -713,6 +713,13 @@ void Net_CloseConnection(INT32 node) #else INT32 i; boolean forceclose = (node & FORCECLOSE) != 0; + + if (node == -1) + { + DEBFILE(M_GetText("Net_CloseConnection: node -1 detected!\n")); + return; // nope, just ignore it + } + node &= ~FORCECLOSE; if (!node) @@ -720,7 +727,7 @@ void Net_CloseConnection(INT32 node) if (node < 0 || node >= MAXNETNODES) // prevent invalid nodes from crashing the game { - CONS_Alert(CONS_WARNING, M_GetText("Net_CloseConnection: invalid node %d detected!\n"), node); + DEBFILE(va(M_GetText("Net_CloseConnection: invalid node %d detected!\n"), node)); return; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 125e9d2c3..0e96b0912 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1609,8 +1609,13 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese mapchangepending = 0; // spawn the server if needed // reset players if there is a new one - if (!(adminplayer == consoleplayer) && SV_SpawnServer()) - buf[0] &= ~(1<<1); + if (!(adminplayer == consoleplayer)) + { + if (SV_SpawnServer()) + buf[0] &= ~(1<<1); + if (!Playing()) // you failed to start a server somehow, so cancel the map change + return; + } // Kick bot from special stages if (botskin) @@ -3116,7 +3121,13 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) filestatus_t ncs = FS_NOTFOUND; UINT8 md5sum[16]; boolean kick = false; + boolean toomany = false; INT32 i; + size_t packetsize = 0; + serverinfo_pak *dummycheck = NULL; + + // Shut the compiler up. + (void)dummycheck; READSTRINGN(*cp, filename, 240); READMEM(*cp, md5sum, 16); @@ -3142,13 +3153,25 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) return; } - ncs = findfile(filename,md5sum,true); + // See W_LoadWadFile in w_wad.c + for (i = 0; i < numwadfiles; i++) + packetsize += nameonlylength(wadfiles[i]->filename) + 22; - if (ncs != FS_FOUND) + packetsize += nameonlylength(filename) + 22; + + if ((numwadfiles >= MAX_WADFILES) + || (packetsize > sizeof(dummycheck->fileneeded))) + toomany = true; + else + ncs = findfile(filename,md5sum,true); + + if (ncs != FS_FOUND || toomany) { char message[256]; - if (ncs == FS_NOTFOUND) + if (toomany) + sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename); + else if (ncs == FS_NOTFOUND) sprintf(message, M_GetText("The server doesn't have %s\n"), filename); else if (ncs == FS_MD5SUMBAD) sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename); @@ -3218,10 +3241,15 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) ncs = findfile(filename,md5sum,true); - if (ncs != FS_FOUND) + if (ncs != FS_FOUND || !P_AddWadFile(filename, NULL)) { Command_ExitGame_f(); - if (ncs == FS_NOTFOUND) + if (ncs == FS_FOUND) + { + CONS_Printf(M_GetText("The server tried to add %s,\nbut you have too many files added.\nRestart the game to clear loaded files\nand play on this server."), filename); + M_StartMessage(va("The server added a file \n(%s)\nbut you have too many files added.\nRestart the game to clear loaded files.\n\nPress ESC\n",filename), NULL, MM_NOTHING); + } + else if (ncs == FS_NOTFOUND) { CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), filename); M_StartMessage(va("The server added a file \n(%s)\nthat you do not have.\n\nPress ESC\n",filename), NULL, MM_NOTHING); @@ -3239,7 +3267,6 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) return; } - P_AddWadFile(filename, NULL); G_SetGameModified(true); } diff --git a/src/d_netfil.c b/src/d_netfil.c index bf4e59878..172624ad2 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -62,7 +62,8 @@ #include -static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid); +// Prototypes +static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid); // Sender structure typedef struct filetx_s @@ -303,7 +304,8 @@ boolean CL_SendRequestFile(void) } // get request filepak and put it on the send queue -void Got_RequestFilePak(INT32 node) +// returns false if a requested file was not found or cannot be sent +boolean Got_RequestFilePak(INT32 node) { char wad[MAX_WADPATH+1]; UINT8 *p = netbuffer->u.textcmd; @@ -314,8 +316,13 @@ void Got_RequestFilePak(INT32 node) if (id == 0xFF) break; READSTRINGN(p, wad, MAX_WADPATH); - SV_SendFile(node, wad, id); + if (!SV_SendFile(node, wad, id)) + { + SV_AbortSendFiles(node); + return false; // don't read the rest of the files + } } + return true; // no problems with any files } /** Checks if the files needed aren't already loaded or on the disk @@ -330,6 +337,12 @@ INT32 CL_CheckFiles(void) INT32 i, j; char wadfilename[MAX_WADPATH]; INT32 ret = 1; + size_t packetsize = 0; + size_t filestoget = 0; + serverinfo_pak *dummycheck = NULL; + + // Shut the compiler up. + (void)dummycheck; // if (M_CheckParm("-nofiles")) // return 1; @@ -378,6 +391,10 @@ INT32 CL_CheckFiles(void) return 1; } + // See W_LoadWadFile in w_wad.c + for (i = 0; i < numwadfiles; i++) + packetsize += nameonlylength(wadfiles[i]->filename) + 22; + for (i = 1; i < fileneedednum; i++) { CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); @@ -397,6 +414,14 @@ INT32 CL_CheckFiles(void) if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important) continue; + packetsize += nameonlylength(fileneeded[i].filename) + 22; + + if ((numwadfiles+filestoget >= MAX_WADFILES) + || (packetsize > sizeof(dummycheck->fileneeded))) + return 3; + + filestoget++; + fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); if (fileneeded[i].status != FS_FOUND) @@ -480,7 +505,7 @@ static INT32 filestosend = 0; * \sa SV_SendRam * */ -static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) +static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) { filetx_t **q; // A pointer to the "next" field of the last file in the list filetx_t *p; // The new file request @@ -488,7 +513,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) char wadfilename[MAX_WADPATH]; if (cv_noticedownload.value) - CONS_Printf("Sending file \"%s\" to node %d\n", filename, node); + CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node)); // Find the last file in the list and set a pointer to its "next" field q = &transfer[node].txlist; @@ -537,7 +562,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) free(p->id.filename); free(p); *q = NULL; - return; + return false; // cancel the rest of the requests } // Handle huge file requests (i.e. bigger than cv_maxsend.value KB) @@ -549,7 +574,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) free(p->id.filename); free(p); *q = NULL; - return; + return false; // cancel the rest of the requests } DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); @@ -557,6 +582,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) p->fileid = fileid; p->next = NULL; // End of list filestosend++; + return true; } /** Adds a memory block to the file list for a node diff --git a/src/d_netfil.h b/src/d_netfil.h index c9085a5b0..b9b7b2f2e 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -69,7 +69,7 @@ boolean SV_SendingFile(INT32 node); boolean CL_CheckDownloadable(void); boolean CL_SendRequestFile(void); -void Got_RequestFilePak(INT32 node); +boolean Got_RequestFilePak(INT32 node); void SV_AbortSendFiles(INT32 node); void CloseNetFile(void); diff --git a/src/doomdef.h b/src/doomdef.h index ffd799d55..6737cf6d1 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -214,7 +214,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 23 +#define MODVERSION 24 // ========================================================================= diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index b8cf1baec..a661aaf04 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -16,89 +16,127 @@ #include "lua_script.h" #include "lua_libs.h" +#define META_ITERATIONSTATE "iteration state" + static const char *const iter_opt[] = { "all", "mobj", NULL}; +static const actionf_p1 iter_funcs[] = { + NULL, + (actionf_p1)P_MobjThinker +}; + +struct iterationState { + actionf_p1 filter; + int next; +}; + +static int iterationState_gc(lua_State *L) +{ + struct iterationState *it = luaL_checkudata(L, -1, META_ITERATIONSTATE); + if (it->next != LUA_REFNIL) + { + luaL_unref(L, LUA_REGISTRYINDEX, it->next); + it->next = LUA_REFNIL; + } + return 0; +} + +#define push_thinker(th) {\ + if ((th)->function.acp1 == (actionf_p1)P_MobjThinker) \ + LUA_PushUserdata(L, (th), META_MOBJ); \ + else \ + lua_pushlightuserdata(L, (th)); \ +} + static int lib_iterateThinkers(lua_State *L) { - int state = luaL_checkoption(L, 1, "mobj", iter_opt); - - thinker_t *th = NULL; - actionf_p1 searchFunc; - const char *searchMeta; + thinker_t *th = NULL, *next = NULL; + struct iterationState *it; if (gamestate != GS_LEVEL) return luaL_error(L, "This function can only be used in a level!"); - lua_settop(L, 2); - lua_remove(L, 1); // remove state now. + it = luaL_checkudata(L, 1, META_ITERATIONSTATE); - switch(state) + lua_settop(L, 2); + + if (lua_isnil(L, 2)) + th = &thinkercap; + else if (lua_isuserdata(L, 2)) { - case 0: - searchFunc = NULL; - searchMeta = NULL; - break; - case 1: - default: - searchFunc = (actionf_p1)P_MobjThinker; - searchMeta = META_MOBJ; - break; + if (lua_islightuserdata(L, 2)) + th = lua_touserdata(L, 2); + else + { + th = *(thinker_t **)lua_touserdata(L, -1); + if (!th) + { + if (it->next == LUA_REFNIL) + return 0; + + lua_rawgeti(L, LUA_REGISTRYINDEX, it->next); + if (lua_islightuserdata(L, -1)) + next = lua_touserdata(L, -1); + else + next = *(thinker_t **)lua_touserdata(L, -1); + } + } } - if (!lua_isnil(L, 1)) { - if (lua_islightuserdata(L, 1)) - th = (thinker_t *)lua_touserdata(L, 1); - else if (searchMeta) - th = *((thinker_t **)luaL_checkudata(L, 1, searchMeta)); - else - th = *((thinker_t **)lua_touserdata(L, 1)); - } else - th = &thinkercap; + luaL_unref(L, LUA_REGISTRYINDEX, it->next); + it->next = LUA_REFNIL; - if (!th) // something got our userdata invalidated! - return 0; + if (th && !next) + next = th->next; + if (!next) + return luaL_error(L, "next thinker invalidated during iteration"); - if (searchFunc == NULL) - { - if ((th = th->next) != &thinkercap) + for (; next != &thinkercap; next = next->next) + if (!it->filter || next->function.acp1 == it->filter) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - LUA_PushUserdata(L, th, META_MOBJ); - else - lua_pushlightuserdata(L, th); + push_thinker(next); + if (next->next != &thinkercap) + { + push_thinker(next->next); + it->next = luaL_ref(L, LUA_REGISTRYINDEX); + } return 1; } - return 0; - } - - for (th = th->next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != searchFunc) - continue; - - LUA_PushUserdata(L, th, searchMeta); - return 1; - } return 0; } static int lib_startIterate(lua_State *L) { + struct iterationState *it; + if (gamestate != GS_LEVEL) return luaL_error(L, "This function can only be used in a level!"); - luaL_checkoption(L, 1, iter_opt[0], iter_opt); - lua_pushcfunction(L, lib_iterateThinkers); - lua_pushvalue(L, 1); + + lua_pushvalue(L, lua_upvalueindex(1)); + it = lua_newuserdata(L, sizeof(struct iterationState)); + luaL_getmetatable(L, META_ITERATIONSTATE); + lua_setmetatable(L, -2); + + it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)]; + it->next = LUA_REFNIL; return 2; } +#undef push_thinker + int LUA_ThinkerLib(lua_State *L) { + luaL_newmetatable(L, META_ITERATIONSTATE); + lua_pushcfunction(L, iterationState_gc); + lua_setfield(L, -2, "__gc"); + lua_pop(L, 1); + lua_createtable(L, 0, 1); - lua_pushcfunction(L, lib_startIterate); + lua_pushcfunction(L, lib_iterateThinkers); + lua_pushcclosure(L, lib_startIterate, 1); lua_setfield(L, -2, "iterate"); lua_setglobal(L, "thinkers"); return 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index 8820eac76..1d83e8706 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2802,7 +2802,7 @@ static boolean P_ZMovement(mobj_t *mo) mo->z = mo->floorz; #ifdef ESLOPE - if (mo->standingslope) // You're still on the ground; why are we here? + if (!(mo->flags & MF_MISSILE) && mo->standingslope) // You're still on the ground; why are we here? { mo->momz = 0; return true; @@ -8515,6 +8515,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_EGGCAPSULE: mobj->extravalue1 = -1; // timer for how long a player has been at the capsule + break; case MT_REDTEAMRING: mobj->color = skincolor_redteam; break; diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index fbf9bacb2..68391f99c 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.18; + CURRENT_PROJECT_VERSION = 2.1.19; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.18; + CURRENT_PROJECT_VERSION = 2.1.19; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index 98a760c7b..fada7849c 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.18; + CURRENT_PROJECT_VERSION = 2.1.19; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.18; + CURRENT_PROJECT_VERSION = 2.1.19; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/win32/win_cd.c b/src/win32/win_cd.c index d73b95523..ae13d3e57 100644 --- a/src/win32/win_cd.c +++ b/src/win32/win_cd.c @@ -180,9 +180,9 @@ static LPSTR hms(UINT seconds) hours = minutes / 60; minutes %= 60; if (hours > 0) - sprintf (s, "%lu:%02lu:%02lu", hours, minutes, seconds); + sprintf (s, "%lu:%02lu:%02lu", (long unsigned int)hours, (long unsigned int)minutes, (long unsigned int)seconds); else - sprintf (s, "%2lu:%02lu", minutes, seconds); + sprintf (s, "%2lu:%02lu", (long unsigned int)minutes, (long unsigned int)seconds); return s; } diff --git a/src/win32/win_main.c b/src/win32/win_main.c index d84c86232..4ac05f94f 100644 --- a/src/win32/win_main.c +++ b/src/win32/win_main.c @@ -470,7 +470,7 @@ static inline BOOL tlErrorMessage(const TCHAR *err) // // warn user if there is one // - printf("Error %Ts..\n", err); + printf("Error %s..\n", err); fflush(stdout); MessageBox(hWndMain, err, TEXT("ERROR"), MB_OK); diff --git a/src/y_inter.c b/src/y_inter.c index b92b0a5ca..9660f9287 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1008,7 +1008,8 @@ void Y_StartIntermission(void) } // We couldn't display the intermission even if we wanted to. - if (dedicated) return; + // But we still need to give the players their score bonuses, dummy. + //if (dedicated) return; // This should always exist, but just in case... if(!mapheaderinfo[prevmap])