mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-27 04:41:23 +00:00
Merge branch 'next' into public_next
This commit is contained in:
commit
5264f4ce08
17 changed files with 274 additions and 106 deletions
|
@ -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})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version: 2.1.18.{branch}-{build}
|
||||
version: 2.1.19.{branch}-{build}
|
||||
os: MinGW
|
||||
|
||||
environment:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
101
src/d_clisrv.c
101
src/d_clisrv.c
|
@ -1733,9 +1733,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)
|
||||
{
|
||||
|
@ -1769,7 +1767,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();
|
||||
|
@ -3402,17 +3413,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);
|
||||
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.
|
||||
// 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:
|
||||
|
@ -3420,8 +3456,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
|
||||
|
@ -3430,6 +3466,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
|
||||
|
@ -3461,6 +3498,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;
|
||||
|
@ -3524,13 +3562,18 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
Net_CloseConnection(node);
|
||||
break;
|
||||
}
|
||||
else
|
||||
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:
|
||||
|
@ -3553,6 +3596,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
break; // Ignore it
|
||||
|
||||
}
|
||||
#undef SERVERONLY
|
||||
}
|
||||
|
||||
/** Handles a packet received from a node that is in game
|
||||
|
@ -3585,6 +3629,8 @@ FILESTAMP
|
|||
{
|
||||
// -------------------------------------------- SERVER RECEIVE ----------
|
||||
case PT_RESYNCHGET:
|
||||
if (client)
|
||||
break;
|
||||
SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
|
||||
break;
|
||||
case PT_CLIENTCMD:
|
||||
|
@ -3651,7 +3697,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);
|
||||
|
||||
|
@ -3710,6 +3757,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
|
||||
|
@ -3913,6 +3981,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;
|
||||
|
|
|
@ -711,6 +711,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)
|
||||
|
@ -718,7 +725,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1569,8 +1569,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())
|
||||
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)
|
||||
|
@ -3078,7 +3083,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);
|
||||
|
@ -3104,13 +3115,25 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
packetsize += nameonlylength(wadfiles[i]->filename) + 22;
|
||||
|
||||
packetsize += nameonlylength(filename) + 22;
|
||||
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| (packetsize > sizeof(dummycheck->fileneeded)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfile(filename,md5sum,true);
|
||||
|
||||
if (ncs != FS_FOUND)
|
||||
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);
|
||||
|
@ -3180,10 +3203,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);
|
||||
|
@ -3201,7 +3229,6 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
P_AddWadFile(filename, NULL);
|
||||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -150,9 +150,9 @@ extern FILE *logstream;
|
|||
// we use comprevision and compbranch instead.
|
||||
#else
|
||||
#define VERSION 201 // Game version
|
||||
#define SUBVERSION 18 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.18"
|
||||
#define VERSIONSTRINGW L"v2.1.18"
|
||||
#define SUBVERSION 19 // more precise version number
|
||||
#define VERSIONSTRING "v2.1.19"
|
||||
#define VERSIONSTRINGW L"v2.1.19"
|
||||
// Hey! If you change this, add 1 to the MODVERSION below!
|
||||
// Otherwise we can't force updates!
|
||||
#endif
|
||||
|
@ -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
|
||||
|
||||
// =========================================================================
|
||||
|
||||
|
|
|
@ -16,67 +16,87 @@
|
|||
#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 = luaL_checkudata(L, 1, META_ITERATIONSTATE);
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // remove state now.
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 0:
|
||||
searchFunc = NULL;
|
||||
searchMeta = NULL;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
searchFunc = (actionf_p1)P_MobjThinker;
|
||||
searchMeta = META_MOBJ;
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
if (lua_isnil(L, 2))
|
||||
th = &thinkercap;
|
||||
|
||||
if (!th) // something got our userdata invalidated!
|
||||
return 0;
|
||||
|
||||
if (searchFunc == NULL)
|
||||
else if (lua_isuserdata(L, 2))
|
||||
{
|
||||
if ((th = th->next) != &thinkercap)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
LUA_PushUserdata(L, th, META_MOBJ);
|
||||
if (lua_islightuserdata(L, 2))
|
||||
th = lua_touserdata(L, 2);
|
||||
else
|
||||
lua_pushlightuserdata(L, th);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (th = th->next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != searchFunc)
|
||||
continue;
|
||||
th = *(thinker_t **)lua_touserdata(L, -1);
|
||||
if (!th)
|
||||
{
|
||||
if (it->next == LUA_REFNIL)
|
||||
return 0;
|
||||
|
||||
LUA_PushUserdata(L, th, searchMeta);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, it->next);
|
||||
it->next = LUA_REFNIL;
|
||||
|
||||
if (th && !next)
|
||||
next = th->next;
|
||||
if (!next)
|
||||
return luaL_error(L, "next thinker invalidated during iteration");
|
||||
|
||||
for (; next != &thinkercap; next = next->next)
|
||||
if (!it->filter || next->function.acp1 == it->filter)
|
||||
{
|
||||
push_thinker(next);
|
||||
if (next->next != &thinkercap)
|
||||
{
|
||||
push_thinker(next->next);
|
||||
it->next = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -84,16 +104,30 @@ static int lib_iterateThinkers(lua_State *L)
|
|||
|
||||
static int lib_startIterate(lua_State *L)
|
||||
{
|
||||
luaL_checkoption(L, 1, iter_opt[0], iter_opt);
|
||||
lua_pushcfunction(L, lib_iterateThinkers);
|
||||
lua_pushvalue(L, 1);
|
||||
struct iterationState *it;
|
||||
|
||||
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;
|
||||
|
|
|
@ -2363,7 +2363,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;
|
||||
|
@ -7807,6 +7807,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;
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -965,7 +965,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])
|
||||
|
|
Loading…
Reference in a new issue