From eb7c36d72c04628aacea18c79dc95e87fc1a7581 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sat, 16 Jan 2016 19:31:36 -0600 Subject: [PATCH 01/57] Reimplement I/O library Note: I/O library is fully functioning in this state, but lacks security restrictions. We'll get to those later ;) --- src/blua/Makefile.cfg | 1 + src/blua/linit.c | 1 + src/blua/liolib.c | 553 ++++++++++++++++++++++++++++++++++++++++++ src/blua/lualib.h | 3 + 4 files changed, 558 insertions(+) create mode 100644 src/blua/liolib.c diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index e3fb3df4..895f9362 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -18,6 +18,7 @@ OBJS:=$(OBJS) \ $(OBJDIR)/ldo.o \ $(OBJDIR)/lfunc.o \ $(OBJDIR)/linit.o \ + $(OBJDIR)/liolib.o \ $(OBJDIR)/llex.o \ $(OBJDIR)/lmem.o \ $(OBJDIR)/lobject.o \ diff --git a/src/blua/linit.c b/src/blua/linit.c index 52b02dbe..d17390b2 100644 --- a/src/blua/linit.c +++ b/src/blua/linit.c @@ -17,6 +17,7 @@ static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, {LUA_STRLIBNAME, luaopen_string}, {NULL, NULL} }; diff --git a/src/blua/liolib.c b/src/blua/liolib.c new file mode 100644 index 00000000..e79ed1cb --- /dev/null +++ b/src/blua/liolib.c @@ -0,0 +1,553 @@ +/* +** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/src/blua/lualib.h b/src/blua/lualib.h index 6ebe2728..4ea97edf 100644 --- a/src/blua/lualib.h +++ b/src/blua/lualib.h @@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L); #define LUA_TABLIBNAME "table" LUALIB_API int (luaopen_table) (lua_State *L); +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + #define LUA_STRLIBNAME "string" LUALIB_API int (luaopen_string) (lua_State *L); From c9fe83b95daa3189465049e53c058bdfa1ce51b4 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 17 Jan 2016 01:37:19 -0600 Subject: [PATCH 02/57] Block the use of ../ and ..\\ ...and remove io.popen(), cause that shit is DANGEROUS. --- src/blua/liolib.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e79ed1cb..5c48add7 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -160,6 +160,11 @@ static int io_tostring (lua_State *L) { static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); + if (strstr(filename, "../") || strstr(filename, "..\\")) + { + luaL_error(L,"access denied to %s", filename); + return pushresult(L,0,filename); + } const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); @@ -167,19 +172,6 @@ static int io_open (lua_State *L) { } -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); @@ -481,7 +473,6 @@ static const luaL_Reg iolib[] = { {"lines", io_lines}, {"open", io_open}, {"output", io_output}, - {"popen", io_popen}, {"read", io_read}, {"tmpfile", io_tmpfile}, {"type", io_type}, From a68e92690f8cc176e0c0e92b73e9c38ead20d3b3 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 02:26:15 -0600 Subject: [PATCH 03/57] Implement file type whitelist, completely remove popen and pclose This is probably super inefficient. Someone please teach me how2C. --- src/blua/liolib.c | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 5c48add7..d2303415 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -25,6 +25,13 @@ static const char *const fnames[] = {"input", "output"}; +static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder + ".txt", + ".sav2", + ".cfg", + ".png", + ".bmp" +}; static int pushresult (lua_State *L, int i, const char *filename) { @@ -102,17 +109,6 @@ static int io_noclose (lua_State *L) { } -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = NULL; - return pushresult(L, ok, NULL); -} - - /* ** function to close regular files */ @@ -159,16 +155,26 @@ static int io_tostring (lua_State *L) { static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - if (strstr(filename, "../") || strstr(filename, "..\\")) - { - luaL_error(L,"access denied to %s", filename); - return pushresult(L,0,filename); - } - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; + const char *filename = luaL_checkstring(L, 1); + int pass = 0; int i; + int length = strlen(filename) - 1; + for (i = 0; i < 5; i++) // wolfs == noobcoder, so manually change this with any added file types + { + if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) + { + pass = 1; + break; + } + } + if (strstr(filename, "../") || strstr(filename, "..\\") || !pass) + { + luaL_error(L,"access denied to %s", filename); + return pushresult(L,0,filename); + } + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } @@ -535,10 +541,6 @@ LUALIB_API int luaopen_io (lua_State *L) { createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stderr, 0, "stderr"); lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ return 1; } From 569f7d15d1992a437ad48a881feb62ec80d936bd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 16:59:55 -0600 Subject: [PATCH 04/57] Efficiency improvement in whitelist check Thanks Inu! --- src/blua/liolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index d2303415..6dd87704 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -158,7 +158,7 @@ static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); int pass = 0; int i; int length = strlen(filename) - 1; - for (i = 0; i < 5; i++) // wolfs == noobcoder, so manually change this with any added file types + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) { From de03db99e7110b65190d6d3fe540dfed623b33f2 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 21:31:00 -0600 Subject: [PATCH 05/57] Block possible methods of accessing folders outside of SRB2 --- src/blua/liolib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 6dd87704..100dbb6c 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -153,6 +153,12 @@ static int io_tostring (lua_State *L) { return 1; } +static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again +{ + if(strncmp(a, b, strlen(b)) == 0) return 1; + return 0; +} + static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); @@ -166,7 +172,8 @@ static int io_open (lua_State *L) { break; } } - if (strstr(filename, "../") || strstr(filename, "..\\") || !pass) + if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") + || StartsWith(filename, "/") || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); From 5579fb5240347ddc86987a8aedbae20d8602c4bd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 22:35:53 -0600 Subject: [PATCH 06/57] Limit file creation/manipulation to luafiles subfolder Also block % in filename strings --- src/blua/liolib.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 100dbb6c..ac168ef1 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -17,6 +17,9 @@ #include "lauxlib.h" #include "lualib.h" +#include "../i_system.h" +#include "../doomdef.h" +#include "../m_misc.h" @@ -173,11 +176,14 @@ static int io_open (lua_State *L) { } } if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") - || StartsWith(filename, "/") || !pass) + || StartsWith(filename, "/") || strchr(filename, '%') || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } + I_mkdir("luafiles", 0755); + char* destFilename = va("luafiles"PATHSEP"%s", filename); + filename = destFilename; const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); From e27494652850945f8e69383b8c726639cb4a54dd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 22 Jan 2016 00:46:32 -0600 Subject: [PATCH 07/57] Call I_mkdir on subdirectories [NEEDS CLEANUP] I got lazy and used a weird inefficient method, but I don't know how to clean this mess up :c At least it works. --- src/blua/liolib.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index ac168ef1..b209eec9 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -182,6 +182,22 @@ static int io_open (lua_State *L) { return pushresult(L,0,filename); } I_mkdir("luafiles", 0755); + char *splitter = filename; + while ((splitter = strchr(splitter, '/'))) + { + *splitter = 0; + I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + *splitter = '/'; + splitter++; + } + char *splitter2 = filename; + while ((splitter2 = strchr(splitter2, '\\'))) + { + *splitter2 = 0; + I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + *splitter2 = '\\'; + splitter2++; + } char* destFilename = va("luafiles"PATHSEP"%s", filename); filename = destFilename; const char *mode = luaL_optstring(L, 2, "r"); From 591b8035663fc60490229b63b4c43f55b0c0a81c Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 22 Jan 2016 21:45:48 -0600 Subject: [PATCH 08/57] Limit file write size to 1MB If the total file size is above 1MB after writing, discard all changes. --- src/blua/liolib.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index b209eec9..2d20f529 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -26,6 +26,8 @@ #define IO_INPUT 1 #define IO_OUTPUT 2 +#define FILELIMIT 1024*1024 // Size limit for reading/writing files + static const char *const fnames[] = {"input", "output"}; static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder @@ -437,6 +439,7 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; + size_t count; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ @@ -446,6 +449,12 @@ static int g_write (lua_State *L, FILE *f, int arg) { else { size_t l; const char *s = luaL_checklstring(L, arg, &l); + count += l; + if (ftell(f) + l > FILELIMIT) + { + luaL_error(L,"write limit bypassed in file. Changes have been discarded."); + break; + } status = status && (fwrite(s, sizeof(char), l, f) == l); } } From 2639bf4c0ba035bcd79f12ae4f6f00d86feeb662 Mon Sep 17 00:00:00 2001 From: Nipples the Enchilada Date: Sun, 24 Jan 2016 00:24:26 -0500 Subject: [PATCH 09/57] Add liolib.c to CMakeLists --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bb4f9a4a..9a8b3bac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -265,6 +265,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) blua/lfunc.c blua/lgc.c blua/linit.c + blua/liolib.c blua/llex.c blua/lmem.c blua/lobject.c From 0f2a0927418334376a1675590ba7313dde44606e Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 01:13:21 -0800 Subject: [PATCH 10/57] objectplace stability fix Objectplace reallocates the mapthings list to add one more mapthing. By itself there's no problem with this. But, mobj->spawnpoint is a pointer to the mapthing's location in the mapthings list. So by reallocating the mapthings list, all references to mobj->spawnpoints point to freed memory. ... Oops. Now when objectplace reallocates the mapthings list it actually corrects the locations of all mobj's spawnpoints to point to the new list. Hooray, you can use NiGHTS objectplace again if you really want to. --- src/m_cheat.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index bc32e6cf..473fbbf7 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -880,12 +880,33 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling) static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling) { - mapthing_t *mt; + mapthing_t *mt = mapthings; + #ifdef HAVE_BLUA LUA_InvalidateMapthings(); #endif mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + // as Z_Realloc can relocate mapthings, quickly go through thinker list and correct + // the spawnpoints of any objects that have them to the new location + if (mt != mapthings) + { + thinker_t *th; + mobj_t *mo; + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + // get offset from mt, which points to old mapthings, then add new location + if (mo->spawnpoint) + mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; + } + } + mt = (mapthings+nummapthings-1); mt->type = type; From f2f8906a19cd17163853f402f828f609df4c8069 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 18 Jan 2016 19:46:00 +0000 Subject: [PATCH 11/57] Use modulo, not bitwise AND. My fault once again, whoops. The point here is ColorOpposite(MAXSKINCOLORS) would have given an actual result of its own since MAXSKINCOLORS & MAXSKINCOLORS is still MAXSKINCOLORS. This shouldn't happen though, as both Color_Opposite[MAXSKINCOLORS*2] and Color_Opposite[MAXSKINCOLOR*2+1] aren't defined. --- src/lua_mathlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index f4b5ca5f..fd00180d 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -166,7 +166,7 @@ static int lib_all7emeralds(lua_State *L) // Returns both color and frame numbers! static int lib_coloropposite(lua_State *L) { - int colornum = ((int)luaL_checkinteger(L, 1)) & MAXSKINCOLORS; + int colornum = ((int)luaL_checkinteger(L, 1)) % MAXSKINCOLORS; lua_pushinteger(L, Color_Opposite[colornum*2]); // push color lua_pushinteger(L, Color_Opposite[colornum*2+1]); // push frame return 2; From f559b50995ea7be5e7b3119a095aeab8cc235773 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 09:25:28 -0800 Subject: [PATCH 12/57] fix bad lstring usage in map header lua This is not how you use pushlstring! This is actually sending uninitialized memory to Lua, which is making scripts have inconsistent results (duh?) c/o JTE: "Tell Red they're a doofus." --- src/lua_maplib.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0a12478c..85c3b094 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1162,9 +1162,9 @@ static int mapheaderinfo_get(lua_State *L) //for (i = 0; i < 21; i++) // if (!header->lvlttl[i]) // break; - lua_pushlstring(L, header->lvlttl, 21); + lua_pushstring(L, header->lvlttl); } else if (fastcmp(field,"subttl")) - lua_pushlstring(L, header->subttl, 32); + lua_pushstring(L, header->subttl); else if (fastcmp(field,"actnum")) lua_pushinteger(L, header->actnum); else if (fastcmp(field,"typeoflevel")) @@ -1176,7 +1176,7 @@ static int mapheaderinfo_get(lua_State *L) else if (fastcmp(field,"musicslottrack")) lua_pushinteger(L, header->musicslottrack); else if (fastcmp(field,"forcecharacter")) - lua_pushlstring(L, header->forcecharacter, 16); + lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) lua_pushinteger(L, header->weather); else if (fastcmp(field,"skynum")) @@ -1188,11 +1188,11 @@ static int mapheaderinfo_get(lua_State *L) else if (fastcmp(field,"skybox_scalez")) lua_pushinteger(L, header->skybox_scalez); else if (fastcmp(field,"interscreen")) - lua_pushlstring(L, header->interscreen, 8); + lua_pushstring(L, header->interscreen); else if (fastcmp(field,"runsoc")) - lua_pushlstring(L, header->runsoc, 32); + lua_pushstring(L, header->runsoc); else if (fastcmp(field,"scriptname")) - lua_pushlstring(L, header->scriptname, 32); + lua_pushstring(L, header->scriptname); else if (fastcmp(field,"precutscenenum")) lua_pushinteger(L, header->precutscenenum); else if (fastcmp(field,"cutscenenum")) @@ -1221,7 +1221,7 @@ static int mapheaderinfo_get(lua_State *L) for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i); if(i < header->numCustomOptions) - lua_pushlstring(L, header->customopts[i].value, 255); + lua_pushstring(L, header->customopts[i].value); else lua_pushnil(L); } From c30188f9fdfa6cf674e998b962d99e3f203a2606 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 09:42:35 -0800 Subject: [PATCH 13/57] interscreen is a lump name and thus needs lstring ... not just lstring though, but the behavior with i that is used elsewhere. --- src/lua_maplib.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 85c3b094..6f28997a 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1157,13 +1157,10 @@ static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); const char *field = luaL_checkstring(L, 2); - //INT16 i; - if (fastcmp(field,"lvlttl")) { - //for (i = 0; i < 21; i++) - // if (!header->lvlttl[i]) - // break; + INT16 i; + if (fastcmp(field,"lvlttl")) lua_pushstring(L, header->lvlttl); - } else if (fastcmp(field,"subttl")) + else if (fastcmp(field,"subttl")) lua_pushstring(L, header->subttl); else if (fastcmp(field,"actnum")) lua_pushinteger(L, header->actnum); @@ -1187,9 +1184,12 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->skybox_scaley); else if (fastcmp(field,"skybox_scalez")) lua_pushinteger(L, header->skybox_scalez); - else if (fastcmp(field,"interscreen")) - lua_pushstring(L, header->interscreen); - else if (fastcmp(field,"runsoc")) + else if (fastcmp(field,"interscreen")) { + for (i = 0; i < 8; i++) + if (!header->interscreen[i]) + break; + lua_pushlstring(L, header->interscreen, i); + } else if (fastcmp(field,"runsoc")) lua_pushstring(L, header->runsoc); else if (fastcmp(field,"scriptname")) lua_pushstring(L, header->scriptname); From c7e540a870f53711a3580b3510de83e33d8e14bc Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 21 Jan 2016 13:50:05 -0500 Subject: [PATCH 14/57] whitespace cleanup --- src/r_bsp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index badf8bda..c547713b 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -935,14 +935,14 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; - - floorcenterz = + + floorcenterz = #ifdef ESLOPE frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif frontsector->floorheight; - - ceilingcenterz = + + ceilingcenterz = #ifdef ESLOPE frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -953,8 +953,8 @@ static void R_Subsector(size_t num) *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : #endif *rover->bottomheight; - - planecenterz = + + planecenterz = #ifdef ESLOPE *rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -966,7 +966,7 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->bottomheight); - + ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover @@ -1002,8 +1002,8 @@ static void R_Subsector(size_t num) *rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : #endif *rover->topheight; - - planecenterz = + + planecenterz = #ifdef ESLOPE *rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -1014,7 +1014,7 @@ static void R_Subsector(size_t num) || (viewz < heightcheck && (rover->flags & FF_BOTHPLANES)))) { light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->topheight); - + ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, frontsector->lightlist[light].extra_colormap, rover From f65c5c016adb2456b020d3a8b280cc963370aeca Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 21 Jan 2016 20:27:35 +0000 Subject: [PATCH 15/57] Fix shadowing in mapheaderinfo_get --- src/lua_maplib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6f28997a..38920c22 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1217,11 +1217,11 @@ static int mapheaderinfo_get(lua_State *L) else { // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) - UINT8 i = 0; - for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i); + UINT8 j = 0; + for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j); - if(i < header->numCustomOptions) - lua_pushstring(L, header->customopts[i].value); + if(j < header->numCustomOptions) + lua_pushstring(L, header->customopts[j].value); else lua_pushnil(L); } From 63a3e03bb0ed8e57860892acc4c8444e8be06d54 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 23 Jan 2016 18:59:17 +0000 Subject: [PATCH 16/57] Fixed math for calculating current texture in texture animations --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index cac822ac..81994d46 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4671,11 +4671,11 @@ void P_UpdateSpecials(void) // ANIMATE TEXTURES for (anim = anims; anim < lastanim; anim++) { - for (i = anim->basepic; i < anim->basepic + anim->numpics; i++) + for (i = 0; i < anim->numpics; i++) { pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); if (anim->istexture) - texturetranslation[i] = pic; + texturetranslation[anim->basepic+i] = pic; } } From 14dcd2404b1f5972cee0b6dc4c559f2506c00a02 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 25 Jan 2016 16:45:08 +0000 Subject: [PATCH 17/57] Fixed compiler warnings to the best of my ability Hopefully this all still works properly, try not to kill me if it doesn't =V --- src/blua/liolib.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 2d20f529..e9a50f37 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -167,8 +167,12 @@ static int StartsWith(const char *a, const char *b) // this is wolfs being lazy static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); - int pass = 0; int i; + int pass = 0; size_t i; int length = strlen(filename) - 1; + char *splitter, *splitter2; + char *destFilename = NULL; + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf; for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) @@ -184,26 +188,27 @@ static int io_open (lua_State *L) { return pushresult(L,0,filename); } I_mkdir("luafiles", 0755); - char *splitter = filename; + + strcpy(destFilename, filename); // copy file name to temp string + splitter = destFilename; while ((splitter = strchr(splitter, '/'))) { *splitter = 0; - I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); *splitter = '/'; splitter++; } - char *splitter2 = filename; + splitter2 = destFilename; while ((splitter2 = strchr(splitter2, '\\'))) { *splitter2 = 0; - I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); *splitter2 = '\\'; splitter2++; } - char* destFilename = va("luafiles"PATHSEP"%s", filename); + destFilename = va("luafiles"PATHSEP"%s", destFilename); filename = destFilename; - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); + pf = newfile(L); *pf = fopen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } From 9c299e5ad484a153d16e127881f4f7701295328e Mon Sep 17 00:00:00 2001 From: Nipples the Enchilada Date: Mon, 25 Jan 2016 22:48:45 -0500 Subject: [PATCH 18/57] Fix and clean up io_open after MI broke it horribly strcpy(NULL, filename); congrats --- src/blua/liolib.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e9a50f37..dee512bf 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -166,16 +166,18 @@ static int StartsWith(const char *a, const char *b) // this is wolfs being lazy static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - int pass = 0; size_t i; - int length = strlen(filename) - 1; - char *splitter, *splitter2; - char *destFilename = NULL; - const char *mode = luaL_optstring(L, 2, "r"); FILE **pf; + const char *filename = luaL_checkstring(L, 1); + int pass = 0; + size_t i; + int length = strlen(filename); + char *splitter, *forward, *backward; + char *destFilename; + const char *mode = luaL_optstring(L, 2, "r"); + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { - if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) + if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) { pass = 1; break; @@ -187,29 +189,27 @@ static int io_open (lua_State *L) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } - I_mkdir("luafiles", 0755); - - strcpy(destFilename, filename); // copy file name to temp string + + destFilename = va("luafiles"PATHSEP"%s", filename); + + // Make directories as needed splitter = destFilename; - while ((splitter = strchr(splitter, '/'))) + + forward = strchr(splitter, '/'); + backward = strchr(splitter, '\\'); + while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward))) { *splitter = 0; - I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); + I_mkdir(destFilename, 0755); *splitter = '/'; splitter++; + + forward = strchr(splitter, '/'); + backward = strchr(splitter, '\\'); } - splitter2 = destFilename; - while ((splitter2 = strchr(splitter2, '\\'))) - { - *splitter2 = 0; - I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); - *splitter2 = '\\'; - splitter2++; - } - destFilename = va("luafiles"PATHSEP"%s", destFilename); - filename = destFilename; + pf = newfile(L); - *pf = fopen(filename, mode); + *pf = fopen(destFilename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } From 2eedecb93ac87e91277c076e39b4c3358e7c42eb Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 26 Jan 2016 12:07:28 +0000 Subject: [PATCH 19/57] Get rid of unneeded tab spaces Least I can do to make up for breaking io.open in the first place :E --- src/blua/liolib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index dee512bf..27ff7449 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -174,7 +174,7 @@ static int io_open (lua_State *L) { char *splitter, *forward, *backward; char *destFilename; const char *mode = luaL_optstring(L, 2, "r"); - + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) @@ -189,12 +189,12 @@ static int io_open (lua_State *L) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } - + destFilename = va("luafiles"PATHSEP"%s", filename); - + // Make directories as needed splitter = destFilename; - + forward = strchr(splitter, '/'); backward = strchr(splitter, '\\'); while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward))) @@ -203,11 +203,11 @@ static int io_open (lua_State *L) { I_mkdir(destFilename, 0755); *splitter = '/'; splitter++; - + forward = strchr(splitter, '/'); backward = strchr(splitter, '\\'); } - + pf = newfile(L); *pf = fopen(destFilename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; From db7da456d2d330f3c116e69017a61f3c82012614 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 29 Jan 2016 01:38:41 -0600 Subject: [PATCH 20/57] Remove block on % in filename strings According to Alam, supporting this shouldn't cause any issues. --- src/blua/liolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 27ff7449..a9e71f74 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -184,7 +184,7 @@ static int io_open (lua_State *L) { } } if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") - || StartsWith(filename, "/") || strchr(filename, '%') || !pass) + || StartsWith(filename, "/") || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); From 12d40a07ccbd6145e228cc5399a19b0e09966e83 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 27 Jun 2020 20:58:33 -0400 Subject: [PATCH 21/57] Load one file per tic Prevents game from locking up when loading large file lists --- src/d_clisrv.c | 19 ++++++++++++------- src/d_netfil.c | 4 +++- src/d_netfil.h | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 251f413a..e0bba6bf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1095,6 +1095,7 @@ typedef enum CL_SEARCHING, CL_DOWNLOADFILES, CL_ASKJOIN, + CL_LOADFILES, CL_WAITJOINRESPONSE, #ifdef JOININGAME CL_DOWNLOADSAVEGAME, @@ -1202,7 +1203,10 @@ static inline void CL_DrawConnectionStatus(void) break; #endif case CL_ASKFULLFILELIST: - cltext = M_GetText("This server has a LOT of files!"); + cltext = M_GetText("This server has a LOT of addons!"); + break; + case CL_LOADFILES: + cltext = M_GetText("Loading server addons..."); break; case CL_ASKJOIN: case CL_WAITJOINRESPONSE: @@ -1933,7 +1937,7 @@ static boolean CL_FinishedFileList(void) return false; } else if (i == 1) - cl_mode = CL_ASKJOIN; + cl_mode = CL_LOADFILES; else { // must download something @@ -2143,7 +2147,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic } if (!curl_transfers) - cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now + cl_mode = CL_LOADFILES; // don't break case continue to cljoin request now break; #endif @@ -2159,11 +2163,12 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic if (waitmore) break; // exit the case - cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now - /* FALLTHRU */ - + cl_mode = CL_LOADFILES; // don't break case continue to cljoin request now + break; + case CL_LOADFILES: + if (!CL_LoadServerFiles()) + break; case CL_ASKJOIN: - CL_LoadServerFiles(); #ifdef JOININGAME // prepare structures to save the file // WARNING: this can be useless in case of server not in GS_LEVEL diff --git a/src/d_netfil.c b/src/d_netfil.c index 821d2a5b..f65959dc 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -457,7 +457,7 @@ INT32 CL_CheckFiles(void) } // Load it now -void CL_LoadServerFiles(void) +boolean CL_LoadServerFiles(void) { INT32 i; @@ -473,6 +473,7 @@ void CL_LoadServerFiles(void) P_AddWadFile(fileneeded[i].filename); G_SetGameModified(true, false); fileneeded[i].status = FS_OPEN; + return false; } else if (fileneeded[i].status == FS_MD5SUMBAD) I_Error("Wrong version of file %s", fileneeded[i].filename); @@ -498,6 +499,7 @@ void CL_LoadServerFiles(void) fileneeded[i].status, s); } } + return true; } // Number of files to send diff --git a/src/d_netfil.h b/src/d_netfil.h index f37df371..3bc2d0d3 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -65,7 +65,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi void CL_PrepareDownloadSaveGame(const char *tmpsave); INT32 CL_CheckFiles(void); -void CL_LoadServerFiles(void); +boolean CL_LoadServerFiles(void); void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid); From fc9f40a177cc9263311e34db994e93517850ad7d Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 21 Mar 2020 21:32:15 -0400 Subject: [PATCH 22/57] New "Overall Download Progress" bar Shows progress of all file downloads pre-join --- src/d_clisrv.c | 49 +++++++++++++++++++++++++++++++++++++------------ src/d_netfil.c | 5 +++++ src/d_netfil.h | 2 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e0bba6bf..0579eb23 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1167,10 +1167,6 @@ static inline void CL_DrawConnectionStatus(void) // Draw background fade V_DrawFadeScreen(0xFF00, 16); - // Draw the bottom box. - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); - if (cl_mode != CL_DOWNLOADFILES #ifdef HAVE_CURL && cl_mode != CL_DOWNLOADHTTPFILES @@ -1182,6 +1178,10 @@ static inline void CL_DrawConnectionStatus(void) // 15 pal entries total. const char *cltext; + //Draw bottom box + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); + for (i = 0; i < 16; ++i) V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); @@ -1221,13 +1221,18 @@ static inline void CL_DrawConnectionStatus(void) cltext = M_GetText("Connecting to server..."); break; } - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, cltext); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-32, V_YELLOWMAP, cltext); } else { if (lastfilenum != -1) { + // Draw the bottom box. + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press ESC to abort"); + INT32 dldlength; + INT32 totalfileslength; static char tempname[28]; fileneeded_t *file = &fileneeded[lastfilenum]; char *filename = file->filename; @@ -1236,8 +1241,10 @@ static inline void CL_DrawConnectionStatus(void) dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); if (dldlength > 256) dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 160); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, 256, 8, 175); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, dldlength, 8, 160); + + memset(tempname, 0, sizeof(tempname)); // offset filename to just the name only part @@ -1255,15 +1262,24 @@ static inline void CL_DrawConnectionStatus(void) strncpy(tempname, filename, sizeof(tempname)-1); } - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-22, V_YELLOWMAP, va(M_GetText("Downloading \"%s\""), tempname)); - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, V_20TRANS|V_MONOSPACE, va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-58, V_20TRANS|V_MONOSPACE, va("%3.1fK/s ", ((double)getbps)/1024)); + + // Download progress + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Total File Download Progress"); + totalfileslength = (INT32)((downloadcompletednum/(double)totalfilesrequestednum) * 256); + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %2u/%2u",downloadcompletednum,totalfilesrequestednum)); } else - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-32, V_YELLOWMAP, M_GetText("Waiting to download files...")); } } @@ -1963,7 +1979,11 @@ static boolean CL_FinishedFileList(void) } if (CL_SendRequestFile()) + { cl_mode = CL_DOWNLOADFILES; + downloadcompletednum = 0; + totalfilesrequestednum = 0; + } } #ifdef HAVE_CURL else @@ -2108,10 +2128,15 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic case CL_PREPAREHTTPFILES: if (http_source[0]) { + downloadcompletednum = 0; + totalfilesrequestednum = 0; for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + { curl_transfers++; - + totalfilesrequestednum++; + } + cl_mode = CL_DOWNLOADHTTPFILES; } break; diff --git a/src/d_netfil.c b/src/d_netfil.c index f65959dc..7fd9e294 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -108,6 +108,8 @@ char downloaddir[512] = "DOWNLOAD"; #ifdef CLIENT_LOADINGSCREEN // for cl loading screen INT32 lastfilenum = -1; +INT32 downloadcompletednum = 0; +INT32 totalfilesrequestednum = 0; #endif #ifdef HAVE_CURL @@ -330,6 +332,7 @@ boolean CL_SendRequestFile(void) // put it in download dir strcatbf(fileneeded[i].filename, downloaddir, "/"); fileneeded[i].status = FS_REQUESTED; + totalfilesrequestednum++; } WRITEUINT8(p, 0xFF); I_GetDiskFreeSpace(&availablefreespace); @@ -860,6 +863,7 @@ void Got_Filetxpak(void) file->status = FS_FOUND; CONS_Printf(M_GetText("Downloading %s...(done)\n"), filename); + downloadcompletednum++; } } else @@ -1171,6 +1175,7 @@ void CURLGetFile(void) { nameonly(curl_realname); CONS_Printf(M_GetText("Finished downloading %s\n"), curl_realname); + downloadcompletednum++; curl_curfile->status = FS_FOUND; fclose(curl_curfile->file); } diff --git a/src/d_netfil.h b/src/d_netfil.h index 3bc2d0d3..b9fdd00a 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -52,6 +52,8 @@ extern char downloaddir[512]; #ifdef CLIENT_LOADINGSCREEN extern INT32 lastfilenum; +extern INT32 downloadcompletednum; +extern INT32 totalfilesrequestednum; #endif #ifdef HAVE_CURL From 9d9105929b220867d7ef340ad17c63c0fe5a3c12 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 21 Mar 2020 21:35:02 -0400 Subject: [PATCH 23/57] Adjustment to new progress text --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 0579eb23..5ef11c1a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1270,13 +1270,13 @@ static inline void CL_DrawConnectionStatus(void) va("%3.1fK/s ", ((double)getbps)/1024)); // Download progress - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Total File Download Progress"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Overall Download Progress"); totalfileslength = (INT32)((downloadcompletednum/(double)totalfilesrequestednum) * 256); M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %2u/%2u",downloadcompletednum,totalfilesrequestednum)); + va(" %2u/%2u Files",downloadcompletednum,totalfilesrequestednum)); } else V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-32, V_YELLOWMAP, From d96c938dbf05e012ebbda1c7db4f00bdc8802b57 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 27 Jun 2020 23:26:38 -0400 Subject: [PATCH 24/57] Add progress bar for file loading --- src/d_clisrv.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5ef11c1a..b9a3294a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1167,7 +1167,7 @@ static inline void CL_DrawConnectionStatus(void) // Draw background fade V_DrawFadeScreen(0xFF00, 16); - if (cl_mode != CL_DOWNLOADFILES + if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES #ifdef HAVE_CURL && cl_mode != CL_DOWNLOADHTTPFILES #endif @@ -1221,11 +1221,32 @@ static inline void CL_DrawConnectionStatus(void) cltext = M_GetText("Connecting to server..."); break; } - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-32, V_YELLOWMAP, cltext); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, cltext); } else { - if (lastfilenum != -1) + if (cl_mode == CL_LOADFILES) + { + INT32 totalfileslength; + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Press ESC to abort"); + + //ima just count files here + INT32 loadcompletednum = 0; + INT32 i; + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_OPEN) + loadcompletednum++; + + // Loading progress + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Loading server addons..."); + totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum+1)) * 256); + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %2u/%2u Files",loadcompletednum,fileneedednum+1)); + } + else if (lastfilenum != -1) { // Draw the bottom box. M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1); From f2593219a64d37b59aabb71457164c8228600aa7 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 27 Jun 2020 23:40:13 -0400 Subject: [PATCH 25/57] Adjust text position --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b9a3294a..d529aebf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1228,7 +1228,7 @@ static inline void CL_DrawConnectionStatus(void) if (cl_mode == CL_LOADFILES) { INT32 totalfileslength; - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Press ESC to abort"); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); //ima just count files here INT32 loadcompletednum = 0; @@ -1238,7 +1238,7 @@ static inline void CL_DrawConnectionStatus(void) loadcompletednum++; // Loading progress - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Loading server addons..."); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Loading server addons..."); totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum+1)) * 256); M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); From 8eb9a6946f4b1ac084280e71a6ecab2880c321d0 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 1 Jul 2020 21:40:21 -0400 Subject: [PATCH 26/57] Fix X/0 files display bug for legacy downloader Also made "Waiting to Download" consistent with other states --- src/d_clisrv.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d529aebf..afe518e0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1300,8 +1300,21 @@ static inline void CL_DrawConnectionStatus(void) va(" %2u/%2u Files",downloadcompletednum,totalfilesrequestednum)); } else - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-32, V_YELLOWMAP, + { + INT32 i, animtime = ((ccstime / 4) & 15) + 16; + UINT8 palstart = (cl_mode == CL_SEARCHING) ? 128 : 160; + // 15 pal entries total. + + //Draw bottom box + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); + + for (i = 0; i < 16; ++i) + V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, M_GetText("Waiting to download files...")); + } } } #endif @@ -1999,11 +2012,11 @@ static boolean CL_FinishedFileList(void) return false; } + downloadcompletednum = 0; + totalfilesrequestednum = 0; if (CL_SendRequestFile()) { cl_mode = CL_DOWNLOADFILES; - downloadcompletednum = 0; - totalfilesrequestednum = 0; } } #ifdef HAVE_CURL @@ -2147,10 +2160,10 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic #ifdef HAVE_CURL case CL_PREPAREHTTPFILES: + downloadcompletednum = 0; + totalfilesrequestednum = 0; if (http_source[0]) { - downloadcompletednum = 0; - totalfilesrequestednum = 0; for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) { From 03d479fdb61108fd8804fff50d107a186d5779c4 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 1 Jul 2020 23:48:14 -0400 Subject: [PATCH 27/57] Connection screen no longer freezes up while searching for addons on disk Game will run one tic after every file status is updated --- src/d_clisrv.c | 6 +++++- src/d_netcmd.c | 6 +++--- src/d_netfil.c | 37 ++++++++++++++++++++++++------------- src/d_netfil.h | 1 + 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index afe518e0..7b419316 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1958,7 +1958,11 @@ static boolean CL_FinishedFileList(void) INT32 i; CONS_Printf(M_GetText("Checking files...\n")); i = CL_CheckFiles(); - if (i == 3) // too many files + if (i == 4) // still checking ... + { + return true; + } + else if (i == 3) // too many files { D_QuitNetGame(); CL_Reset(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7d94d2ed..8d778624 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4088,7 +4088,7 @@ static void Command_RunSOC(void) static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) { char filename[256]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -4260,7 +4260,7 @@ static void Command_Delfile(void) static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; UINT8 md5sum[16]; boolean kick = false; boolean toomany = false; @@ -4355,7 +4355,7 @@ static void Got_Delfilecmd(UINT8 **cp, INT32 playernum) static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; - filestatus_t ncs = FS_NOTFOUND; + filestatus_t ncs = FS_NOTCHECKED; UINT8 md5sum[16]; READSTRINGN(*cp, filename, 240); diff --git a/src/d_netfil.c b/src/d_netfil.c index 7fd9e294..c4c2edd6 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -209,7 +209,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi p = (UINT8 *)fileneededstr; for (i = firstfile; i < fileneedednum; i++) { - fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet + fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet filestatus = READUINT8(p); // The first byte is the file status fileneeded[i].willsend = (UINT8)(filestatus >> 4); fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size @@ -373,6 +373,8 @@ boolean Got_RequestFilePak(INT32 node) * \return 0 if some files are missing * 1 if all files exist * 2 if some already loaded files are not requested or are in a different order + * 3 too many files, over WADLIMIT + * 4 still checking, continuing next tic * */ INT32 CL_CheckFiles(void) @@ -381,7 +383,8 @@ INT32 CL_CheckFiles(void) char wadfilename[MAX_WADPATH]; INT32 ret = 1; size_t packetsize = 0; - size_t filestoget = 0; + size_t filestoload = 0; + boolean downloadrequired = false; // if (M_CheckParm("-nofiles")) // return 1; @@ -427,6 +430,15 @@ INT32 CL_CheckFiles(void) for (i = 0; i < fileneedednum; i++) { + if (fileneeded[i].status != FS_OPEN) //little messy, but this will count right by the time we get through the last file + filestoload++; + + if (fileneeded[i].status == FS_NOTFOUND) + downloadrequired = true; + + if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics + continue; + CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files @@ -438,25 +450,24 @@ INT32 CL_CheckFiles(void) { CONS_Debug(DBG_NETPLAY, "already loaded\n"); fileneeded[i].status = FS_OPEN; - break; + return 4; } } - if (fileneeded[i].status != FS_NOTFOUND) - continue; packetsize += nameonlylength(fileneeded[i].filename) + 22; - if (mainwads+filestoget >= MAX_WADFILES) - 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) - ret = 0; + return 4; } - return ret; + + //now making it here means we've checked the entire list and no FS_NOTCHECKED files remain + if (mainwads+filestoload >= MAX_WADFILES) + return 3; //ensure we wouldn't go over the wad limit + else if (downloadrequired) + return 0; //some stuff is FS_NOTFOUND, needs download + else + return 1; //everything is FS_OPEN or FS_FOUND, proceed to loading } // Load it now diff --git a/src/d_netfil.h b/src/d_netfil.h index b9fdd00a..58ee8b7e 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -25,6 +25,7 @@ typedef enum typedef enum { + FS_NOTCHECKED, FS_NOTFOUND, FS_FOUND, FS_REQUESTED, From 6fe8a6c96af55f6d009d87ca785e77ac06827b0e Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 1 Jul 2020 23:52:43 -0400 Subject: [PATCH 28/57] Changed "this server has a lot of addons!" to "Checking server addon list ..." to be more informative --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7b419316..15b155bf 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1203,7 +1203,7 @@ static inline void CL_DrawConnectionStatus(void) break; #endif case CL_ASKFULLFILELIST: - cltext = M_GetText("This server has a LOT of addons!"); + cltext = M_GetText("Checking server addon list ..."); break; case CL_LOADFILES: cltext = M_GetText("Loading server addons..."); From 774b917c0e069bc3eb87ff22e5522a58f698558f Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 2 Jul 2020 17:47:10 -0400 Subject: [PATCH 29/57] Correct total files to load off by one --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 15b155bf..a73df38a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1239,12 +1239,12 @@ static inline void CL_DrawConnectionStatus(void) // Loading progress V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Loading server addons..."); - totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum+1)) * 256); + totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256); M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %2u/%2u Files",loadcompletednum,fileneedednum+1)); + va(" %2u/%2u Files",loadcompletednum,fileneedednum)); } else if (lastfilenum != -1) { From b8fdd6b89cde9eceecca9893c5b164b34b9f1311 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 2 Jul 2020 20:57:33 -0400 Subject: [PATCH 30/57] Fix file number accounting Should ensure appropriate accounting and prevent loading of server files if it would put us over MAX_WADFILES --- src/d_netfil.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index c4c2edd6..25825d52 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -143,7 +143,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - for (i = mainwads; i < numwadfiles; i++) + for (i = mainwads+1; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad { // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) @@ -430,11 +430,11 @@ INT32 CL_CheckFiles(void) for (i = 0; i < fileneedednum; i++) { - if (fileneeded[i].status != FS_OPEN) //little messy, but this will count right by the time we get through the last file - filestoload++; - if (fileneeded[i].status == FS_NOTFOUND) downloadrequired = true; + + if (fileneeded[i].status == FS_FOUND || fileneeded[i].status == FS_NOTFOUND) + filestoload++; if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics continue; @@ -462,8 +462,8 @@ INT32 CL_CheckFiles(void) } //now making it here means we've checked the entire list and no FS_NOTCHECKED files remain - if (mainwads+filestoload >= MAX_WADFILES) - return 3; //ensure we wouldn't go over the wad limit + if (numwadfiles+filestoload > MAX_WADFILES) + return 3; else if (downloadrequired) return 0; //some stuff is FS_NOTFOUND, needs download else From 7da3d70f6c860a914a22c2dcec84321fb772f8ee Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 2 Jul 2020 21:48:45 -0400 Subject: [PATCH 31/57] Remove Checking Files spam --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a73df38a..13a0ab36 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1956,7 +1956,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) static boolean CL_FinishedFileList(void) { INT32 i; - CONS_Printf(M_GetText("Checking files...\n")); + //CONS_Printf(M_GetText("Checking files...\n")); i = CL_CheckFiles(); if (i == 4) // still checking ... { From 2c0671d8fdd3a9c7ca1b7b1c7ceb7953ee9eb7d4 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 4 Jul 2020 01:12:38 -0400 Subject: [PATCH 32/57] Let's just ALWAYS go into ask file list mode Easier to maintain and understand a single code path Rather than switching behavior based on amount of addons --- src/d_clisrv.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 13a0ab36..cc934173 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2085,17 +2085,9 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) if (serverlist[i].info.httpsource[0]) CONS_Printf("We received a http url from the server, however it will not be used as this build lacks curl support (%s)\n", serverlist[i].info.httpsource); #endif - - D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0); - if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) - { - cl_mode = CL_ASKFULLFILELIST; - cl_lastcheckedfilecount = 0; - return true; - } - - if (!CL_FinishedFileList()) - return false; + cl_mode = CL_ASKFULLFILELIST; + cl_lastcheckedfilecount = 0; + return true; } else cl_mode = CL_ASKJOIN; // files need not be checked for the server. From 159316b15507a782db7d13fb39218d90047871cd Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 4 Jul 2020 22:25:02 -0400 Subject: [PATCH 33/57] Remove now unused ret var --- src/d_netfil.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 25825d52..3b9d9081 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -381,7 +381,6 @@ INT32 CL_CheckFiles(void) { INT32 i, j; char wadfilename[MAX_WADPATH]; - INT32 ret = 1; size_t packetsize = 0; size_t filestoload = 0; boolean downloadrequired = false; From 4c5eb0d6bc8e4fe7ca137b754ea036ca384b0860 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 9 Aug 2020 00:47:55 -0400 Subject: [PATCH 34/57] Redo logic for lots of files vs not Now new CL state for checking files so it can spread over tics whether we ask for the extended list or not --- src/d_clisrv.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index cc934173..06684f83 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1093,6 +1093,7 @@ static INT16 Consistancy(void); typedef enum { CL_SEARCHING, + CL_CHECKFILES, CL_DOWNLOADFILES, CL_ASKJOIN, CL_LOADFILES, @@ -2085,9 +2086,15 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) if (serverlist[i].info.httpsource[0]) CONS_Printf("We received a http url from the server, however it will not be used as this build lacks curl support (%s)\n", serverlist[i].info.httpsource); #endif - cl_mode = CL_ASKFULLFILELIST; - cl_lastcheckedfilecount = 0; - return true; + D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0); + if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) + { + cl_mode = CL_ASKFULLFILELIST; + cl_lastcheckedfilecount = 0; + return true; + } + + cl_mode = CL_CHECKFILES; } else cl_mode = CL_ASKJOIN; // files need not be checked for the server. @@ -2140,10 +2147,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic case CL_ASKFULLFILELIST: if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved - { - if (!CL_FinishedFileList()) - return false; - } + cl_mode = CL_CHECKFILES; else if (fileneedednum != cl_lastcheckedfilecount || *asksent + NEWTICRATE < I_GetTime()) { if (CL_AskFileList(fileneedednum)) @@ -2153,6 +2157,10 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic } } break; + case CL_CHECKFILES: + if (!CL_FinishedFileList()) + return false; + break; #ifdef HAVE_CURL case CL_PREPAREHTTPFILES: From cc78ef2c7845656ad44cbaedb43c6e61bf3ffa21 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sun, 9 Aug 2020 00:48:53 -0400 Subject: [PATCH 35/57] Now that the server doesn't erroneously send the last mainwad As the first part of fileneeded, we must load file 0 --- src/d_netfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 3b9d9081..6bdeab4b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -477,7 +477,7 @@ boolean CL_LoadServerFiles(void) // if (M_CheckParm("-nofiles")) // return; - for (i = 1; i < fileneedednum; i++) + for (i = 0; i < fileneedednum; i++) { if (fileneeded[i].status == FS_OPEN) continue; // Already loaded From a7720967575e689bc6ae45e39c7fc3e960f6434f Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Aug 2020 08:25:12 -0700 Subject: [PATCH 36/57] dumbass doesn't test changes before pushing directly to next (cherry picked from commit be14b8a564a89a5afb84ac19f1586f3db7f68367) --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 51e47781..cbb0fa20 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,7 +100,6 @@ set(SRB2_CORE_HEADERS m_swap.h md5.h mserv.h - http-mserv.h p5prof.h s_sound.h screen.h From f800159bb8a9e2d5f94ae08df86fde54b41dad7b Mon Sep 17 00:00:00 2001 From: Ashnal Date: Sat, 15 Aug 2020 01:03:45 -0400 Subject: [PATCH 37/57] Improve total downloads bar Now has total file size AND number of files --- src/d_clisrv.c | 26 +++++++++++++++++++++++--- src/d_netfil.c | 5 +++++ src/d_netfil.h | 2 ++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 06684f83..186848fc 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1255,6 +1255,7 @@ static inline void CL_DrawConnectionStatus(void) INT32 dldlength; INT32 totalfileslength; + UINT32 totaldldsize; static char tempname[28]; fileneeded_t *file = &fileneeded[lastfilenum]; char *filename = file->filename; @@ -1292,13 +1293,27 @@ static inline void CL_DrawConnectionStatus(void) va("%3.1fK/s ", ((double)getbps)/1024)); // Download progress + + if (fileneeded[lastfilenum].currentsize != fileneeded[lastfilenum].totalsize) + totaldldsize = downloadcompletedsize+fileneeded[lastfilenum].currentsize; //Add in single file progress download if applicable + else + totaldldsize = downloadcompletedsize; + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Overall Download Progress"); - totalfileslength = (INT32)((downloadcompletednum/(double)totalfilesrequestednum) * 256); + totalfileslength = (INT32)((totaldldsize/(double)totalfilesrequestedsize) * 256); M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %2u/%2u Files",downloadcompletednum,totalfilesrequestednum)); + + if (totalfilesrequestedsize>>20 >= 100) //display in MB if over 100MB + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %4uM/%4uM",totaldldsize>>20,totalfilesrequestedsize>>20)); + else + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",totaldldsize>>10,totalfilesrequestedsize>>10)); + + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va("%2u/%2u Files ",downloadcompletednum,totalfilesrequestednum)); } else { @@ -2018,7 +2033,9 @@ static boolean CL_FinishedFileList(void) } downloadcompletednum = 0; + downloadcompletedsize = 0; totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; if (CL_SendRequestFile()) { cl_mode = CL_DOWNLOADFILES; @@ -2165,7 +2182,9 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic #ifdef HAVE_CURL case CL_PREPAREHTTPFILES: downloadcompletednum = 0; + downloadcompletedsize = 0; totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; if (http_source[0]) { for (i = 0; i < fileneedednum; i++) @@ -2173,6 +2192,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic { curl_transfers++; totalfilesrequestednum++; + totalfilesrequestedsize += fileneeded[i].totalsize; } cl_mode = CL_DOWNLOADHTTPFILES; diff --git a/src/d_netfil.c b/src/d_netfil.c index 6bdeab4b..0a2b1579 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -109,7 +109,9 @@ char downloaddir[512] = "DOWNLOAD"; // for cl loading screen INT32 lastfilenum = -1; INT32 downloadcompletednum = 0; +UINT32 downloadcompletedsize = 0; INT32 totalfilesrequestednum = 0; +UINT32 totalfilesrequestedsize = 0; #endif #ifdef HAVE_CURL @@ -333,6 +335,7 @@ boolean CL_SendRequestFile(void) strcatbf(fileneeded[i].filename, downloaddir, "/"); fileneeded[i].status = FS_REQUESTED; totalfilesrequestednum++; + totalfilesrequestedsize += fileneeded[i].totalsize; } WRITEUINT8(p, 0xFF); I_GetDiskFreeSpace(&availablefreespace); @@ -874,6 +877,7 @@ void Got_Filetxpak(void) CONS_Printf(M_GetText("Downloading %s...(done)\n"), filename); downloadcompletednum++; + downloadcompletedsize += file->totalsize; } } else @@ -1186,6 +1190,7 @@ void CURLGetFile(void) nameonly(curl_realname); CONS_Printf(M_GetText("Finished downloading %s\n"), curl_realname); downloadcompletednum++; + downloadcompletedsize += curl_curfile->totalsize; curl_curfile->status = FS_FOUND; fclose(curl_curfile->file); } diff --git a/src/d_netfil.h b/src/d_netfil.h index 58ee8b7e..905364e3 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -54,7 +54,9 @@ extern char downloaddir[512]; #ifdef CLIENT_LOADINGSCREEN extern INT32 lastfilenum; extern INT32 downloadcompletednum; +extern UINT32 downloadcompletedsize; extern INT32 totalfilesrequestednum; +extern UINT32 totalfilesrequestedsize; #endif #ifdef HAVE_CURL From 1bfcec92426891f5bcde737a621a4bda74f3f87f Mon Sep 17 00:00:00 2001 From: Kimberly Wilber Date: Sat, 15 Aug 2020 12:09:41 -0400 Subject: [PATCH 38/57] [OSX] Fix "SIGILL: illegal instruction" on macOS Catalina on OSX, strncpy may copy to overlapping (protected) memory. this sometimes happens when loading WAD files. This patch eliminates these problems for me --- src/w_wad.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/w_wad.c b/src/w_wad.c index 7fd7ac12..77d0d6d2 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -150,7 +150,10 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) { FILE *handle; - strncpy(filenamebuf, *filename, MAX_WADPATH); + if (filenamebuf != *filename) { + // avoid overlap + strncpy(filenamebuf, *filename, MAX_WADPATH); + } filenamebuf[MAX_WADPATH - 1] = '\0'; *filename = filenamebuf; From df0cc6a7271259b3d2a7bcd52a454e9d234248c2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 16 Aug 2020 21:18:33 -0400 Subject: [PATCH 39/57] No previous prototype for K_DropKitchenSink --- src/k_kart.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.h b/src/k_kart.h index e6241f8a..79606540 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -56,6 +56,7 @@ INT32 K_GetKartDriftSparkValue(player_t *player); void K_KartUpdatePosition(player_t *player); void K_DropItems(player_t *player); void K_DropRocketSneaker(player_t *player); +void K_DropKitchenSink(player_t *player); void K_StripItems(player_t *player); void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); From 5dc3ca393483aa20ff558558f684a254a1dce883 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 16 Aug 2020 20:39:46 -0700 Subject: [PATCH 40/57] Remove HAVE_CURL guards on sending httpsource --- src/d_clisrv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c4df72f5..20418809 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1309,10 +1309,8 @@ static boolean CL_SendJoin(void) static void SV_SendServerInfo(INT32 node, tic_t servertime) { UINT8 *p; -#ifdef HAVE_CURL size_t mirror_length; const char *httpurl = cv_httpsource.string; -#endif netbuffer->packettype = PT_SERVERINFO; netbuffer->u.serverinfo._255 = 255; @@ -1401,7 +1399,6 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.actnum = 0; //mapheaderinfo[gamemap-1]->actnum -#ifdef HAVE_CURL mirror_length = strlen(httpurl); if (mirror_length > MAX_MIRROR_LENGTH) mirror_length = MAX_MIRROR_LENGTH; @@ -1411,7 +1408,6 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) strncpy(netbuffer->u.serverinfo.httpsource, "", mirror_length); netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0'; -#endif p = PutFileNeeded(0); From 7a05a8acf73ac0f012135339447c9a935e3b7939 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 16 Aug 2020 21:42:58 -0700 Subject: [PATCH 41/57] Do not do master server things when NOCURL --- src/d_clisrv.c | 21 ++++++++++++---- src/doomdef.h | 6 +++++ src/http-mserv.c | 8 ++++++ src/m_menu.c | 27 +++++++++++++------- src/mserv.c | 65 ++++++++++++++++++++++++++++++++---------------- 5 files changed, 91 insertions(+), 36 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c4df72f5..9e399ce7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1824,7 +1824,7 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) M_SortServerList(); } -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) struct Fetch_servers_ctx { int room; @@ -1869,7 +1869,7 @@ Fetch_servers_thread (struct Fetch_servers_ctx *ctx) free(ctx); } -#endif/*HAVE_THREADS*/ +#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ void CL_QueryServerList (msg_server_t *server_list) { @@ -1906,9 +1906,8 @@ void CL_QueryServerList (msg_server_t *server_list) void CL_UpdateServerList(boolean internetsearch, INT32 room) { -#ifdef HAVE_THREADS - struct Fetch_servers_ctx *ctx; -#endif + (void)internetsearch; + (void)room; SL_ClearServerList(0); @@ -1925,9 +1924,12 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) if (netgame) SendAskInfo(BROADCASTADDR); +#ifdef MASTERSERVER if (internetsearch) { #ifdef HAVE_THREADS + struct Fetch_servers_ctx *ctx; + ctx = malloc(sizeof *ctx); /* This called from M_Refresh so I don't use a mutex */ @@ -1954,6 +1956,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) } #endif } +#endif/*MASTERSERVER*/ } #endif // ifndef NONET @@ -3427,8 +3430,10 @@ void D_QuitNetGame(void) for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i]) HSendPacket(i, true, 0, 0); +#ifdef MASTERSERVER if (serverrunning && ms_RoomId > 0) UnregisterServer(); +#endif } else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]) { @@ -3676,8 +3681,10 @@ boolean SV_SpawnServer(void) if (netgame && I_NetOpenSocket) { I_NetOpenSocket(); +#ifdef MASTERSERVER if (ms_RoomId > 0) RegisterServer(); +#endif } // non dedicated server just connect to itself @@ -5395,7 +5402,9 @@ FILESTAMP GetPackets(); FILESTAMP +#ifdef MASTERSERVER MasterClient_Ticker(); +#endif if (client) { @@ -5452,7 +5461,9 @@ FILESTAMP // client send the command after a receive of the server // the server send before because in single player is beter +#ifdef MASTERSERVER MasterClient_Ticker(); // Acking the Master Server +#endif if (client) { diff --git a/src/doomdef.h b/src/doomdef.h index 9ee55d94..f8eade65 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -681,4 +681,10 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Hardware renderer: OpenGL #define GL_SHADERS +#ifdef HAVE_CURL +#define MASTERSERVER +#else +#undef UPDATE_ALERT +#endif + #endif // __DOOMDEF__ diff --git a/src/http-mserv.c b/src/http-mserv.c index 9d05b80e..13c7b43d 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -14,7 +14,9 @@ Documentation available here. */ +#ifdef HAVE_CURL #include +#endif #include "doomdef.h" #include "d_clisrv.h" @@ -49,6 +51,8 @@ consvar_t cv_masterserver_token = { NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */ }; +#ifdef MASTERSERVER + static int hms_started; static char *hms_api; @@ -666,10 +670,14 @@ HMS_set_api (char *api) #endif } +#endif/*MASTERSERVER*/ + static void MasterServer_Debug_OnChange (void) { +#ifdef MASTERSERVER /* TODO: change to 'latest-log.txt' for log files revision. */ if (cv_masterserver_debug.value) CONS_Printf("Master server debug messages will appear in log.txt\n"); +#endif } diff --git a/src/m_menu.c b/src/m_menu.c index 850b8d74..3bdb78d3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3310,7 +3310,7 @@ void M_SetupNextMenu(menu_t *menudef) { INT16 i; -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef) { I_lock_mutex(&ms_QueryId_mutex); @@ -3392,7 +3392,7 @@ void M_Ticker(void) setmodeneeded = vidm_previousmode + 1; } -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) I_lock_mutex(&ms_ServerList_mutex); { if (ms_ServerList) @@ -8603,8 +8603,9 @@ static boolean M_CheckMODVersion(int id) } else return true; } +#endif/*UPDATE_ALERT*/ -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) static void Check_new_version_thread (int *id) { @@ -8613,7 +8614,9 @@ Check_new_version_thread (int *id) okay = 0; +#ifdef UPDATE_ALERT if (M_CheckMODVersion(*id)) +#endif { I_lock_mutex(&ms_QueryId_mutex); { @@ -8657,8 +8660,7 @@ Check_new_version_thread (int *id) free(id); } -#endif/*HAVE_THREADS*/ -#endif/*UPDATE_ALERT*/ +#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ static void M_ConnectMenu(INT32 choice) { @@ -8699,7 +8701,7 @@ UINT32 roomIds[NUM_LIST_ROOMS]; static void M_RoomMenu(INT32 choice) { INT32 i; -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) int *id; #endif @@ -8721,9 +8723,14 @@ static void M_RoomMenu(INT32 choice) MP_RoomDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_RoomDef); -#ifdef UPDATE_ALERT +#ifdef MASTERSERVER #ifdef HAVE_THREADS +#ifdef UPDATE_ALERT m_waiting_mode = M_WAITING_VERSION; +#else/*UPDATE_ALERT*/ + m_waiting_mode = M_WAITING_ROOMS; +#endif/*UPDATE_ALERT*/ + MP_RoomMenu[0].text = ""; id = malloc(sizeof *id); @@ -8737,17 +8744,19 @@ static void M_RoomMenu(INT32 choice) I_spawn_thread("check-new-version", (I_thread_fn)Check_new_version_thread, id); #else/*HAVE_THREADS*/ +#ifdef UPDATE_ALERT if (M_CheckMODVersion(0)) +#endif/*UPDATE_ALERT*/ { GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0); } #endif/*HAVE_THREADS*/ -#endif/*UPDATE_ALERT*/ +#endif/*MASTERSERVER*/ } static void M_ChooseRoom(INT32 choice) { -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) I_lock_mutex(&ms_QueryId_mutex); { ms_QueryId++; diff --git a/src/mserv.c b/src/mserv.c index f3d414c9..4c044fed 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -23,6 +23,8 @@ #include "m_menu.h" #include "z_zone.h" +#ifdef MASTERSERVER + static int MSId; static int MSRegisteredId = -1; @@ -43,11 +45,14 @@ static I_cond MSCond; # define Unlock_state() #endif/*HAVE_THREADS*/ -static void Update_parameters (void); - #ifndef NONET static void Command_Listserv_f(void); #endif + +#endif/*MASTERSERVER*/ + +static void Update_parameters (void); + static void MasterServer_OnChange(void); static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { @@ -63,7 +68,7 @@ consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SA INT16 ms_RoomId = -1; -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) int ms_QueryId; I_mutex ms_QueryId_mutex; @@ -91,10 +96,14 @@ void AddMServCommands(void) CV_RegisterVar(&cv_masterserver_debug); CV_RegisterVar(&cv_masterserver_token); CV_RegisterVar(&cv_servername); +#ifdef MASTERSERVER COM_AddCommand("listserv", Command_Listserv_f); #endif +#endif } +#ifdef MASTERSERVER + static void WarnGUI (void) { #ifdef HAVE_THREADS @@ -395,6 +404,7 @@ Change_masterserver_thread (char *api) void RegisterServer(void) { +#ifdef MASTERSERVER #ifdef HAVE_THREADS I_spawn_thread( "register-server", @@ -404,6 +414,7 @@ void RegisterServer(void) #else Finish_registration(); #endif +#endif/*MASTERSERVER*/ } static void UpdateServer(void) @@ -421,6 +432,7 @@ static void UpdateServer(void) void UnregisterServer(void) { +#ifdef MASTERSERVER #ifdef HAVE_THREADS I_spawn_thread( "unlist-server", @@ -430,6 +442,7 @@ void UnregisterServer(void) #else Finish_unlist(); #endif +#endif/*MASTERSERVER*/ } static boolean @@ -465,9 +478,33 @@ static inline void SendPingToMasterServer(void) } } +void MasterClient_Ticker(void) +{ +#ifdef MASTERSERVER + SendPingToMasterServer(); +#endif +} + +static void +Set_api (const char *api) +{ +#ifdef HAVE_THREADS + I_spawn_thread( + "change-masterserver", + (I_thread_fn)Change_masterserver_thread, + strdup(api) + ); +#else + HMS_set_api(strdup(api)); +#endif +} + +#endif/*MASTERSERVER*/ + static void Update_parameters (void) { +#ifdef MASTERSERVER int registered; int delayed; @@ -487,29 +524,12 @@ Update_parameters (void) if (! delayed && registered) UpdateServer(); } -} - -void MasterClient_Ticker(void) -{ - SendPingToMasterServer(); -} - -static void -Set_api (const char *api) -{ -#ifdef HAVE_THREADS - I_spawn_thread( - "change-masterserver", - (I_thread_fn)Change_masterserver_thread, - strdup(api) - ); -#else - HMS_set_api(strdup(api)); -#endif +#endif/*MASTERSERVER*/ } static void MasterServer_OnChange(void) { +#ifdef MASTERSERVER UnregisterServer(); /* @@ -527,4 +547,5 @@ static void MasterServer_OnChange(void) if (Online()) RegisterServer(); +#endif/*MASTERSERVER*/ } From 9a9d81bbe0c4e57e52db7e5eb61319ac5f36d1af Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 17 Aug 2020 03:47:23 -0400 Subject: [PATCH 42/57] New message boxes for downloads and full server waiting Downloads must be confirmed before proceeding Allows downloading mods for full servers Client will wait for a slot to open on a full server to join This has a 5 minute timeout --- src/d_clisrv.c | 212 +++++++++++++++++++++++++++++++++++++++---------- src/d_netfil.c | 4 +- 2 files changed, 170 insertions(+), 46 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 186848fc..3d910d9e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -141,6 +141,9 @@ char connectedservername[MAXSERVERNAME]; /// \todo WORK! boolean acceptnewnode = true; +boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not +tic_t firstconnectattempttime = 0; + // engine // Must be a power of two @@ -1104,6 +1107,7 @@ typedef enum CL_CONNECTED, CL_ABORTED, CL_ASKFULLFILELIST, + CL_CONFIRMCONNECT, #ifdef HAVE_CURL CL_PREPAREHTTPFILES, CL_DOWNLOADHTTPFILES, @@ -1204,14 +1208,22 @@ static inline void CL_DrawConnectionStatus(void) break; #endif case CL_ASKFULLFILELIST: + case CL_CHECKFILES: cltext = M_GetText("Checking server addon list ..."); break; + case CL_CONFIRMCONNECT: + cltext = ""; + break; case CL_LOADFILES: cltext = M_GetText("Loading server addons..."); break; case CL_ASKJOIN: case CL_WAITJOINRESPONSE: - cltext = M_GetText("Requesting to join..."); + if (serverisfull) + cltext = M_GetText("Server full, waiting for a slot..."); + else + cltext = M_GetText("Requesting to join..."); + break; #ifdef HAVE_CURL case CL_PREPAREHTTPFILES: @@ -1969,9 +1981,42 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif // ifndef NONET +static void M_ConfirmConnect(INT32 ch) +{ + if (ch == ' ' || ch == 'y' || ch == KEY_ENTER) + { + if (totalfilesrequestednum > 0) + { +#ifdef HAVE_CURL + if (http_source[0] == '\0' || curl_failedwebdownload) +#endif + { + if (CL_SendRequestFile()) + { + cl_mode = CL_DOWNLOADFILES; + } + } +#ifdef HAVE_CURL + else + cl_mode = CL_PREPAREHTTPFILES; +#endif + } + else + cl_mode = CL_LOADFILES; + + M_ClearMenus(true); + } + else if (ch == 'n' || ch == KEY_ESCAPE) + { + cl_mode = CL_ABORTED; + M_ClearMenus(true); + } +} + static boolean CL_FinishedFileList(void) { INT32 i; + char *downloadsize; //CONS_Printf(M_GetText("Checking files...\n")); i = CL_CheckFiles(); if (i == 4) // still checking ... @@ -2007,7 +2052,21 @@ static boolean CL_FinishedFileList(void) return false; } else if (i == 1) - cl_mode = CL_LOADFILES; + { + if (serverisfull) + { + M_StartMessage(M_GetText( + "This server is full!\n" + "\n" + "You may load server addons (if any), and wait for a slot.\n" + "\n" + "Press ACCEL to continue or BRAKE to cancel.\n\n" + ), M_ConfirmConnect, MM_YESNO); + cl_mode = CL_CONFIRMCONNECT; + } + else + cl_mode = CL_LOADFILES; + } else { // must download something @@ -2031,20 +2090,55 @@ static boolean CL_FinishedFileList(void) ), NULL, MM_NOTHING); return false; } + } +#ifdef HAVE_CURL + if (!curl_failedwebdownload) +#endif + { downloadcompletednum = 0; downloadcompletedsize = 0; totalfilesrequestednum = 0; totalfilesrequestedsize = 0; - if (CL_SendRequestFile()) - { - cl_mode = CL_DOWNLOADFILES; - } + + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) + { + totalfilesrequestednum++; + totalfilesrequestedsize += fileneeded[i].totalsize; + } + + if (totalfilesrequestedsize>>20 >= 100) + downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20)); + else + downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10)); + + if (serverisfull) + M_StartMessage(va(M_GetText( + "This server is full!\n" + "Download of %s additional content is required to join.\n" + "\n" + "You may download, load server addons, and wait for a slot.\n" + "\n" + "Press ACCEL to continue or BRAKE to cancel.\n\n" + ), downloadsize), M_ConfirmConnect, MM_YESNO); + else + M_StartMessage(va(M_GetText( + "Download of %s additional content is required to join.\n" + "\n" + "Press ACCEL to continue or BRAKE to cancel.\n\n" + ), downloadsize), M_ConfirmConnect, MM_YESNO); + + Z_Free(downloadsize); + cl_mode = CL_CONFIRMCONNECT; } #ifdef HAVE_CURL else { - cl_mode = CL_PREPAREHTTPFILES; + if (CL_SendRequestFile()) + { + cl_mode = CL_DOWNLOADFILES; + } } #endif } @@ -2085,11 +2179,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) // Quit here rather than downloading files and being refused later. if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer) { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); - return false; + serverisfull = true; } if (client) @@ -2150,7 +2240,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic { boolean waitmore; INT32 i; - + #ifdef NONET (void)tmpsave; #endif @@ -2178,21 +2268,14 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic if (!CL_FinishedFileList()) return false; break; - #ifdef HAVE_CURL case CL_PREPAREHTTPFILES: - downloadcompletednum = 0; - downloadcompletedsize = 0; - totalfilesrequestednum = 0; - totalfilesrequestedsize = 0; if (http_source[0]) { for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) { curl_transfers++; - totalfilesrequestednum++; - totalfilesrequestedsize += fileneeded[i].totalsize; } cl_mode = CL_DOWNLOADHTTPFILES; @@ -2218,19 +2301,13 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic if (curl_failedwebdownload && !curl_transfers) { - if (!CL_FinishedFileList()) - break; - CONS_Printf("One or more files failed to download, falling back to internal downloader\n"); - if (CL_SendRequestFile()) - { - cl_mode = CL_DOWNLOADFILES; - break; - } + cl_mode = CL_CHECKFILES; + break; } if (!curl_transfers) - cl_mode = CL_LOADFILES; // don't break case continue to cljoin request now + cl_mode = CL_LOADFILES; break; #endif @@ -2246,22 +2323,49 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic if (waitmore) break; // exit the case - cl_mode = CL_LOADFILES; // don't break case continue to cljoin request now + cl_mode = CL_LOADFILES; break; case CL_LOADFILES: - if (!CL_LoadServerFiles()) - break; + if (CL_LoadServerFiles()) + { + *asksent = I_GetTime() - (NEWTICRATE*5); //This ensure the first join ask is right away + firstconnectattempttime = I_GetTime(); + cl_mode = CL_ASKJOIN; + } + break; case CL_ASKJOIN: + if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime()) + { + CONS_Printf(M_GetText("5 minute wait time exceeded.\n")); + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "5 minute wait time exceeded.\n" + "You may retry connection.\n" + "\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + } #ifdef JOININGAME // prepare structures to save the file // WARNING: this can be useless in case of server not in GS_LEVEL // but since the network layer doesn't provide ordered packets... CL_PrepareDownloadSaveGame(tmpsave); #endif - if (CL_SendJoin()) + if ((*asksent + NEWTICRATE*3) < I_GetTime() && CL_SendJoin()) + { + *asksent = I_GetTime(); cl_mode = CL_WAITJOINRESPONSE; + } + break; + case CL_WAITJOINRESPONSE: + if ((*asksent + NEWTICRATE*3) < I_GetTime()) + { + cl_mode = CL_ASKJOIN; + } break; - #ifdef JOININGAME case CL_DOWNLOADSAVEGAME: // At this state, the first (and only) needed file is the gamestate @@ -2270,13 +2374,13 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic // Gamestate is now handled within CL_LoadReceivedSavegame() CL_LoadReceivedSavegame(); cl_mode = CL_CONNECTED; + break; } // don't break case continue to CL_CONNECTED else break; #endif - - case CL_WAITJOINRESPONSE: case CL_CONNECTED: + case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect default: break; @@ -2297,9 +2401,13 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic INT32 key; I_OsPolling(); + + if (cl_mode == CL_CONFIRMCONNECT) + D_ProcessEvents(); //needed for menu system to receive inputs + key = I_GetKey(); // Only ESC and non-keyboard keys abort connection - if (key == KEY_ESCAPE || key >= KEY_MOUSE1) + if (key == KEY_ESCAPE || key >= KEY_MOUSE1 || cl_mode == CL_ABORTED) { CONS_Printf(M_GetText("Network game synchronization aborted.\n")); D_QuitNetGame(); @@ -2316,6 +2424,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic F_TitleScreenTicker(true); F_TitleScreenDrawer(); CL_DrawConnectionStatus(); + M_Drawer(); //Needed for drawing messageboxes on the connection screen I_UpdateNoVsync(); // page flip or blit buffer if (moviemode) M_SaveFrame(); @@ -2824,6 +2933,12 @@ void CL_Reset(void) fileneedednum = 0; memset(fileneeded, 0, sizeof(fileneeded)); + totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; + firstconnectattempttime = 0; + serverisfull = false; + connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack + #ifdef HAVE_CURL curl_failedwebdownload = false; curl_transfers = 0; @@ -3746,7 +3861,7 @@ void SV_StopServer(void) D_Clearticcmd(i); consoleplayer = 0; - cl_mode = CL_SEARCHING; + cl_mode = CL_ABORTED; maketic = gametic+1; neededtic = maketic; serverrunning = false; @@ -3772,7 +3887,7 @@ static void SV_SendRefuse(INT32 node, const char *reason) strcpy(netbuffer->u.serverrefuse.reason, reason); netbuffer->packettype = PT_SERVERREFUSE; - HSendPacket(node, true, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); + HSendPacket(node, false, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); Net_CloseConnection(node); } @@ -4044,13 +4159,24 @@ static void HandlePacketFromAwayNode(SINT8 node) if (!reason) I_Error("Out of memory!\n"); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); + if (strstr(reason, "Maximum players reached")) + { + serverisfull = true; + //Special timeout for when refusing due to player cap. The client will wait 3 seconds between join requests when waiting for a slot, so we need this to be much longer + //We set it back to the value of cv_nettimeout.value in CL_Reset + connectiontimeout = NEWTICRATE*7; + cl_mode = CL_ASKJOIN; + free(reason); + break; + } M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), reason), NULL, MM_NOTHING); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + free(reason); // Will be reset by caller. Signals refusal. @@ -4070,7 +4196,7 @@ static void HandlePacketFromAwayNode(SINT8 node) } SERVERONLY /// \note how would this happen? and is it doing the right thing if it does? - if (cl_mode != CL_WAITJOINRESPONSE) + if (!(cl_mode == CL_WAITJOINRESPONSE || cl_mode == CL_ASKJOIN)) break; if (client) diff --git a/src/d_netfil.c b/src/d_netfil.c index 0a2b1579..eca0db69 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -334,8 +334,6 @@ boolean CL_SendRequestFile(void) // put it in download dir strcatbf(fileneeded[i].filename, downloaddir, "/"); fileneeded[i].status = FS_REQUESTED; - totalfilesrequestednum++; - totalfilesrequestedsize += fileneeded[i].totalsize; } WRITEUINT8(p, 0xFF); I_GetDiskFreeSpace(&availablefreespace); @@ -432,7 +430,7 @@ INT32 CL_CheckFiles(void) for (i = 0; i < fileneedednum; i++) { - if (fileneeded[i].status == FS_NOTFOUND) + if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_FALLBACK) downloadrequired = true; if (fileneeded[i].status == FS_FOUND || fileneeded[i].status == FS_NOTFOUND) From afc6bdbc7ee5567ddf3a1981e7bccea45ad9e3ec Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 17 Aug 2020 03:51:19 -0400 Subject: [PATCH 43/57] Fixes for file accounting mainwads+1 to not use the first mainwad --- src/d_netfil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index eca0db69..fd28413b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -401,7 +401,7 @@ INT32 CL_CheckFiles(void) if (modifiedgame) { CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); - for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;) + for (i = 0, j = mainwads+1; i < fileneedednum || j < numwadfiles;) { if (j < numwadfiles && !wadfiles[j]->important) { @@ -442,7 +442,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = mainwads; wadfiles[j]; j++) + for (j = mainwads+1; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && From 03150e5fe6998ac6beeb1cf600057326465894b1 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 17 Aug 2020 03:56:13 -0400 Subject: [PATCH 44/57] Move declaration to appease C90 also remove some extra tab characters --- src/d_clisrv.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3d910d9e..bb3fb3e1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1241,15 +1241,16 @@ static inline void CL_DrawConnectionStatus(void) if (cl_mode == CL_LOADFILES) { INT32 totalfileslength; + INT32 loadcompletednum = 0; + INT32 i; + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); //ima just count files here - INT32 loadcompletednum = 0; - INT32 i; for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_OPEN) loadcompletednum++; - + // Loading progress V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Loading server addons..."); totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256); @@ -1279,8 +1280,6 @@ static inline void CL_DrawConnectionStatus(void) V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, 256, 8, 175); V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, dldlength, 8, 160); - - memset(tempname, 0, sizeof(tempname)); // offset filename to just the name only part filename += strlen(filename) - nameonlylength(filename); @@ -1323,7 +1322,7 @@ static inline void CL_DrawConnectionStatus(void) else V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, va(" %4uK/%4uK",totaldldsize>>10,totalfilesrequestedsize>>10)); - + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, va("%2u/%2u Files ",downloadcompletednum,totalfilesrequestednum)); } From eb81bea943e2b6028332de2362c65907abcd7924 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 17 Aug 2020 04:03:02 -0400 Subject: [PATCH 45/57] Move code down so declarations are above to appease C90 --- src/d_clisrv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bb3fb3e1..2212a64b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1262,10 +1262,6 @@ static inline void CL_DrawConnectionStatus(void) } else if (lastfilenum != -1) { - // Draw the bottom box. - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press ESC to abort"); - INT32 dldlength; INT32 totalfileslength; UINT32 totaldldsize; @@ -1273,6 +1269,10 @@ static inline void CL_DrawConnectionStatus(void) fileneeded_t *file = &fileneeded[lastfilenum]; char *filename = file->filename; + // Draw the bottom box. + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-58-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-14, V_YELLOWMAP, "Press ESC to abort"); + Net_GetNetStat(); dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); if (dldlength > 256) From 7c5740d98f1d304576f09cac0170e8dc0838392b Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 19 Aug 2020 18:01:56 -0400 Subject: [PATCH 46/57] COnfirm box now respects rebindable accelerate and brake on keyboards --- src/d_clisrv.c | 53 ++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2212a64b..5b02fc5e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1980,35 +1980,38 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif // ifndef NONET -static void M_ConfirmConnect(INT32 ch) +static void M_ConfirmConnect(event_t *ev) { - if (ch == ' ' || ch == 'y' || ch == KEY_ENTER) + if (ev->type == ev_keydown) { - if (totalfilesrequestednum > 0) + if (ev->data1 == ' ' || ev->data1 == 'y' || ev->data1 == KEY_ENTER || ev->data1 == gamecontrol[gc_accelerate][0] || ev->data1 == gamecontrol[gc_accelerate][1]) { -#ifdef HAVE_CURL - if (http_source[0] == '\0' || curl_failedwebdownload) -#endif + if (totalfilesrequestednum > 0) { - if (CL_SendRequestFile()) - { - cl_mode = CL_DOWNLOADFILES; - } - } #ifdef HAVE_CURL - else - cl_mode = CL_PREPAREHTTPFILES; + if (http_source[0] == '\0' || curl_failedwebdownload) #endif + { + if (CL_SendRequestFile()) + { + cl_mode = CL_DOWNLOADFILES; + } + } +#ifdef HAVE_CURL + else + cl_mode = CL_PREPAREHTTPFILES; +#endif + } + else + cl_mode = CL_LOADFILES; + + M_ClearMenus(true); + } + else if (ev->data1 == 'n' || ev->data1 == KEY_ESCAPE|| ev->data1 == gamecontrol[gc_brake][0] || ev->data1 == gamecontrol[gc_brake][1]) + { + cl_mode = CL_ABORTED; + M_ClearMenus(true); } - else - cl_mode = CL_LOADFILES; - - M_ClearMenus(true); - } - else if (ch == 'n' || ch == KEY_ESCAPE) - { - cl_mode = CL_ABORTED; - M_ClearMenus(true); } } @@ -2060,7 +2063,7 @@ static boolean CL_FinishedFileList(void) "You may load server addons (if any), and wait for a slot.\n" "\n" "Press ACCEL to continue or BRAKE to cancel.\n\n" - ), M_ConfirmConnect, MM_YESNO); + ), M_ConfirmConnect, MM_EVENTHANDLER); cl_mode = CL_CONFIRMCONNECT; } else @@ -2120,13 +2123,13 @@ static boolean CL_FinishedFileList(void) "You may download, load server addons, and wait for a slot.\n" "\n" "Press ACCEL to continue or BRAKE to cancel.\n\n" - ), downloadsize), M_ConfirmConnect, MM_YESNO); + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); else M_StartMessage(va(M_GetText( "Download of %s additional content is required to join.\n" "\n" "Press ACCEL to continue or BRAKE to cancel.\n\n" - ), downloadsize), M_ConfirmConnect, MM_YESNO); + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); Z_Free(downloadsize); cl_mode = CL_CONFIRMCONNECT; From cadb4719cfb958b60be85256768ad5b63784a31f Mon Sep 17 00:00:00 2001 From: Ashnal Date: Wed, 19 Aug 2020 19:52:24 -0400 Subject: [PATCH 47/57] Added m_menu_mutex to M_Drawer in connection screen --- src/d_clisrv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6b8c107b..3a7626ef 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2484,7 +2484,13 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic F_TitleScreenTicker(true); F_TitleScreenDrawer(); CL_DrawConnectionStatus(); +#ifdef HAVE_THREADS + I_lock_mutex(&m_menu_mutex); +#endif M_Drawer(); //Needed for drawing messageboxes on the connection screen +#ifdef HAVE_THREADS + I_unlock_mutex(m_menu_mutex); +#endif I_UpdateNoVsync(); // page flip or blit buffer if (moviemode) M_SaveFrame(); From 1cd7c3b74764af1bf46e8a81376012dc719ae918 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 19 Aug 2020 17:47:07 -0700 Subject: [PATCH 48/57] Rearrange time comparsion on asksent to make it underflow friendly This fixes '-connect'. NEWTICRATE*5 is subtracted from asksent after CL_LOADFILES. If this happens too early, an underflow will occur. --- src/d_clisrv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3a7626ef..e947964c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2414,14 +2414,14 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic // but since the network layer doesn't provide ordered packets... CL_PrepareDownloadSaveGame(tmpsave); #endif - if ((*asksent + NEWTICRATE*3) < I_GetTime() && CL_SendJoin()) + if (( I_GetTime() - NEWTICRATE*3 ) >= *asksent && CL_SendJoin()) { *asksent = I_GetTime(); cl_mode = CL_WAITJOINRESPONSE; } break; case CL_WAITJOINRESPONSE: - if ((*asksent + NEWTICRATE*3) < I_GetTime()) + if (( I_GetTime() - NEWTICRATE*3 ) >= *asksent && CL_SendJoin()) { cl_mode = CL_ASKJOIN; } From 65968f00d3c0ef69fa3d0304fe70ec51651ee6bd Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 19 Aug 2020 17:55:01 -0700 Subject: [PATCH 49/57] Fix tiny mistake with the last commit --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e947964c..929a992c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2421,7 +2421,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } break; case CL_WAITJOINRESPONSE: - if (( I_GetTime() - NEWTICRATE*3 ) >= *asksent && CL_SendJoin()) + if (( I_GetTime() - NEWTICRATE*3 ) >= *asksent) { cl_mode = CL_ASKJOIN; } From b1f5e66a2306397d6988f7b89e40a6fc30230e13 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 18 Dec 2019 15:34:55 -0800 Subject: [PATCH 50/57] Use a random port when connecting (cherry picked from commit f584b61c93a97e1a9852f306acba673ced21e03a) --- src/d_net.h | 2 ++ src/i_tcp.c | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/d_net.h b/src/d_net.h index cc80fcaa..607f3e90 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -43,6 +43,8 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game +extern boolean serverrunning; + INT32 Net_GetFreeAcks(boolean urgent); void Net_AckTicker(void); diff --git a/src/i_tcp.c b/src/i_tcp.c index f58aa22b..74144d5e 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -924,6 +924,7 @@ static boolean UDP_Socket(void) #ifdef HAVE_IPV6 const INT32 b_ipv6 = M_CheckParm("-ipv6"); #endif + const char *serv; for (s = 0; s < mysocketses; s++) @@ -939,11 +940,16 @@ static boolean UDP_Socket(void) hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; + if (serverrunning) + serv = port_name; + else + serv = NULL;/* any port */ + if (M_CheckParm("-bindaddr")) { while (M_IsNextParm()) { - gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai); + gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -964,7 +970,7 @@ static boolean UDP_Socket(void) } else { - gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai); + gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -997,7 +1003,7 @@ static boolean UDP_Socket(void) { while (M_IsNextParm()) { - gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai); + gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); if (gaie == 0) { runp = ai; @@ -1018,7 +1024,7 @@ static boolean UDP_Socket(void) } else { - gaie = I_getaddrinfo("::", port_name, &hints, &ai); + gaie = I_getaddrinfo("::", serv, &hints, &ai); if (gaie == 0) { runp = ai; From b77541b51db50ec5f96c0b9d242d229cc5fdb46a Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 18 Dec 2019 15:43:29 -0800 Subject: [PATCH 51/57] Use a pointer for port_name Using strcpy is stupid because we don't know how long the argument would be. There's no need for a buffer anyway. (cherry picked from commit 4e321012894b2aa87e312597f19be26b30545a8b) --- src/i_tcp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 74144d5e..d7f767ba 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -246,7 +246,7 @@ static size_t numbans = 0; static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? static boolean init_tcp_driver = false; -static char port_name[8] = DEFAULTPORT; +static const char *port_name = DEFAULTPORT; #ifndef NONET @@ -1485,10 +1485,11 @@ boolean I_InitTcpNetwork(void) // Combined -udpport and -clientport into -port // As it was really redundant having two seperate parms that does the same thing { - if (M_IsNextParm()) - strcpy(port_name, M_GetNextParm()); - else - strcpy(port_name, "0"); + /* + If it's NULL, that's okay! Because then + we'll get a random port from getaddrinfo. + */ + port_name = M_GetNextParm(); } // parse network game options, From 94512c49e4139ef12e733928cd596e566e4f5142 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 18 Dec 2019 15:47:47 -0800 Subject: [PATCH 52/57] -clientport (it's back!) and -serverport, which is an alias to -port If you ever need to, you can change the client port number. (cherry picked from commit 843d9b9f0a345330d97c579e94f208eb2b65c156) --- src/i_tcp.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index d7f767ba..1f1cf4f2 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -246,7 +246,8 @@ static size_t numbans = 0; static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? static boolean init_tcp_driver = false; -static const char *port_name = DEFAULTPORT; +static const char *serverport_name = DEFAULTPORT; +static const char *clientport_name;/* any port */ #ifndef NONET @@ -941,9 +942,9 @@ static boolean UDP_Socket(void) hints.ai_protocol = IPPROTO_UDP; if (serverrunning) - serv = port_name; + serv = serverport_name; else - serv = NULL;/* any port */ + serv = clientport_name; if (M_CheckParm("-bindaddr")) { @@ -985,8 +986,8 @@ static boolean UDP_Socket(void) #ifdef HAVE_MINIUPNPC if (UPNP_support) { - I_UPnP_rem(port_name, "UDP"); - I_UPnP_add(NULL, port_name, "UDP"); + I_UPnP_rem(serverport_name, "UDP"); + I_UPnP_add(NULL, serverport_name, "UDP"); } #endif } @@ -1481,16 +1482,19 @@ boolean I_InitTcpNetwork(void) if (!I_InitTcpDriver()) return false; - if (M_CheckParm("-port")) + if (M_CheckParm("-port") || M_CheckParm("-serverport")) // Combined -udpport and -clientport into -port // As it was really redundant having two seperate parms that does the same thing + /* Sorry Steel, I'm adding these back. But -udpport is a stupid name. */ { /* If it's NULL, that's okay! Because then we'll get a random port from getaddrinfo. */ - port_name = M_GetNextParm(); + serverport_name = M_GetNextParm(); } + if (M_CheckParm("-clientport")) + clientport_name = M_GetNextParm(); // parse network game options, if (M_CheckParm("-server") || dedicated) From e3f07b33bb032a85b57001b318a3896f44b41c5e Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 19 Aug 2020 22:37:14 -0400 Subject: [PATCH 53/57] GME cleanup and fixes Just some stuff backported from SRB2 2.2, well mostly get_zlib_error function to reduce code duplication Return false if it fails to load the VGZ lump Reduce redundant calls to gme_set_equalizer Fix sometimes loading a VGZ crashing the game --- src/sdl/mixer_sound.c | 123 ++++++++++-------------------------------- 1 file changed, 29 insertions(+), 94 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 1617da2a..86fc8efb 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -110,6 +110,27 @@ static void var_cleanup(void) internal_volume = 100; } +static const char* get_zlib_error(int zErr) +{ + switch (zErr) + { + case Z_ERRNO: + return "Z_ERRNO"; + case Z_STREAM_ERROR: + return "Z_STREAM_ERROR"; + case Z_DATA_ERROR: + return "Z_DATA_ERROR"; + case Z_MEM_ERROR: + return "Z_MEM_ERROR"; + case Z_BUF_ERROR: + return "Z_BUF_ERROR"; + case Z_VERSION_ERROR: + return "Z_VERSION_ERROR"; + default: + return "unknown error"; + } +} + /// ------------------------ /// Audio System /// ------------------------ @@ -371,51 +392,11 @@ void *I_GetSfx(sfxinfo_t *sfx) } } else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up #else return NULL; // No zlib support @@ -945,73 +926,25 @@ boolean I_LoadSong(char *data, size_t len) // Run GME on new data if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100)) { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_start_track(gme, 0); - current_track = 0; - gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around return true; } } else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up + return false; #else CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); - return true; + return false; #endif } else if (!gme_open_data(data, len, &gme, 44100)) - { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_set_equalizer(gme, &eq); return true; - } #endif rw = SDL_RWFromMem(data, len); @@ -1082,6 +1015,8 @@ boolean I_PlaySong(boolean looping) #ifdef HAVE_LIBGME if (gme) { + gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; + gme_set_equalizer(gme, &eq); gme_start_track(gme, 0); current_track = 0; Mix_HookMusic(mix_gme, gme); From aa2b25e667f90c4d46e914cb191d3004f55d2546 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 20 Aug 2020 00:54:18 -0400 Subject: [PATCH 54/57] Well actually, lets fix all comparisons of askset to use the same comparison If we initialize to I_GetTime() - NEWTICRATE*3 it never underflows and everything is good --- src/d_clisrv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 929a992c..e22ab463 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2271,7 +2271,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) } // Ask the info to the server (askinfo packet) - if (*asksent + NEWTICRATE < I_GetTime()) + if ((I_GetTime() - NEWTICRATE) >= *asksent) { SendAskInfo(servernode); *asksent = I_GetTime(); @@ -2315,7 +2315,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic case CL_ASKFULLFILELIST: if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved cl_mode = CL_CHECKFILES; - else if (fileneedednum != cl_lastcheckedfilecount || *asksent + NEWTICRATE < I_GetTime()) + else if (fileneedednum != cl_lastcheckedfilecount || (I_GetTime() - NEWTICRATE) >= *asksent) { if (CL_AskFileList(fileneedednum)) { @@ -2388,7 +2388,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic case CL_LOADFILES: if (CL_LoadServerFiles()) { - *asksent = I_GetTime() - (NEWTICRATE*5); //This ensure the first join ask is right away + *asksent = I_GetTime() - (NEWTICRATE*3); //This ensure the first join ask is right away firstconnectattempttime = I_GetTime(); cl_mode = CL_ASKJOIN; } @@ -2557,7 +2557,7 @@ static void CL_ConnectToServer(void) pnumnodes = 1; oldtic = I_GetTime() - 1; #ifndef NONET - asksent = (tic_t) - TICRATE; + asksent = I_GetTime() - NEWTICRATE*3; i = SL_SearchServer(servernode); From d0d612805330f9d2cf94cdbfa50d78124531ac5b Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 20 Aug 2020 13:41:03 +0800 Subject: [PATCH 55/57] Instantaneous lookback camera (v2 backport) --- src/p_user.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 03f8f0fb..9926b980 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7487,13 +7487,14 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled) { - static UINT8 lookbackdelay[4] = {0,0,0,0}; + static boolean lookbackactive[MAXSPLITSCREENPLAYERS]; + static UINT8 lookbackdelay[MAXSPLITSCREENPLAYERS]; UINT8 num; angle_t angle = 0, focusangle = 0, focusaiming = 0; - fixed_t x, y, z, dist, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; + fixed_t x, y, z, dist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; fixed_t pan, xpan, ypan; INT32 camrotate; - boolean camstill, lookback; + boolean camstill, lookback, lookbackdown; UINT8 timeover; mobj_t *mo; fixed_t f1, f2; @@ -7684,15 +7685,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camstill = true; else if (lookback || lookbackdelay[num]) // SRB2kart - Camera flipper { +#define MAXLOOKBACKDELAY 2 camspeed = FRACUNIT; if (lookback) { camrotate += 180; - lookbackdelay[num] = 2; + lookbackdelay[num] = MAXLOOKBACKDELAY; } else lookbackdelay[num]--; } + lookbackdown = (lookbackdelay[num] == MAXLOOKBACKDELAY) != lookbackactive[num]; + lookbackactive[num] = (lookbackdelay[num] == MAXLOOKBACKDELAY); +#undef MAXLOOKBACKDELAY if (mo->eflags & MFE_VERTICALFLIP) camheight += thiscam->height; @@ -7735,8 +7740,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->angle = angle; } - height = camheight; - // sets ideal cam pos dist = camdist; @@ -7745,10 +7748,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist += abs(thiscam->momz)/4; if (player->kartstuff[k_boostcam]) - { dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]); - height -= FixedMul(height, player->kartstuff[k_boostcam]); - } x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); @@ -8070,6 +8070,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->aiming = ANGLE_22h; } + if (lookbackdown) + P_MoveChaseCamera(player, thiscam, false); + return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } From 247239c2bc6dd7298697050225111f9d9ac8fcd5 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 20 Aug 2020 23:09:12 -0400 Subject: [PATCH 56/57] Add return false to the connect timeout --- src/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e22ab463..2a138177 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2407,6 +2407,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic "\n" "Press ESC\n" ), NULL, MM_NOTHING); + return false; } #ifdef JOININGAME // prepare structures to save the file From 9e1d7146add13f9443fa36b9e9e742f93cd63986 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Thu, 20 Aug 2020 23:38:04 -0400 Subject: [PATCH 57/57] Fixed retry timeout to no ttrigger when starting a local server --- src/d_clisrv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2a138177..2441659c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2394,7 +2394,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } break; case CL_ASKJOIN: - if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime()) + if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime() && !server) { CONS_Printf(M_GetText("5 minute wait time exceeded.\n")); CONS_Printf(M_GetText("Network game synchronization aborted.\n")); @@ -2559,6 +2559,7 @@ static void CL_ConnectToServer(void) oldtic = I_GetTime() - 1; #ifndef NONET asksent = I_GetTime() - NEWTICRATE*3; + firstconnectattempttime = I_GetTime(); i = SL_SearchServer(servernode);