From aec041af072e140d7c756c7115f2872d5b33bd10 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:04:03 -0500 Subject: [PATCH 01/93] Update deh_tables.c --- src/deh_tables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5733d9b0e..1b877d4b4 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3822,6 +3822,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BIGMACE", // Big Mace "MT_SMALLGRABCHAIN", // Small Grab Chain "MT_BIGGRABCHAIN", // Big Grab Chain + "MT_BLUESPRINGBALL", // Blue spring on a ball "MT_YELLOWSPRINGBALL", // Yellow spring on a ball "MT_REDSPRINGBALL", // Red spring on a ball "MT_SMALLFIREBAR", // Small Firebar From 4da83888c9e2407f5582cb7c2cab39f92e3c0c97 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:11:31 -0500 Subject: [PATCH 02/93] Update info.c --- src/info.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/info.c b/src/info.c index 29a79b1d6..8281cb80c 100644 --- a/src/info.c +++ b/src/info.c @@ -2234,6 +2234,13 @@ state_t states[NUMSTATES] = {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGMACE {SPR_SMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLGRABCHAIN {SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGRABCHAIN + + // Blue spring on a ball + {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL + {SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3}, // S_BLUESPRINGBALL2 + {SPR_BSPB, 3, 1, {NULL}, 0, 0, S_BLUESPRINGBALL4}, // S_BLUESPRINGBALL3 + {SPR_BSPB, 2, 1, {NULL}, 0, 0, S_BLUESPRINGBALL5}, // S_BLUESPRINGBALL4 + {SPR_BSPB, 1, 1, {NULL}, 0, 0, S_BLUESPRINGBALL}, // S_BLUESPRINGBALL5 // Yellow spring on a ball {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL @@ -11511,6 +11518,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags S_NULL // raisestate }, + + { // MT_BLUESPRINGBALL + 1133, // doomednum + S_BLUESPRINGBALL, // spawnstate + 1000, // spawnhealth + S_BLUESPRINGBALL2, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_spring, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 24*FRACUNIT, // speed + 17*FRACUNIT, // radius + 34*FRACUNIT, // height + 1, // display offset + 11*FRACUNIT, // mass + 0, // damage + sfx_mswing, // activesound + MF_SCENERY|MF_SPRING|MF_NOGRAVITY, // flags + S_BLUESPRINGBALL2 // raisestate + }, { // MT_YELLOWSPRINGBALL 1134, // doomednum From 8ce067d7ebca9cb96878f902a6ec7022b2fab5f8 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:13:59 -0500 Subject: [PATCH 03/93] Update p_mobj.c --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7ba6d1fad..0fdf95155 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10379,6 +10379,7 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_SMALLGRABCHAIN: case MT_BIGGRABCHAIN: + case MT_BLUESPRINGBALL: case MT_YELLOWSPRINGBALL: case MT_REDSPRINGBALL: From 802f5ab4ea9119e4796f6ec5c96ba1a96a303f1e Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:17:13 -0500 Subject: [PATCH 04/93] Update info.h --- src/info.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/info.h b/src/info.h index 604922beb..125497644 100644 --- a/src/info.h +++ b/src/info.h @@ -779,6 +779,7 @@ typedef enum sprite SPR_BMCH, // Big Mace Chain SPR_SMCE, // Small Mace SPR_BMCE, // Big Mace + SPR_BSPB, // Blue spring on a ball SPR_YSPB, // Yellow spring on a ball SPR_RSPB, // Red spring on a ball SPR_SFBR, // Small Firebar @@ -2669,6 +2670,14 @@ typedef enum state S_SMALLGRABCHAIN, S_BIGGRABCHAIN, + // Blue spring on a ball + S_BLUESPRINGBALL, + S_BLUESPRINGBALL2, + S_BLUESPRINGBALL3, + S_BLUESPRINGBALL4, + S_BLUESPRINGBALL5, + + // Yellow spring on a ball S_YELLOWSPRINGBALL, S_YELLOWSPRINGBALL2, @@ -4644,6 +4653,7 @@ typedef enum mobj_type MT_BIGMACE, // Big Mace MT_SMALLGRABCHAIN, // Small Grab Chain MT_BIGGRABCHAIN, // Big Grab Chain + MT_BLUESPRINGBALL, // Blue spring on a ball MT_YELLOWSPRINGBALL, // Yellow spring on a ball MT_REDSPRINGBALL, // Red spring on a ball MT_SMALLFIREBAR, // Small Firebar From 3195022936adef7d3019a435f198e7eea56e5da3 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:19:32 -0500 Subject: [PATCH 05/93] Update deh_tables.c --- src/deh_tables.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index 1b877d4b4..d2087ebb0 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1867,6 +1867,13 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SMALLGRABCHAIN", "S_BIGGRABCHAIN", + // Blue spring on a ball + "S_BLUESPRINGBALL", + "S_BLUESPRINGBALL2", + "S_BLUESPRINGBALL3", + "S_BLUESPRINGBALL4", + "S_BLUESPRINGBALL5", + // Yellow spring on a ball "S_YELLOWSPRINGBALL", "S_YELLOWSPRINGBALL2", From 8fbf24d68b018eeaffc9ffca788c67f60d53b8ef Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:35:17 -0500 Subject: [PATCH 06/93] Update info.c --- src/info.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/info.c b/src/info.c index 8281cb80c..3da92bb96 100644 --- a/src/info.c +++ b/src/info.c @@ -245,6 +245,7 @@ char sprnames[NUMSPRITES + 1][5] = "BMCH", // Big Mace Chain "SMCE", // Small Mace "BMCE", // Big Mace + "BSPB", // Blue spring on a ball "YSPB", // Yellow spring on a ball "RSPB", // Red spring on a ball "SFBR", // Small Firebar From b0fe3b6b5ac3aaef0ca9ac1e84052017d73c19f7 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:36:41 -0500 Subject: [PATCH 07/93] Update hw_light.c --- src/hardware/hw_light.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 987d70c69..76fecd7aa 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -340,6 +340,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_BMCH &lspr[NOLIGHT], // SPR_SMCE &lspr[NOLIGHT], // SPR_BMCE + &lspr[NOLIGHT], // SPR_BSPB &lspr[NOLIGHT], // SPR_YSPB &lspr[NOLIGHT], // SPR_RSPB &lspr[REDBALL_L], // SPR_SFBR From 6c9b73ba29a21bed9762408a874d88c265e3a70e Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 11:53:24 -0500 Subject: [PATCH 08/93] Fixed formatting From 63c95e91867559ce062a54774e1285b839a740d4 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 11:55:03 -0500 Subject: [PATCH 09/93] Update info.c --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 3da92bb96..c53241cdf 100644 --- a/src/info.c +++ b/src/info.c @@ -2237,7 +2237,7 @@ state_t states[NUMSTATES] = {SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGRABCHAIN // Blue spring on a ball - {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL + {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL {SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3}, // S_BLUESPRINGBALL2 {SPR_BSPB, 3, 1, {NULL}, 0, 0, S_BLUESPRINGBALL4}, // S_BLUESPRINGBALL3 {SPR_BSPB, 2, 1, {NULL}, 0, 0, S_BLUESPRINGBALL5}, // S_BLUESPRINGBALL4 From 3b01da753f0cdb457ee94c5f0f3707288de7321f Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 16:17:21 -0500 Subject: [PATCH 10/93] Update p_mobj.c --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0fdf95155..ac971f5db 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10378,8 +10378,8 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_SMALLGRABCHAIN: case MT_BIGGRABCHAIN: - - case MT_BLUESPRINGBALL: + + case MT_BLUESPRINGBALL: case MT_YELLOWSPRINGBALL: case MT_REDSPRINGBALL: From 6f4117f7161a46c6b6751eb56d0e4416bcee7ade Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 16:18:54 -0500 Subject: [PATCH 11/93] Update info.h --- src/info.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/info.h b/src/info.h index 125497644..1a26922f7 100644 --- a/src/info.h +++ b/src/info.h @@ -2677,7 +2677,6 @@ typedef enum state S_BLUESPRINGBALL4, S_BLUESPRINGBALL5, - // Yellow spring on a ball S_YELLOWSPRINGBALL, S_YELLOWSPRINGBALL2, From 979ebe262bde2fbd003c9ec97a5d56254cd19c6f Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 18:03:36 -0500 Subject: [PATCH 12/93] Update info.c --- src/info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index c53241cdf..9b1c4ac55 100644 --- a/src/info.c +++ b/src/info.c @@ -2235,7 +2235,7 @@ state_t states[NUMSTATES] = {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGMACE {SPR_SMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLGRABCHAIN {SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGRABCHAIN - + // Blue spring on a ball {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL {SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3}, // S_BLUESPRINGBALL2 @@ -11519,7 +11519,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags S_NULL // raisestate }, - + { // MT_BLUESPRINGBALL 1133, // doomednum S_BLUESPRINGBALL, // spawnstate From 3f63bb1a676a0f1b0fea925651346f4659f43b52 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 18:16:22 -0500 Subject: [PATCH 13/93] Update p_mobj.c --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ac971f5db..6c7721aa1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10378,7 +10378,7 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_SMALLGRABCHAIN: case MT_BIGGRABCHAIN: - + case MT_BLUESPRINGBALL: case MT_YELLOWSPRINGBALL: case MT_REDSPRINGBALL: From 1a5f0d94f3379ed2c07e83190c140cd3246359bf Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Sat, 1 May 2021 14:05:01 -0400 Subject: [PATCH 14/93] Expose P_ThrustEvenIn2D and P_VectorInstaThrust --- src/p_user.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index c5f919c78..6a879c785 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -104,8 +104,7 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move) mo->momy += FixedMul(move, FINESINE(angle)); } -#if 0 -static inline void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move) +void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move) { angle >>= ANGLETOFINESHIFT; @@ -113,7 +112,7 @@ static inline void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move) mo->momy += FixedMul(move, FINESINE(angle)); } -static inline void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, +void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, fixed_t za, fixed_t zb, fixed_t zc, fixed_t momentum, mobj_t *mo) { fixed_t a1, b1, c1, a2, b2, c2, i, j, k; @@ -143,7 +142,6 @@ static inline void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed mo->momy = j; mo->momz = k; } -#endif // // P_InstaThrust From 47a2710ec292b551ce559813863611ef1805c3f7 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Sat, 1 May 2021 14:05:07 -0400 Subject: [PATCH 15/93] Expose P_ThrustEvenIn2D, P_InstaThrustEvenIn2D, and P_VectorInstaThrust to Lua --- src/lua_baselib.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 4667fdbf4..64c5967b8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1514,6 +1514,19 @@ static int lib_pInstaThrust(lua_State *L) return 0; } +static int lib_pInstaThrustEvenIn2D(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + angle_t angle = luaL_checkangle(L, 2); + fixed_t move = luaL_checkfixed(L, 3); + NOHUD + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + P_InstaThrustEvenIn2D(mo, angle, move); + return 0; +} + static int lib_pReturnThrustX(lua_State *L) { angle_t angle; @@ -2075,6 +2088,40 @@ static int lib_pThrust(lua_State *L) return 0; } +static int lib_pThrustEvenIn2D(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + angle_t angle = luaL_checkangle(L, 2); + fixed_t move = luaL_checkfixed(L, 3); + NOHUD + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + P_ThrustEvenIn2D(mo, angle, move); + return 0; +} + +static int lib_pVectorInstaThrust(lua_State *L) +{ + fixed_t xa = luaL_checkfixed(L, 1); + fixed_t xb = luaL_checkfixed(L, 2); + fixed_t xc = luaL_checkfixed(L, 3); + fixed_t ya = luaL_checkfixed(L, 4); + fixed_t yb = luaL_checkfixed(L, 5); + fixed_t yc = luaL_checkfixed(L, 6); + fixed_t za = luaL_checkfixed(L, 7); + fixed_t zb = luaL_checkfixed(L, 8); + fixed_t zc = luaL_checkfixed(L, 9); + fixed_t momentum = luaL_checkfixed(L, 10); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 11, META_MOBJ)); + NOHUD + INLEVEL + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + P_VectorInstaThrust(xa, xb, xc, ya, yb, yc, za, zb, zc, momentum, mo); + return 0; +} + static int lib_pSetMobjStateNF(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3853,6 +3900,7 @@ static luaL_Reg lib[] = { {"P_DoPlayerFinish",lib_pDoPlayerFinish}, {"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_InstaThrust",lib_pInstaThrust}, + {"P_InstaThrustEvenIn2D",lib_pInstaThrustEvenIn2D}, {"P_ReturnThrustX",lib_pReturnThrustX}, {"P_ReturnThrustY",lib_pReturnThrustY}, {"P_LookForEnemies",lib_pLookForEnemies}, @@ -3900,6 +3948,8 @@ static luaL_Reg lib[] = { // p_spec {"P_Thrust",lib_pThrust}, + {"P_ThrustEvenIn2D",lib_pThrustEvenIn2D}, + {"P_VectorInstaThrust",lib_pVectorInstaThrust}, {"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, From e16a8946807349c5b308e422aaf09a1f29b8252b Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Sat, 1 May 2021 20:47:01 -0400 Subject: [PATCH 16/93] Actually define newly exposed thrust functions. Oops. --- src/p_local.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_local.h b/src/p_local.h index 8a5084962..ab6ef0177 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -527,6 +527,9 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state); boolean P_CheckMissileSpawn(mobj_t *th); void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); +void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); +void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, + fixed_t za, fixed_t zb, fixed_t zc, fixed_t momentum, mobj_t *mo); void P_DoSuperTransformation(player_t *player, boolean giverings); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); From 7c75f61be74a6a152640df01bcb60d4c07fd7e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 3 Jun 2023 13:05:33 +0200 Subject: [PATCH 17/93] Fix buffer overflow when displaying a scrolling background --- src/m_menu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/m_menu.c b/src/m_menu.c index 64a1c9404..2fc0b889f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2807,6 +2807,7 @@ void M_SetMenuCurBackground(const char *defaultname) { char name[9]; strncpy(name, defaultname, 8); + name[8] = '\0'; M_IterateMenuTree(MIT_SetCurBackground, &name); } From 606797a5a4f6ec1f2af72639ac60f6744253895e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 27 Jul 2023 14:41:02 +0200 Subject: [PATCH 18/93] Temporarily revert recent netcode changes --- src/d_clisrv.c | 465 +++++++++---------------------------- src/d_clisrv.h | 10 +- src/d_net.c | 31 +-- src/d_net.h | 2 +- src/d_netcmd.c | 594 ++++++++++++++++++++++------------------------- src/d_netcmd.h | 14 +- src/d_netfil.c | 4 +- src/d_netfil.h | 2 +- src/http-mserv.c | 30 +-- src/i_addrinfo.c | 2 +- src/i_addrinfo.h | 2 +- src/i_net.h | 13 +- src/i_tcp.c | 73 ++---- src/i_tcp.h | 2 +- src/mserv.c | 10 +- src/mserv.h | 6 +- 16 files changed, 447 insertions(+), 813 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c66c8d798..3091f3344 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,7 +25,8 @@ #include "st_stuff.h" #include "hu_stuff.h" #include "keys.h" -#include "g_input.h" // JOY1 +#include "g_input.h" +#include "i_gamepad.h" #include "m_menu.h" #include "console.h" #include "d_netfil.h" @@ -33,6 +34,7 @@ #include "p_saveg.h" #include "z_zone.h" #include "p_local.h" +#include "p_haptic.h" #include "m_misc.h" #include "am_map.h" #include "m_random.h" @@ -49,7 +51,7 @@ #include "m_perfstats.h" // aaaaaa -#include "i_joy.h" +#include "i_gamepad.h" #ifndef NONET // cl loading screen @@ -120,8 +122,6 @@ UINT8 hu_redownloadinggamestate = 0; // true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks boolean hu_stopped = false; -consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); - UINT8 adminpassmd5[16]; boolean adminpasswordset = false; @@ -655,22 +655,6 @@ static UINT8 Snake_GetOppositeDir(UINT8 dir) return 12 + 5 - dir; } -event_t *snakejoyevents[MAXEVENTS]; -UINT16 joyeventcount = 0; - -// I'm screaming the hack is clean - ashi -static boolean Snake_Joy_Grabber(event_t *ev) -{ - if (ev->type == ev_joystick && ev->key == 0) - { - snakejoyevents[joyeventcount] = ev; - joyeventcount++; - return true; - } - else - return false; -} - static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) { UINT8 x, y; @@ -697,19 +681,17 @@ static void Snake_Handle(void) UINT8 x, y; UINT8 oldx, oldy; UINT16 i; - UINT16 j; UINT16 joystate = 0; - static INT32 pjoyx = 0, pjoyy = 0; // Handle retry - if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER])) + if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER])) { Snake_Initialise(); snake->pausepressed = true; // Avoid accidental pause on respawn } // Handle pause - if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER]) + if (G_PlayerInputDown(0, GC_PAUSE) || gamekeydown[KEY_ENTER]) { if (!snake->pausepressed) snake->paused = !snake->paused; @@ -728,58 +710,23 @@ static void Snake_Handle(void) oldx = snake->snakex[1]; oldy = snake->snakey[1]; - // process the input events in here dear lord - for (j = 0; j < joyeventcount; j++) - { - event_t *ev = snakejoyevents[j]; - const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT; - if (ev->y != INT32_MAX) - { - if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone) - { - if (ev->y < 0 && pjoyy >= 0) - joystate = 1; - else if (ev->y > 0 && pjoyy <= 0) - joystate = 2; - pjoyy = ev->y; - } - else - pjoyy = 0; - } - - if (ev->x != INT32_MAX) - { - if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone) - { - if (ev->x < 0 && pjoyx >= 0) - joystate = 3; - else if (ev->x > 0 && pjoyx <= 0) - joystate = 4; - pjoyx = ev->x; - } - else - pjoyx = 0; - } - } - joyeventcount = 0; - // Update direction - if (PLAYER1INPUTDOWN(GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) + if (G_PlayerInputDown(0, GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) { if (snake->snakelength < 2 || x <= oldx) snake->snakedir[0] = 1; } - else if (PLAYER1INPUTDOWN(GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) + else if (G_PlayerInputDown(0, GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) { if (snake->snakelength < 2 || x >= oldx) snake->snakedir[0] = 2; } - else if (PLAYER1INPUTDOWN(GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) + else if (G_PlayerInputDown(0, GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) { if (snake->snakelength < 2 || y <= oldy) snake->snakedir[0] = 3; } - else if (PLAYER1INPUTDOWN(GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) + else if (G_PlayerInputDown(0, GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) { if (snake->snakelength < 2 || y >= oldy) snake->snakedir[0] = 4; @@ -1295,7 +1242,6 @@ static boolean CL_AskFileList(INT32 firstfile) static boolean CL_SendJoin(void) { UINT8 localplayers = 1; - char const *player2name; if (netgame) CONS_Printf(M_GetText("Sending join request...\n")); netbuffer->packettype = PT_CLIENTJOIN; @@ -1312,23 +1258,18 @@ static boolean CL_SendJoin(void) CleanupPlayerName(consoleplayer, cv_playername.zstring); if (splitscreen) CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ - // Avoid empty string on bots to avoid softlocking in singleplayer - if (botingame) - player2name = strcmp(cv_playername.zstring, "Tails") == 0 ? "Tail" : "Tails"; - else - player2name = cv_playername2.zstring; strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); - strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); } static INT32 FindRejoinerNum(SINT8 node) { - char addressbuffer[64]; + char strippednodeaddress[64]; const char *nodeaddress; - const char *strippednodeaddress; + char *port; INT32 i; // Make sure there is no dead dress before proceeding to the stripping @@ -1339,8 +1280,10 @@ static INT32 FindRejoinerNum(SINT8 node) return -1; // Strip the address of its port - strcpy(addressbuffer, nodeaddress); - strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL); + strcpy(strippednodeaddress, nodeaddress); + port = strchr(strippednodeaddress, ':'); + if (port) + *port = '\0'; // Check if any player matches the stripped address for (i = 0; i < MAXPLAYERS; i++) @@ -1383,9 +1326,8 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); - // Exclude bots from both counts - netbuffer->u.serverinfo.numberofplayer = (UINT8)(D_NumPlayers() - D_NumBots()); - netbuffer->u.serverinfo.maxplayer = (UINT8)(cv_maxplayers.value - D_NumBots()); + netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); + netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); @@ -1512,7 +1454,6 @@ static boolean SV_SendServerConfig(INT32 node) netbuffer->u.servercfg.gamestate = (UINT8)gamestate; netbuffer->u.servercfg.gametype = (UINT8)gametype; netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; - netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats; memcpy(netbuffer->u.servercfg.server_context, server_context, 8); @@ -1711,6 +1652,8 @@ static void CL_LoadReceivedSavegame(boolean reloading) titledemo = false; automapactive = false; + P_StopRumble(NULL); + // load a base level if (P_LoadNetGame(reloading)) { @@ -1997,9 +1940,10 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) static void M_ConfirmConnect(event_t *ev) { #ifndef NONET - if (ev->type == ev_keydown) + + if (ev->type == ev_keydown || ev->type == ev_gamepad_down) { - if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER || ev->key == KEY_JOY1) + if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A)) { if (totalfilesrequestednum > 0) { @@ -2014,7 +1958,7 @@ static void M_ConfirmConnect(event_t *ev) M_ClearMenus(true); } - else if (ev->key == 'n' || ev->key == KEY_ESCAPE || ev->key == KEY_JOY1 + 3) + else if ((ev->type == ev_keydown && (ev->key == 'n' || ev->key == KEY_ESCAPE)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_B)) { cl_mode = CL_ABORTED; M_ClearMenus(true); @@ -2448,14 +2392,11 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic // my hand has been forced and I am dearly sorry for this awful hack :vomit: for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { -#ifndef NONET - if (!Snake_Joy_Grabber(&events[eventtail])) -#endif - G_MapEventsToControls(&events[eventtail]); + G_MapEventsToControls(&events[eventtail]); } } - if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED) + if (gamekeydown[KEY_ESCAPE] || gamepads[0].buttons[GAMEPAD_BUTTON_B] || cl_mode == CL_ABORTED) { CONS_Printf(M_GetText("Network game synchronization aborted.\n")); M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); @@ -2493,7 +2434,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic { if (!snake) { - F_MenuPresTicker(); // title sky + F_MenuPresTicker(true); // title sky F_TitleScreenTicker(true); F_TitleScreenDrawer(); } @@ -2608,8 +2549,6 @@ static void CL_ConnectToServer(void) } while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); - if (netgame) - F_StartWaitingPlayers(); DEBFILE(va("Synchronisation Finished\n")); displayplayer = consoleplayer; @@ -3516,10 +3455,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, maxplayers_cons_t, NULL); +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; @@ -3547,22 +3486,22 @@ void D_ClientServerInit(void) VERSION/100, VERSION%100, SUBVERSION)); #ifndef NONET - COM_AddCommand("getplayernum", Command_GetPlayerNum, COM_LUA); - COM_AddCommand("kick", Command_Kick, COM_LUA); - COM_AddCommand("ban", Command_Ban, COM_LUA); - COM_AddCommand("banip", Command_BanIP, COM_LUA); - COM_AddCommand("clearbans", Command_ClearBans, COM_LUA); - COM_AddCommand("showbanlist", Command_ShowBan, COM_LUA); - COM_AddCommand("reloadbans", Command_ReloadBan, COM_LUA); - COM_AddCommand("connect", Command_connect, COM_LUA); - COM_AddCommand("nodes", Command_Nodes, COM_LUA); - COM_AddCommand("resendgamestate", Command_ResendGamestate, COM_LUA); + COM_AddCommand("getplayernum", Command_GetPlayerNum); + COM_AddCommand("kick", Command_Kick); + COM_AddCommand("ban", Command_Ban); + COM_AddCommand("banip", Command_BanIP); + COM_AddCommand("clearbans", Command_ClearBans); + COM_AddCommand("showbanlist", Command_ShowBan); + COM_AddCommand("reloadbans", Command_ReloadBan); + COM_AddCommand("connect", Command_connect); + COM_AddCommand("nodes", Command_Nodes); + COM_AddCommand("resendgamestate", Command_ResendGamestate); #ifdef PACKETDROP - COM_AddCommand("drop", Command_Drop, COM_LUA); - COM_AddCommand("droprate", Command_Droprate, COM_LUA); + COM_AddCommand("drop", Command_Drop); + COM_AddCommand("droprate", Command_Droprate); #endif #ifdef _DEBUG - COM_AddCommand("numnodes", Command_Numnodes, COM_LUA); + COM_AddCommand("numnodes", Command_Numnodes); #endif #endif @@ -3653,9 +3592,6 @@ void SV_ResetServer(void) CV_RevertNetVars(); - // Ensure synched when creating a new server - M_CopyGameData(serverGamedata, clientGamedata); - DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } @@ -3779,13 +3715,14 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (server && I_GetNodeAddress) { - char addressbuffer[64]; const char *address = I_GetNodeAddress(node); + char *port = NULL; if (address) // MI: fix msvcrt.dll!_mbscat crash? { - strcpy(addressbuffer, address); - strcpy(playeraddress[newplayernum], - I_NetSplitAddress(addressbuffer, NULL)); + strcpy(playeraddress[newplayernum], address); + port = strchr(playeraddress[newplayernum], ':'); + if (port) + *port = '\0'; } } } @@ -4089,7 +4026,7 @@ ConnectionRefused (SINT8 node, INT32 rejoinernum) { return va( "Maximum players reached: %d", - cv_maxplayers.value - D_NumBots()); + cv_maxplayers.value); } } @@ -4417,8 +4354,6 @@ static void HandlePacketFromAwayNode(SINT8 node) maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; - if (netbuffer->u.servercfg.usedCheats) - G_SetUsedCheats(true); memcpy(server_context, netbuffer->u.servercfg.server_context, 8); } @@ -4528,7 +4463,6 @@ static void HandlePacketFromPlayer(SINT8 node) netconsole = 0; else netconsole = nodetoplayer[node]; - #ifdef PARANOIA if (netconsole >= MAXPLAYERS) I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); @@ -4567,32 +4501,21 @@ static void HandlePacketFromPlayer(SINT8 node) // Update the nettics nettics[node] = realend; - // This should probably still timeout though, as the node should always have a player 1 number - if (netconsole == -1) + // Don't do anything for packets of type NODEKEEPALIVE? + if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) break; // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? freezetimeout[node] = I_GetTime() + connectiontimeout; - // Don't do anything for packets of type NODEKEEPALIVE? - // Sryder 2018/07/01: Update the freezetimeout still! - if (netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) - break; - - // If we've alredy received a ticcmd for this tic, just submit it for the next one. - tic_t faketic = maketic; - if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) - && (maketic - firstticstosend < BACKUPTICS)) - faketic++; - // Copy ticcmd - G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); // Check ticcmd for "speed hacks" - if (netcmds[faketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[faketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) + if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE + || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) { CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); //D_Clearticcmd(k); @@ -4604,10 +4527,9 @@ static void HandlePacketFromPlayer(SINT8 node) // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); - // Check player consistancy during the level if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) @@ -4644,21 +4566,6 @@ static void HandlePacketFromPlayer(SINT8 node) } } break; - case PT_BASICKEEPALIVE: - if (client) - break; - - // This should probably still timeout though, as the node should always have a player 1 number - if (netconsole == -1) - break; - - // If a client sends this it should mean they are done receiving the savegame - sendingsavegame[node] = false; - - // As long as clients send keep alives, the server can keep running, so reset the timeout - /// \todo Use a separate cvar for that kind of timeout? - freezetimeout[node] = I_GetTime() + connectiontimeout; - break; case PT_TEXTCMD2: // splitscreen special netconsole = nodetoplayer2[node]; /* FALLTHRU */ @@ -5085,66 +4992,39 @@ static INT16 Consistancy(void) return (INT16)(ret & 0xFFFF); } -// confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE -// used during wipes to tell the server that a node is still connected -static void CL_SendClientKeepAlive(void) -{ - netbuffer->packettype = PT_BASICKEEPALIVE; - - HSendPacket(servernode, false, 0, 0); -} - -static void SV_SendServerKeepAlive(void) -{ - INT32 n; - - for (n = 1; n < MAXNETNODES; n++) - { - if (nodeingame[n]) - { - netbuffer->packettype = PT_BASICKEEPALIVE; - HSendPacket(n, false, 0, 0); - } - } -} - // send the client packet to the server static void CL_SendClientCmd(void) { size_t packetsize = 0; - boolean mis = false; netbuffer->packettype = PT_CLIENTCMD; if (cl_packetmissed) - { - netbuffer->packettype = PT_CLIENTMIS; - mis = true; - } - + netbuffer->packettype++; netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX); netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX); if (gamestate == GS_WAITINGPLAYERS) { // Send PT_NODEKEEPALIVE packet - netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE); + netbuffer->packettype += 4; packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); } else if (gamestate != GS_NULL && (addedtogame || dedicated)) { - packetsize = sizeof (clientcmd_pak); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); // Send a special packet with 2 cmd for splitscreen if (splitscreen || botingame) { - netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD); - packetsize = sizeof (client2cmd_pak); + netbuffer->packettype += 2; G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + packetsize = sizeof (client2cmd_pak); } + else + packetsize = sizeof (clientcmd_pak); HSendPacket(servernode, false, 0, packetsize); } @@ -5155,7 +5035,7 @@ static void CL_SendClientCmd(void) if (localtextcmd[0]) { netbuffer->packettype = PT_TEXTCMD; - M_Memcpy(netbuffer->u.textcmd, localtextcmd, localtextcmd[0]+1); + M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); // All extra data have been sent if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... localtextcmd[0] = 0; @@ -5299,7 +5179,7 @@ static void Local_Maketic(INT32 realtics) // game responder calls HU_Responder, AM_Responder, // and G_MapEventsToControls if (!dedicated) rendergametic = gametic; - // translate inputs (keyboard/mouse/joystick) into game controls + // translate inputs (keyboard/mouse/gamepad) into game controls G_BuildTiccmd(&localcmds, realtics, 1); if (splitscreen || botingame) G_BuildTiccmd(&localcmds2, realtics, 2); @@ -5535,11 +5415,28 @@ static inline void PingUpdate(void) pingmeasurecount = 1; //Reset count } -static tic_t gametime = 0; - -static void UpdatePingTable(void) +void NetUpdate(void) { + static tic_t gametime = 0; + static tic_t resptime = 0; + tic_t nowtime; INT32 i; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + if (realtics <= 0) // nothing new to update + return; + if (realtics > 5) + { + if (server) + realtics = 1; + else + realtics = 5; + } + + gametime = nowtime; if (server) { @@ -5551,150 +5448,6 @@ static void UpdatePingTable(void) realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); pingmeasurecount++; } -} - -// Handle timeouts to prevent definitive freezes from happenning -static void HandleNodeTimeouts(void) -{ - INT32 i; - - if (server) - { - for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && freezetimeout[i] < I_GetTime()) - Net_ConnectionTimeout(i); - - // In case the cvar value was lowered - if (joindelay) - joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); - } -} - -// Keep the network alive while not advancing tics! -void NetKeepAlive(void) -{ - tic_t nowtime; - INT32 realtics; - - nowtime = I_GetTime(); - realtics = nowtime - gametime; - - // return if there's no time passed since the last call - if (realtics <= 0) // nothing new to update - return; - - UpdatePingTable(); - - GetPackets(); - -#ifdef MASTERSERVER - MasterClient_Ticker(); -#endif - - if (client) - { - // send keep alive - CL_SendClientKeepAlive(); - // No need to check for resynch because we aren't running any tics - } - else - { - SV_SendServerKeepAlive(); - } - - // No else because no tics are being run and we can't resynch during this - - Net_AckTicker(); - HandleNodeTimeouts(); - FileSendTicker(); -} - -void NetUpdate(void) -{ - static tic_t resptime = 0; - tic_t nowtime; - INT32 i; - INT32 realtics; - - nowtime = I_GetTime(); - realtics = nowtime - gametime; - - if (realtics <= 0) // nothing new to update - return; - - if (realtics > 5) - { - if (server) - realtics = 1; - else - realtics = 5; - } - - if (server && dedicated && gamestate == GS_LEVEL) - { - const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; - static tic_t dedicatedidletimeprev = 0; - static tic_t dedicatedidle = 0; - - if (dedicatedidletime > 0) - { - for (i = 1; i < MAXNETNODES; ++i) - if (nodeingame[i]) - { - if (dedicatedidle >= dedicatedidletime) - { - CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i); - dedicatedidle = 0; - } - break; - } - - if (i == MAXNETNODES) - { - if (leveltime == 2) - { - // On next tick... - dedicatedidle = dedicatedidletime-1; - } - else if (dedicatedidle >= dedicatedidletime) - { - if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0)) - { - CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); - dedicatedidle = 0; - } - else - { - realtics = 0; - } - } - else if ((dedicatedidle += realtics) >= dedicatedidletime) - { - const char *idlereason = "at round start"; - if (leveltime > 3) - idlereason = va("for %d seconds", dedicatedidle/TICRATE); - - CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason); - realtics = 0; - dedicatedidle = dedicatedidletime; - } - } - } - else - { - if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) - { - CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); - } - dedicatedidle = 0; - } - - dedicatedidletimeprev = dedicatedidletime; - } - - gametime = nowtime; - - UpdatePingTable(); if (client) maketic = neededtic; @@ -5726,25 +5479,24 @@ void NetUpdate(void) } else { - if (!demoplayback && realtics > 0) + if (!demoplayback) { INT32 counts; hu_redownloadinggamestate = false; - // Don't erase tics not acknowledged - counts = realtics; - firstticstosend = gametic; for (i = 0; i < MAXNETNODES; i++) - { - if (!nodeingame[i]) - continue; - if (nettics[i] < firstticstosend) + if (nodeingame[i] && nettics[i] < firstticstosend) + { firstticstosend = nettics[i]; - if (maketic + counts >= nettics[i] + (BACKUPTICS - TICRATE)) - Net_ConnectionTimeout(i); - } + + if (maketic + 1 >= nettics[i] + BACKUPTICS) + Net_ConnectionTimeout(i); + } + + // Don't erase tics not acknowledged + counts = realtics; if (maketic + counts >= firstticstosend + BACKUPTICS) counts = firstticstosend+BACKUPTICS-maketic-1; @@ -5762,10 +5514,20 @@ void NetUpdate(void) } Net_AckTicker(); - HandleNodeTimeouts(); + + // Handle timeouts to prevent definitive freezes from happenning + if (server) + { + for (i = 1; i < MAXNETNODES; i++) + if (nodeingame[i] && freezetimeout[i] < I_GetTime()) + Net_ConnectionTimeout(i); + + // In case the cvar value was lowered + if (joindelay) + joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); + } nowtime /= NEWTICRATERATIO; - if (nowtime > resptime) { resptime = nowtime; @@ -5796,19 +5558,6 @@ INT32 D_NumPlayers(void) return num; } -/** Similar to the above, but counts only bots. - * Purpose is to remove bots from both the player count and the - * max player count on the server view -*/ -INT32 D_NumBots(void) -{ - INT32 num = 0, ix; - for (ix = 0; ix < MAXPLAYERS; ix++) - if (playeringame[ix] && players[ix].bot) - num++; - return num; -} - tic_t GetLag(INT32 node) { return gametic - nettics[node]; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 49fb5fc1d..e07864122 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -77,8 +77,6 @@ typedef enum PT_ASKLUAFILE, // Client telling the server they don't have the file PT_HASLUAFILE, // Client telling the server they have the file - PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called - // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL @@ -160,7 +158,6 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; - UINT8 usedCheats; char server_context[8]; // Unique context id, generated at server startup. } ATTRPACK serverconfig_pak; @@ -400,7 +397,6 @@ extern tic_t servermaxping; extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout; extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; -extern consvar_t cv_dedicatedidletime; // Used in d_net, the only dependence tic_t ExpandTics(INT32 low, INT32 node); @@ -415,9 +411,6 @@ void SendKick(UINT8 playernum, UINT8 msg); // Create any new ticcmds and broadcast to other players. void NetUpdate(void); -// Maintain connections to nodes without timing them all out. -void NetKeepAlive(void); - void SV_StartSinglePlayerServer(void); boolean SV_SpawnServer(void); void SV_StopServer(void); @@ -454,7 +447,6 @@ extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); -INT32 D_NumBots(void); void D_ResetTiccmds(void); tic_t GetLag(INT32 node); diff --git a/src/d_net.c b/src/d_net.c index 6d8c72942..a7e1eb16d 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -869,9 +869,6 @@ static void DebugPrintpacket(const char *header) (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode), (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode)); break; - case PT_BASICKEEPALIVE: - fprintf(debugfile, " wipetime\n"); - break; case PT_TEXTCMD: case PT_TEXTCMD2: fprintf(debugfile, " length %d\n ", netbuffer->u.textcmd[0]); @@ -1210,32 +1207,26 @@ static void Internal_FreeNodenum(INT32 nodenum) (void)nodenum; } -char *I_NetSplitAddress(char *host, char **port) -{ - boolean v4 = (strchr(host, '.') != NULL); - - host = strtok(host, v4 ? ":" : "[]"); - - if (port) - *port = strtok(NULL, ":"); - - return host; -} - SINT8 I_NetMakeNode(const char *hostname) { SINT8 newnode = -1; if (I_NetMakeNodewPort) { char *localhostname = strdup(hostname); - char *port; + char *t = localhostname; + const char *port; if (!localhostname) return newnode; - // retrieve portnum from address! - hostname = I_NetSplitAddress(localhostname, &port); + strtok(localhostname, ":"); + port = strtok(NULL, ":"); - newnode = I_NetMakeNodewPort(hostname, port); + // remove the port in the hostname as we've it already + while ((*t != ':') && (*t != '\0')) + t++; + *t = '\0'; + + newnode = I_NetMakeNodewPort(localhostname, port); free(localhostname); } return newnode; diff --git a/src/d_net.h b/src/d_net.h index ddedbef4a..5baa593a0 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 45a394eff..5f02bc2de 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,6 +21,7 @@ #include "g_game.h" #include "hu_stuff.h" #include "g_input.h" +#include "i_gamepad.h" #include "m_menu.h" #include "r_local.h" #include "r_skins.h" @@ -49,7 +50,6 @@ #include "m_anigif.h" #include "md5.h" #include "m_perfstats.h" -#include "u_list.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -182,14 +182,6 @@ static CV_PossibleValue_t mouse2port_cons_t[] = {{1, "COM1"}, {2, "COM2"}, {3, " {0, NULL}}; #endif -#ifdef LJOYSTICK -static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {3, "/dev/js2"}, - {4, "/dev/js3"}, {0, NULL}}; -#else -// accept whatever value - it is in fact the joystick device number -#define usejoystick_cons_t NULL -#endif - static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}}; static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; @@ -203,37 +195,37 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; -consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL); #ifdef NETGAME_DEVMODE static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange); #endif static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); -consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, startingliveslimit_cons_t, NULL); +consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL); static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, respawntime_cons_t, NULL); +consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); -consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, competitionboxes_cons_t, NULL); +consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; -consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE|CV_ALLOWLUA, seenames_cons_t, 0); -consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0); +consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); // names consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange); // player colors UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE; -consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color_OnChange); -consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color2_OnChange); +consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange); +consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange); // player's skin, saved for commodity, when using a favorite skins wad.. -consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin_OnChange); -consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin2_OnChange); +consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange); +consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange); // saved versions of the above six consvar_t cv_defaultplayercolor = CVAR_INIT ("defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL); @@ -248,19 +240,61 @@ INT32 cv_debug; consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse); consvar_t cv_usemouse2 = CVAR_INIT ("use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2); -consvar_t cv_usejoystick = CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick); -consvar_t cv_usejoystick2 = CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2); -#if (defined (LJOYSTICK) || defined (HAVE_SDL)) -#ifdef LJOYSTICK -consvar_t cv_joyport = CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); -consvar_t cv_joyport2 = CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); //Alam: for later -#endif -consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale); -consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2); -#else -consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save -consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save -#endif +// We use cv_usegamepad.string as the USER-SET var +// and cv_usegamepad.value as the INTERNAL var +// +// In practice, if cv_usegamepad.string == 0, this overrides +// cv_usegamepad.value and always disables + +static void UseGamepad_OnChange(void) +{ + I_ChangeGamepad(0); +} + +static void UseGamepad2_OnChange(void) +{ + I_ChangeGamepad(1); +} + +consvar_t cv_usegamepad[2] = { + CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, NULL, UseGamepad_OnChange), + CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, NULL, UseGamepad2_OnChange) +}; + +static void PadScale_OnChange(void) +{ + I_SetGamepadDigital(0, cv_gamepad_scale[0].value == 0); +} + +static void PadScale2_OnChange(void) +{ + I_SetGamepadDigital(1, cv_gamepad_scale[1].value == 0); +} + +consvar_t cv_gamepad_scale[2] = { + CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, PadScale_OnChange), + CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, PadScale2_OnChange) +}; + +static void PadRumble_OnChange(void) +{ + if (!cv_gamepad_rumble[0].value) + I_StopGamepadRumble(0); +} + +static void PadRumble2_OnChange(void) +{ + if (!cv_gamepad_rumble[1].value) + I_StopGamepadRumble(1); +} + +consvar_t cv_gamepad_rumble[2] = { + CVAR_INIT ("padrumble", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble_OnChange), + CVAR_INIT ("padrumble2", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble2_OnChange) +}; + +consvar_t cv_gamepad_autopause = CVAR_INIT ("pauseongamepaddisconnect", "On", CV_SAVE, CV_OnOff, NULL); + #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL); consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); @@ -268,43 +302,43 @@ consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL); #endif -consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, matchboxes_cons_t, NULL); -consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL); +consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, Ringslinger_OnChange); -consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL|CV_ALLOWLUA, NULL, Gravity_OnChange); +consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange); +consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange); static CV_PossibleValue_t minitimelimit_cons_t[] = {{1, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, minitimelimit_cons_t, NULL); +consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); -consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, minitimelimit_cons_t, Hidetime_OnChange); +consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange); -consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, AutoBalance_OnChange); -consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, teamscramble_cons_t, TeamScramble_OnChange); -consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, teamscramble_cons_t, NULL); +consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); +consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); +consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL); -consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL|CV_ALLOWLUA, CV_OnOff, ItemFinder_OnChange); +consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange); // Scoring type options -consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL); @@ -315,13 +349,13 @@ static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-pe consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL); static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, pointlimit_cons_t, PointLimit_OnChange); +consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, timelimit_cons_t, TimeLimit_OnChange); +consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}}; -consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, numlaps_cons_t, NumLaps_OnChange); +consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, basenumlaps_cons_t, BaseNumLaps_OnChange); +consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -330,11 +364,11 @@ INT32 timelimits[NUMGAMETYPES]; // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL); -consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, NULL, ForceSkin_OnChange); +consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); -consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL); consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; @@ -352,26 +386,26 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; -consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, inttime_cons_t, NULL); +consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL); static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}}; -consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, coopstarposts_cons_t, CoopStarposts_OnChange); +consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange); static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}}; -consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, cooplives_cons_t, CoopLives_OnChange); +consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange); static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; -consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, advancemap_cons_t, NULL); +consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL); static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}}; -consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, playersforexit_cons_t, NULL); +consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL); -consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, ExitMove_OnChange); +consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange); -consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL); -consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, pause_cons_t, NULL); -consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, Mute_OnChange); +consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL); +consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange); consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); @@ -464,57 +498,57 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_LUAFILE, Got_LuaFile); // Remote Administration - COM_AddCommand("password", Command_Changepassword_f, COM_LUA); - COM_AddCommand("login", Command_Login_f, COM_LUA); // useful in dedicated to kick off remote admin - COM_AddCommand("promote", Command_Verify_f, COM_LUA); + COM_AddCommand("password", Command_Changepassword_f); + COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin + COM_AddCommand("promote", Command_Verify_f); RegisterNetXCmd(XD_VERIFIED, Got_Verification); - COM_AddCommand("demote", Command_RemoveAdmin_f, COM_LUA); + COM_AddCommand("demote", Command_RemoveAdmin_f); RegisterNetXCmd(XD_DEMOTED, Got_Removal); - COM_AddCommand("motd", Command_MotD_f, COM_LUA); + COM_AddCommand("motd", Command_MotD_f); RegisterNetXCmd(XD_SETMOTD, Got_MotD_f); // For remote admin RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange); - COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA); + COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f); RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores); - COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA); - COM_AddCommand("map", Command_Map_f, COM_LUA); + COM_AddCommand("clearscores", Command_Clearscores_f); + COM_AddCommand("map", Command_Map_f); - COM_AddCommand("exitgame", Command_ExitGame_f, COM_LUA); - COM_AddCommand("retry", Command_Retry_f, COM_LUA); - COM_AddCommand("exitlevel", Command_ExitLevel_f, COM_LUA); - COM_AddCommand("showmap", Command_Showmap_f, COM_LUA); - COM_AddCommand("mapmd5", Command_Mapmd5_f, COM_LUA); + COM_AddCommand("exitgame", Command_ExitGame_f); + COM_AddCommand("retry", Command_Retry_f); + COM_AddCommand("exitlevel", Command_ExitLevel_f); + COM_AddCommand("showmap", Command_Showmap_f); + COM_AddCommand("mapmd5", Command_Mapmd5_f); - COM_AddCommand("addfolder", Command_Addfolder, COM_LUA); - COM_AddCommand("addfile", Command_Addfile, COM_LUA); - COM_AddCommand("listwad", Command_ListWADS_f, COM_LUA); + COM_AddCommand("addfolder", Command_Addfolder); + COM_AddCommand("addfile", Command_Addfile); + COM_AddCommand("listwad", Command_ListWADS_f); - COM_AddCommand("runsoc", Command_RunSOC, COM_LUA); - COM_AddCommand("pause", Command_Pause, COM_LUA); - COM_AddCommand("suicide", Command_Suicide, COM_LUA); + COM_AddCommand("runsoc", Command_RunSOC); + COM_AddCommand("pause", Command_Pause); + COM_AddCommand("suicide", Command_Suicide); - COM_AddCommand("gametype", Command_ShowGametype_f, COM_LUA); - COM_AddCommand("version", Command_Version_f, COM_LUA); + COM_AddCommand("gametype", Command_ShowGametype_f); + COM_AddCommand("version", Command_Version_f); #ifdef UPDATE_ALERT - COM_AddCommand("mod_details", Command_ModDetails_f, COM_LUA); + COM_AddCommand("mod_details", Command_ModDetails_f); #endif - COM_AddCommand("quit", Command_Quit_f, COM_LUA); + COM_AddCommand("quit", Command_Quit_f); - COM_AddCommand("saveconfig", Command_SaveConfig_f, 0); - COM_AddCommand("loadconfig", Command_LoadConfig_f, 0); - COM_AddCommand("changeconfig", Command_ChangeConfig_f, 0); - COM_AddCommand("isgamemodified", Command_Isgamemodified_f, COM_LUA); // test - COM_AddCommand("showscores", Command_ShowScores_f, COM_LUA); - COM_AddCommand("showtime", Command_ShowTime_f, COM_LUA); - COM_AddCommand("cheats", Command_Cheats_f, COM_LUA); // test + COM_AddCommand("saveconfig", Command_SaveConfig_f); + COM_AddCommand("loadconfig", Command_LoadConfig_f); + COM_AddCommand("changeconfig", Command_ChangeConfig_f); + COM_AddCommand("isgamemodified", Command_Isgamemodified_f); // test + COM_AddCommand("showscores", Command_ShowScores_f); + COM_AddCommand("showtime", Command_ShowTime_f); + COM_AddCommand("cheats", Command_Cheats_f); // test #ifdef _DEBUG - COM_AddCommand("togglemodified", Command_Togglemodified_f, COM_LUA); - COM_AddCommand("archivetest", Command_Archivetest_f, COM_LUA); + COM_AddCommand("togglemodified", Command_Togglemodified_f); + COM_AddCommand("archivetest", Command_Archivetest_f); #endif - COM_AddCommand("downloads", Command_Downloads_f, COM_LUA); + COM_AddCommand("downloads", Command_Downloads_f); // for master server connection AddMServCommands(); @@ -599,10 +633,9 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_joinnextround); CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); - CV_RegisterVar(&cv_dedicatedidletime); #endif - COM_AddCommand("ping", Command_Ping_f, COM_LUA); + COM_AddCommand("ping", Command_Ping_f); CV_RegisterVar(&cv_nettimeout); CV_RegisterVar(&cv_jointimeout); @@ -614,10 +647,6 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allowseenames); - // Other filesrch.c consvars are defined in D_RegisterClientCommands - CV_RegisterVar(&cv_addons_option); - CV_RegisterVar(&cv_addons_folder); - CV_RegisterVar(&cv_dummyconsvar); } @@ -650,25 +679,25 @@ void D_RegisterClientCommands(void) if (dedicated) return; - COM_AddCommand("numthinkers", Command_Numthinkers_f, COM_LUA); - COM_AddCommand("countmobjs", Command_CountMobjs_f, COM_LUA); + COM_AddCommand("numthinkers", Command_Numthinkers_f); + COM_AddCommand("countmobjs", Command_CountMobjs_f); - COM_AddCommand("changeteam", Command_Teamchange_f, COM_LUA); - COM_AddCommand("changeteam2", Command_Teamchange2_f, COM_LUA); + COM_AddCommand("changeteam", Command_Teamchange_f); + COM_AddCommand("changeteam2", Command_Teamchange2_f); - COM_AddCommand("playdemo", Command_Playdemo_f, 0); - COM_AddCommand("timedemo", Command_Timedemo_f, 0); - COM_AddCommand("stopdemo", Command_Stopdemo_f, COM_LUA); - COM_AddCommand("playintro", Command_Playintro_f, COM_LUA); + COM_AddCommand("playdemo", Command_Playdemo_f); + COM_AddCommand("timedemo", Command_Timedemo_f); + COM_AddCommand("stopdemo", Command_Stopdemo_f); + COM_AddCommand("playintro", Command_Playintro_f); - COM_AddCommand("resetcamera", Command_ResetCamera_f, COM_LUA); + COM_AddCommand("resetcamera", Command_ResetCamera_f); - COM_AddCommand("setcontrol", Command_Setcontrol_f, 0); - COM_AddCommand("setcontrol2", Command_Setcontrol2_f, 0); + COM_AddCommand("setcontrol", Command_Setcontrol_f); + COM_AddCommand("setcontrol2", Command_Setcontrol2_f); - COM_AddCommand("screenshot", M_ScreenShot, COM_LUA); - COM_AddCommand("startmovie", Command_StartMovie_f, COM_LUA); - COM_AddCommand("stopmovie", Command_StopMovie_f, COM_LUA); + COM_AddCommand("screenshot", M_ScreenShot); + COM_AddCommand("startmovie", Command_StartMovie_f); + COM_AddCommand("stopmovie", Command_StopMovie_f); CV_RegisterVar(&cv_screenshot_option); CV_RegisterVar(&cv_screenshot_folder); @@ -730,7 +759,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ghost_last); CV_RegisterVar(&cv_ghost_guest); - COM_AddCommand("displayplayer", Command_Displayplayer_f, COM_LUA); + COM_AddCommand("displayplayer", Command_Displayplayer_f); // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_globalgamma); @@ -777,30 +806,30 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_pauseifunfocused); // g_input.c - CV_RegisterVar(&cv_sideaxis); - CV_RegisterVar(&cv_sideaxis2); - CV_RegisterVar(&cv_turnaxis); - CV_RegisterVar(&cv_turnaxis2); - CV_RegisterVar(&cv_moveaxis); - CV_RegisterVar(&cv_moveaxis2); - CV_RegisterVar(&cv_lookaxis); - CV_RegisterVar(&cv_lookaxis2); - CV_RegisterVar(&cv_jumpaxis); - CV_RegisterVar(&cv_jumpaxis2); - CV_RegisterVar(&cv_spinaxis); - CV_RegisterVar(&cv_spinaxis2); - CV_RegisterVar(&cv_fireaxis); - CV_RegisterVar(&cv_fireaxis2); - CV_RegisterVar(&cv_firenaxis); - CV_RegisterVar(&cv_firenaxis2); - CV_RegisterVar(&cv_deadzone); - CV_RegisterVar(&cv_deadzone2); - CV_RegisterVar(&cv_digitaldeadzone); - CV_RegisterVar(&cv_digitaldeadzone2); + CV_RegisterVar(&cv_sideaxis[0]); + CV_RegisterVar(&cv_sideaxis[1]); + CV_RegisterVar(&cv_turnaxis[0]); + CV_RegisterVar(&cv_turnaxis[1]); + CV_RegisterVar(&cv_moveaxis[0]); + CV_RegisterVar(&cv_moveaxis[1]); + CV_RegisterVar(&cv_lookaxis[0]); + CV_RegisterVar(&cv_lookaxis[1]); + CV_RegisterVar(&cv_jumpaxis[0]); + CV_RegisterVar(&cv_jumpaxis[1]); + CV_RegisterVar(&cv_spinaxis[0]); + CV_RegisterVar(&cv_spinaxis[1]); + CV_RegisterVar(&cv_fireaxis[0]); + CV_RegisterVar(&cv_fireaxis[1]); + CV_RegisterVar(&cv_firenaxis[0]); + CV_RegisterVar(&cv_firenaxis[1]); + CV_RegisterVar(&cv_deadzone[0]); + CV_RegisterVar(&cv_deadzone[1]); + CV_RegisterVar(&cv_digitaldeadzone[0]); + CV_RegisterVar(&cv_digitaldeadzone[1]); // filesrch.c - //CV_RegisterVar(&cv_addons_option); // These two are now defined - //CV_RegisterVar(&cv_addons_folder); // in D_RegisterServerCommands + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); CV_RegisterVar(&cv_addons_search_type); @@ -825,14 +854,14 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_mousemove); CV_RegisterVar(&cv_mousemove2); - CV_RegisterVar(&cv_usejoystick); - CV_RegisterVar(&cv_usejoystick2); -#ifdef LJOYSTICK - CV_RegisterVar(&cv_joyport); - CV_RegisterVar(&cv_joyport2); -#endif - CV_RegisterVar(&cv_joyscale); - CV_RegisterVar(&cv_joyscale2); + for (i = 0; i < 2; i++) + { + CV_RegisterVar(&cv_usegamepad[i]); + CV_RegisterVar(&cv_gamepad_scale[i]); + CV_RegisterVar(&cv_gamepad_rumble[i]); + } + + CV_RegisterVar(&cv_gamepad_autopause); // Analog Control CV_RegisterVar(&cv_analog[0]); @@ -874,15 +903,10 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); - CV_RegisterVar(&cv_renderhitboxinterpolation); - CV_RegisterVar(&cv_renderhitboxgldepth); - CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); - CV_RegisterVar(&cv_scr_width_w); - CV_RegisterVar(&cv_scr_height_w); CV_RegisterVar(&cv_soundtest); @@ -891,7 +915,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ps_descriptor); // ingame object placing - COM_AddCommand("objectplace", Command_ObjectPlace_f, COM_LUA); + COM_AddCommand("objectplace", Command_ObjectPlace_f); //COM_AddCommand("writethings", Command_Writethings_f); CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_opflags); @@ -903,32 +927,32 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_freedemocamera); // add cheat commands - COM_AddCommand("noclip", Command_CheatNoClip_f, COM_LUA); - COM_AddCommand("god", Command_CheatGod_f, COM_LUA); - COM_AddCommand("notarget", Command_CheatNoTarget_f, COM_LUA); - COM_AddCommand("getallemeralds", Command_Getallemeralds_f, COM_LUA); - COM_AddCommand("resetemeralds", Command_Resetemeralds_f, COM_LUA); - COM_AddCommand("setrings", Command_Setrings_f, COM_LUA); - COM_AddCommand("setlives", Command_Setlives_f, COM_LUA); - COM_AddCommand("setcontinues", Command_Setcontinues_f, COM_LUA); - COM_AddCommand("devmode", Command_Devmode_f, COM_LUA); - COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f, COM_LUA); - COM_AddCommand("scale", Command_Scale_f, COM_LUA); - COM_AddCommand("gravflip", Command_Gravflip_f, COM_LUA); - COM_AddCommand("hurtme", Command_Hurtme_f, COM_LUA); - COM_AddCommand("jumptoaxis", Command_JumpToAxis_f, COM_LUA); - COM_AddCommand("charability", Command_Charability_f, COM_LUA); - COM_AddCommand("charspeed", Command_Charspeed_f, COM_LUA); - COM_AddCommand("teleport", Command_Teleport_f, COM_LUA); - COM_AddCommand("rteleport", Command_RTeleport_f, COM_LUA); - COM_AddCommand("skynum", Command_Skynum_f, COM_LUA); - COM_AddCommand("weather", Command_Weather_f, COM_LUA); - COM_AddCommand("toggletwod", Command_Toggletwod_f, COM_LUA); + COM_AddCommand("noclip", Command_CheatNoClip_f); + COM_AddCommand("god", Command_CheatGod_f); + COM_AddCommand("notarget", Command_CheatNoTarget_f); + COM_AddCommand("getallemeralds", Command_Getallemeralds_f); + COM_AddCommand("resetemeralds", Command_Resetemeralds_f); + COM_AddCommand("setrings", Command_Setrings_f); + COM_AddCommand("setlives", Command_Setlives_f); + COM_AddCommand("setcontinues", Command_Setcontinues_f); + COM_AddCommand("devmode", Command_Devmode_f); + COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f); + COM_AddCommand("scale", Command_Scale_f); + COM_AddCommand("gravflip", Command_Gravflip_f); + COM_AddCommand("hurtme", Command_Hurtme_f); + COM_AddCommand("jumptoaxis", Command_JumpToAxis_f); + COM_AddCommand("charability", Command_Charability_f); + COM_AddCommand("charspeed", Command_Charspeed_f); + COM_AddCommand("teleport", Command_Teleport_f); + COM_AddCommand("rteleport", Command_RTeleport_f); + COM_AddCommand("skynum", Command_Skynum_f); + COM_AddCommand("weather", Command_Weather_f); + COM_AddCommand("toggletwod", Command_Toggletwod_f); #ifdef _DEBUG - COM_AddCommand("causecfail", Command_CauseCfail_f, COM_LUA); + COM_AddCommand("causecfail", Command_CauseCfail_f); #endif #ifdef LUA_ALLOW_BYTECODE - COM_AddCommand("dumplua", Command_Dumplua_f, COM_LUA); + COM_AddCommand("dumplua", Command_Dumplua_f); #endif } @@ -1643,14 +1667,9 @@ static void Command_Playdemo_f(void) { char name[256]; - if (COM_Argc() < 2) + if (COM_Argc() != 2) { - CONS_Printf("playdemo [-addfiles / -force]:\n"); - CONS_Printf(M_GetText( - "Play back a demo file. The full path from your SRB2 directory must be given.\n\n" - - "* With \"-addfiles\", any required files are added from a list contained within the demo file.\n" - "* With \"-force\", the demo is played even if the necessary files have not been added.\n")); + CONS_Printf(M_GetText("playdemo : playback a demo\n")); return; } @@ -1672,16 +1691,6 @@ static void Command_Playdemo_f(void) CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); - demofileoverride = DFILE_OVERRIDE_NONE; - if (strcmp(COM_Argv(2), "-addfiles") == 0) - { - demofileoverride = DFILE_OVERRIDE_LOAD; - } - else if (strcmp(COM_Argv(2), "-force") == 0) - { - demofileoverride = DFILE_OVERRIDE_SKIP; - } - // Internal if no extension, external if one exists // If external, convert the file name to a path in SRB2's home directory if (FIL_CheckExtension(name)) @@ -1903,7 +1912,7 @@ static void Command_Map_f(void) const char *gametypename; boolean newresetplayers; - boolean wouldSetCheats; + boolean mustmodifygame; INT32 newmapnum; @@ -1924,11 +1933,11 @@ static void Command_Map_f(void) option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - wouldSetCheats = - !( netgame || multiplayer ) && - !( usedCheats ); + mustmodifygame = + !( netgame || multiplayer ) && + (!modifiedgame || savemoddata ); - if (wouldSetCheats && !option_force) + if (mustmodifygame && !option_force) { /* May want to be more descriptive? */ CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); @@ -1982,9 +1991,9 @@ static void Command_Map_f(void) return; } - if (wouldSetCheats && option_force) + if (mustmodifygame && option_force) { - G_SetUsedCheats(false); + G_SetGameModified(false); } // new gametype value @@ -2057,7 +2066,7 @@ static void Command_Map_f(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - if (!dedicated && M_MapLocked(newmapnum, serverGamedata)) + if (!dedicated && M_MapLocked(newmapnum)) { CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); Z_Free(realmapname); @@ -2192,7 +2201,7 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_WAITINGPLAYERS) || (marathonmode && gamestate == GS_INTERMISSION)) + if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION)) { CONS_Printf(M_GetText("You can't pause here.\n")); return; @@ -2241,9 +2250,14 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) { if (!menuactive || netgame) S_PauseAudio(); + + P_PauseRumble(NULL); } else + { S_ResumeAudio(); + P_UnpauseRumble(NULL); + } } I_UpdateMouseGrab(); @@ -2355,7 +2369,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) } for (i = 0; i < MAXPLAYERS; i++) - players[i].score = players[i].recordscore = 0; + players[i].score = 0; CONS_Printf(M_GetText("Scores have been reset by the server.\n")); } @@ -3298,69 +3312,6 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) G_SetGameModified(true); } -// C++ would make this SO much simpler! -typedef struct addedfile_s -{ - struct addedfile_s *next; - struct addedfile_s *prev; - char *value; -} addedfile_t; - -static boolean AddedFileContains(addedfile_t *list, const char *value) -{ - addedfile_t *node; - for (node = list; node; node = node->next) - { - if (!strcmp(value, node->value)) - return true; - } - - return false; -} - -static void AddedFilesAdd(addedfile_t **list, const char *value) -{ - addedfile_t *item = Z_Calloc(sizeof(addedfile_t), PU_STATIC, NULL); - item->value = Z_StrDup(value); - ListAdd(item, (listitem_t**)list); -} - -static void AddedFilesRemove(void *pItem, addedfile_t **itemHead) -{ - addedfile_t *item = (addedfile_t *)pItem; - - if (item == *itemHead) // Start of list - { - *itemHead = item->next; - - if (*itemHead) - (*itemHead)->prev = NULL; - } - else if (item->next == NULL) // end of list - { - item->prev->next = NULL; - } - else // Somewhere in between - { - item->prev->next = item->next; - item->next->prev = item->prev; - } - - Z_Free(item->value); - Z_Free(item); -} - -static void AddedFilesClearList(addedfile_t **itemHead) -{ - addedfile_t *item; - addedfile_t *next; - for (item = *itemHead; item; item = next) - { - next = item->next; - AddedFilesRemove(item, itemHead); - } -} - /** Adds a pwad at runtime. * Searches for sounds, maps, music, new images. */ @@ -3369,7 +3320,8 @@ static void Command_Addfile(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - addedfile_t *addedfiles = NULL; // list of filenames already processed + const char *addedfiles[argc]; // list of filenames already processed + size_t numfilesadded = 0; // the amount of filenames processed if (argc < 2) { @@ -3384,14 +3336,25 @@ static void Command_Addfile(void) char buf[256]; char *buf_p = buf; INT32 i; + size_t ii; int musiconly; // W_VerifyNMUSlumps isn't boolean boolean fileadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - fileadded = AddedFileContains(addedfiles, fn); - if (fileadded) // If this is one of them, don't try to add it. + for (ii = 0; ii < numfilesadded; ii++) + { + // If this is one of them, don't try to add it. + if (!strcmp(fn, addedfiles[ii])) + { + fileadded = true; + break; + } + } + + // If we've added this one, skip to the next one. + if (fileadded) { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3400,16 +3363,13 @@ static void Command_Addfile(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') - { - AddedFilesClearList(&addedfiles); return; - } musiconly = W_VerifyNMUSlumps(fn, false); if (musiconly == -1) { - AddedFilesAdd(&addedfiles, fn); + addedfiles[numfilesadded++] = fn; continue; } @@ -3428,7 +3388,7 @@ static void Command_Addfile(void) if (!(netgame || multiplayer) || musiconly) { P_AddWadFile(fn); - AddedFilesAdd(&addedfiles, fn); + addedfiles[numfilesadded++] = fn; continue; } @@ -3443,7 +3403,6 @@ static void Command_Addfile(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - AddedFilesClearList(&addedfiles); return; } @@ -3483,15 +3442,13 @@ static void Command_Addfile(void) WRITEMEM(buf_p, md5sum, 16); } - AddedFilesAdd(&addedfiles, fn); + addedfiles[numfilesadded++] = fn; if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } - - AddedFilesClearList(&addedfiles); } static void Command_Addfolder(void) @@ -3499,7 +3456,8 @@ static void Command_Addfolder(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - addedfile_t *addedfolders = NULL; // list of filenames already processed + const char *addedfolders[argc]; // list of filenames already processed + size_t numfoldersadded = 0; // the amount of filenames processed if (argc < 2) { @@ -3515,13 +3473,24 @@ static void Command_Addfolder(void) char buf[256]; char *buf_p = buf; INT32 i, stat; + size_t ii; boolean folderadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - folderadded = AddedFileContains(addedfolders, fn); - if (folderadded) // If we've added this one, skip to the next one. + for (ii = 0; ii < numfoldersadded; ii++) + { + // If this is one of them, don't try to add it. + if (!strcmp(fn, addedfolders[ii])) + { + folderadded = true; + break; + } + } + + // If we've added this one, skip to the next one. + if (folderadded) { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3530,16 +3499,13 @@ static void Command_Addfolder(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') - { - AddedFilesClearList(&addedfolders); return; - } // Add file on your client directly if you aren't in a netgame. if (!(netgame || multiplayer)) { P_AddFolder(fn); - AddedFilesAdd(&addedfolders, fn); + addedfolders[numfoldersadded++] = fn; continue; } @@ -3561,7 +3527,6 @@ static void Command_Addfolder(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - AddedFilesClearList(&addedfolders); return; } @@ -3607,7 +3572,7 @@ static void Command_Addfolder(void) Z_Free(fullpath); - AddedFilesAdd(&addedfolders, fn); + addedfolders[numfoldersadded++] = fn; WRITESTRINGN(buf_p,p,240); @@ -3966,12 +3931,18 @@ void ItemFinder_OnChange(void) if (!cv_itemfinder.value) return; // it's fine. - if (!M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) + if (!M_SecretUnlocked(SECRET_ITEMFINDER)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_itemfinder, 0); return; } + else if (netgame || multiplayer) + { + CONS_Printf(M_GetText("This only works in single player.\n")); + CV_StealthSetValue(&cv_itemfinder, 0); + return; + } } /** Deals with a pointlimit change by printing the change to the console. @@ -4320,7 +4291,7 @@ void D_GameTypeChanged(INT32 lastgametype) static void Ringslinger_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && cv_ringslinger.value && !cv_debug) + if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && cv_ringslinger.value && !cv_debug) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_ringslinger, 0); @@ -4328,12 +4299,12 @@ static void Ringslinger_OnChange(void) } if (cv_ringslinger.value) // Only if it's been turned on - G_SetUsedCheats(false); + G_SetGameModified(multiplayer); } static void Gravity_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && !cv_debug + if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); @@ -4349,7 +4320,7 @@ static void Gravity_OnChange(void) #endif if (!CV_IsSetToDefault(&cv_gravity)) - G_SetUsedCheats(false); + G_SetGameModified(multiplayer); gravity = cv_gravity.value; } @@ -4630,9 +4601,10 @@ void Command_ExitGame_f(void) botskin = 0; cv_debug = 0; emeralds = 0; - automapactive = false; memset(&luabanks, 0, sizeof(luabanks)); + P_StopRumble(NULL); + if (dirmenu) closefilemenu(true); @@ -4666,7 +4638,7 @@ static void Fishcake_OnChange(void) // so don't make modifiedgame always on! if (cv_debug) { - G_SetUsedCheats(false); + G_SetGameModified(multiplayer); } else if (cv_debug != cv_fishcake.value) @@ -4683,11 +4655,11 @@ static void Fishcake_OnChange(void) static void Command_Isgamemodified_f(void) { if (savemoddata) - CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n")); + CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n")); else if (modifiedgame) - CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n")); + CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); else - CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n")); + CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); } static void Command_Cheats_f(void) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 26bf4d5c6..47f68a17e 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,14 +33,10 @@ extern consvar_t cv_defaultskin2; extern consvar_t cv_seenames, cv_allowseenames; extern consvar_t cv_usemouse; -extern consvar_t cv_usejoystick; -extern consvar_t cv_usejoystick2; -#ifdef LJOYSTICK -extern consvar_t cv_joyport; -extern consvar_t cv_joyport2; -#endif -extern consvar_t cv_joyscale; -extern consvar_t cv_joyscale2; +extern consvar_t cv_usegamepad[2]; +extern consvar_t cv_gamepad_scale[2]; +extern consvar_t cv_gamepad_rumble[2]; +extern consvar_t cv_gamepad_autopause; // splitscreen with second mouse extern consvar_t cv_mouse2port; diff --git a/src/d_netfil.c b/src/d_netfil.c index 3fef75681..edbef30bb 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -498,7 +498,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = mainwads; j < numwadfiles; j++) + for (j = mainwads; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && diff --git a/src/d_netfil.h b/src/d_netfil.h index ecec976be..f778a518f 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/http-mserv.c b/src/http-mserv.c index b7032e89a..b0ef37fa1 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by James R. +// Copyright (C) 2020-2022 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -65,8 +65,6 @@ static I_mutex hms_api_mutex; static char *hms_server_token; -static char hms_useragent[512]; - struct HMS_buffer { CURL *curl; @@ -83,22 +81,6 @@ Contact_error (void) ); } -static void -get_user_agent(char *buf, size_t len) -{ - if (snprintf(buf, len, "%s/%s (%s; %s; %i; %i) SRB2BASE/%i", SRB2APPLICATION, VERSIONSTRING, compbranch, comprevision, MODID, MODVERSION, CODEBASE) < 0) - I_Error("http-mserv: get_user_agent failed"); -} - -static void -init_user_agent_once(void) -{ - if (hms_useragent[0] != '\0') - return; - - get_user_agent(hms_useragent, 512); -} - static size_t HMS_on_read (char *s, size_t _1, size_t n, void *userdata) { @@ -174,8 +156,6 @@ HMS_connect (const char *format, ...) I_lock_mutex(&hms_api_mutex); #endif - init_user_agent_once(); - seek = strlen(hms_api) + 1;/* + '/' */ va_start (ap, format); @@ -216,18 +196,12 @@ HMS_connect (const char *format, ...) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - -#ifndef NO_IPV6 - if (M_CheckParm("-noipv6")) -#endif - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer); - curl_easy_setopt(curl, CURLOPT_USERAGENT, hms_useragent); - curl_free(quack_token); free(url); diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index 9efaff4da..49aadf27d 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2023 by Sonic Team Junior. +// Copyright (C) 2011-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h index 79cfb05b2..592e693f4 100644 --- a/src/i_addrinfo.h +++ b/src/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2023 by Sonic Team Junior. +// Copyright (C) 2011-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_net.h b/src/i_net.h index 12a07f183..62b7528d5 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -109,17 +109,6 @@ extern boolean (*I_NetCanSend)(void); */ extern void (*I_NetFreeNodenum)(INT32 nodenum); -/** - \brief split a string into address and port - - \param address string to split - - \param port double pointer to hold port component (optional) - - \return address component -*/ -extern char *I_NetSplitAddress(char *address, char **port); - /** \brief open a connection with specified address \param address address to connect to diff --git a/src/i_tcp.c b/src/i_tcp.c index d95b381f4..8838ba725 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -340,14 +340,8 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype) static const char *SOCK_AddrToStr(mysockaddr_t *sk) { - static char s[64]; // 255.255.255.255:65535 or - // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 + static char s[64]; // 255.255.255.255:65535 or IPv6:65535 #ifdef HAVE_NTOP -#ifdef HAVE_IPV6 - int v6 = (sk->any.sa_family == AF_INET6); -#else - int v6 = 0; -#endif void *addr; if(sk->any.sa_family == AF_INET) @@ -361,21 +355,14 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) if(addr == NULL) sprintf(s, "No address"); - else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) + else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL) sprintf(s, "Unknown family type, error #%u", errno); #ifdef HAVE_IPV6 - else if(sk->any.sa_family == AF_INET6) - { - s[0] = '['; - strcat(s, "]"); - - if (sk->ip6.sin6_port != 0) - strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); - } + else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0) + strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); #endif else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); - #else if (sk->any.sa_family == AF_INET) { @@ -440,7 +427,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) && (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port)); #ifdef HAVE_IPV6 else if (b->any.sa_family == AF_INET6) - return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) + return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) && (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port)); #endif else @@ -748,7 +735,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen unsigned long trueval = true; #endif mysockaddr_t straddr; - socklen_t len = sizeof(straddr); + struct sockaddr_in sin; + socklen_t len = sizeof(sin); if (s == (SOCKET_TYPE)ERRSOCKET) return (SOCKET_TYPE)ERRSOCKET; @@ -766,12 +754,14 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } #endif - memcpy(&straddr, addr, addrlen); + straddr.any = *addr; I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr)); if (family == AF_INET) { - if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) + mysockaddr_t tmpaddr; + tmpaddr.any = *addr ; + if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) { opt = true; opts = (socklen_t)sizeof(opt); @@ -788,7 +778,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen #ifdef HAVE_IPV6 else if (family == AF_INET6) { - if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL + if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL { opt = true; opts = (socklen_t)sizeof(opt); @@ -798,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen // make it IPv6 ony opt = true; opts = (socklen_t)sizeof(opt); - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts)) + if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore } @@ -840,17 +830,10 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); } - if (getsockname(s, &straddr.any, &len) == -1) + if (getsockname(s, (struct sockaddr *)&sin, &len) == -1) CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); else - { - if (family == AF_INET) - current_port = (UINT16)ntohs(straddr.ip4.sin_port); -#ifdef HAVE_IPV6 - else if (family == AF_INET6) - current_port = (UINT16)ntohs(straddr.ip6.sin6_port); -#endif - } + current_port = (UINT16)ntohs(sin.sin_port); return s; } @@ -861,7 +844,7 @@ static boolean UDP_Socket(void) struct my_addrinfo *ai, *runp, hints; int gaie; #ifdef HAVE_IPV6 - const INT32 b_ipv6 = !M_CheckParm("-noipv6"); + const INT32 b_ipv6 = M_CheckParm("-ipv6"); #endif const char *serv; @@ -1173,7 +1156,6 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) SINT8 newnode = -1; struct my_addrinfo *ai = NULL, *runp, hints; int gaie; - size_t i; if (!port || !port[0]) port = DEFAULTPORT; @@ -1201,24 +1183,13 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) while (runp != NULL) { - // test ip address of server - for (i = 0; i < mysocketses; ++i) + // find ip of the server + if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0) { - /* sendto tests that there is a network to this - address */ - if (runp->ai_addr->sa_family == myfamily[i] && - sendto(mysockets[i], NULL, 0, 0, - runp->ai_addr, runp->ai_addrlen) == 0) - { - memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); - break; - } - } - - if (i < mysocketses) - runp = runp->ai_next; - else + memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); break; + } + runp = runp->ai_next; } I_freeaddrinfo(ai); return newnode; diff --git a/src/i_tcp.h b/src/i_tcp.h index ae9983bf1..b6e5b9235 100644 --- a/src/i_tcp.h +++ b/src/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.c b/src/mserv.c index 62cda96e4..bff562c95 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. -// Copyright (C) 2020-2023 by James R. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 2020-2022 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,7 +62,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); @@ -97,8 +97,8 @@ void AddMServCommands(void) CV_RegisterVar(&cv_masterserver_token); CV_RegisterVar(&cv_servername); #ifdef MASTERSERVER - COM_AddCommand("listserv", Command_Listserv_f, 0); - COM_AddCommand("masterserver_update", Update_parameters, COM_LUA); // allows people to updates manually in case you were delisted by accident + COM_AddCommand("listserv", Command_Listserv_f); + COM_AddCommand("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident #endif #endif } diff --git a/src/mserv.h b/src/mserv.h index 07253da85..23b26fbc5 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. -// Copyright (C) 2020-2023 by James R. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 2020-2022 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,7 +33,7 @@ typedef union typedef struct { msg_header_t header; - char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; + char ip[16]; char port[8]; char name[32]; INT32 room; From 77253157899492a2c7aab1967f7995b90c46fbbe Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 28 Dec 2022 16:12:05 +0100 Subject: [PATCH 19/93] Move snake minigame to its own files --- src/Sourcefile | 1 + src/d_clisrv.c | 525 +----------------------------------------------- src/snake.c | 535 +++++++++++++++++++++++++++++++++++++++++++++++++ src/snake.h | 20 ++ 4 files changed, 564 insertions(+), 517 deletions(-) create mode 100644 src/snake.c create mode 100644 src/snake.h diff --git a/src/Sourcefile b/src/Sourcefile index 7c5305000..c55752b09 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -84,6 +84,7 @@ lzf.c vid_copy.s b_bot.c u_list.c +snake.c lua_script.c lua_baselib.c lua_mathlib.c diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3091f3344..be10e4f9b 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -57,6 +57,7 @@ // cl loading screen #include "v_video.h" #include "f_finale.h" +#include "snake.h" #endif // @@ -543,505 +544,7 @@ static cl_mode_t cl_mode = CL_SEARCHING; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list #ifndef NONET -#define SNAKE_SPEED 5 - -#define SNAKE_NUM_BLOCKS_X 20 -#define SNAKE_NUM_BLOCKS_Y 10 -#define SNAKE_BLOCK_SIZE 12 -#define SNAKE_BORDER_SIZE 12 - -#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE) -#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE) - -#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE) -#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1) -#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48) -#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1) - -enum snake_bonustype_s { - SNAKE_BONUS_NONE = 0, - SNAKE_BONUS_SLOW, - SNAKE_BONUS_FAST, - SNAKE_BONUS_GHOST, - SNAKE_BONUS_NUKE, - SNAKE_BONUS_SCISSORS, - SNAKE_BONUS_REVERSE, - SNAKE_BONUS_EGGMAN, - SNAKE_NUM_BONUSES, -}; - -static const char *snake_bonuspatches[] = { - NULL, - "DL_SLOW", - "TVSSC0", - "TVIVC0", - "TVARC0", - "DL_SCISSORS", - "TVRCC0", - "TVEGC0", -}; - -static const char *snake_backgrounds[] = { - "RVPUMICF", - "FRSTRCKF", - "TAR", - "MMFLRB4", - "RVDARKF1", - "RVZWALF1", - "RVZWALF4", - "RVZWALF5", - "RVZGRS02", - "RVZGRS04", -}; - -typedef struct snake_s -{ - boolean paused; - boolean pausepressed; - tic_t time; - tic_t nextupdate; - boolean gameover; - UINT8 background; - - UINT16 snakelength; - enum snake_bonustype_s snakebonus; - tic_t snakebonustime; - UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - - UINT8 applex; - UINT8 appley; - - enum snake_bonustype_s bonustype; - UINT8 bonusx; - UINT8 bonusy; -} snake_t; - -static snake_t *snake = NULL; - -static void Snake_Initialise(void) -{ - if (!snake) - snake = malloc(sizeof(snake_t)); - - snake->paused = false; - snake->pausepressed = false; - snake->time = 0; - snake->nextupdate = SNAKE_SPEED; - snake->gameover = false; - snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds)); - - snake->snakelength = 1; - snake->snakebonus = SNAKE_BONUS_NONE; - snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - snake->snakedir[0] = 0; - snake->snakedir[1] = 0; - - snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - - snake->bonustype = SNAKE_BONUS_NONE; -} - -static UINT8 Snake_GetOppositeDir(UINT8 dir) -{ - if (dir == 1 || dir == 3) - return dir + 1; - else if (dir == 2 || dir == 4) - return dir - 1; - else - return 12 + 5 - dir; -} - -static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) -{ - UINT8 x, y; - UINT16 i; - - do - { - x = M_RandomKey(SNAKE_NUM_BLOCKS_X); - y = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - - for (i = 0; i < snake->snakelength; i++) - if (x == snake->snakex[i] && y == snake->snakey[i]) - break; - } while (i < snake->snakelength || (x == headx && y == heady) - || (x == snake->applex && y == snake->appley) - || (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); - - *freex = x; - *freey = y; -} - -static void Snake_Handle(void) -{ - UINT8 x, y; - UINT8 oldx, oldy; - UINT16 i; - UINT16 joystate = 0; - - // Handle retry - if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER])) - { - Snake_Initialise(); - snake->pausepressed = true; // Avoid accidental pause on respawn - } - - // Handle pause - if (G_PlayerInputDown(0, GC_PAUSE) || gamekeydown[KEY_ENTER]) - { - if (!snake->pausepressed) - snake->paused = !snake->paused; - snake->pausepressed = true; - } - else - snake->pausepressed = false; - - if (snake->paused) - return; - - snake->time++; - - x = snake->snakex[0]; - y = snake->snakey[0]; - oldx = snake->snakex[1]; - oldy = snake->snakey[1]; - - // Update direction - if (G_PlayerInputDown(0, GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) - { - if (snake->snakelength < 2 || x <= oldx) - snake->snakedir[0] = 1; - } - else if (G_PlayerInputDown(0, GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) - { - if (snake->snakelength < 2 || x >= oldx) - snake->snakedir[0] = 2; - } - else if (G_PlayerInputDown(0, GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) - { - if (snake->snakelength < 2 || y <= oldy) - snake->snakedir[0] = 3; - } - else if (G_PlayerInputDown(0, GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) - { - if (snake->snakelength < 2 || y >= oldy) - snake->snakedir[0] = 4; - } - - if (snake->snakebonustime) - { - snake->snakebonustime--; - if (!snake->snakebonustime) - snake->snakebonus = SNAKE_BONUS_NONE; - } - - snake->nextupdate--; - if (snake->nextupdate) - return; - if (snake->snakebonus == SNAKE_BONUS_SLOW) - snake->nextupdate = SNAKE_SPEED * 2; - else if (snake->snakebonus == SNAKE_BONUS_FAST) - snake->nextupdate = SNAKE_SPEED * 2 / 3; - else - snake->nextupdate = SNAKE_SPEED; - - if (snake->gameover) - return; - - // Find new position - switch (snake->snakedir[0]) - { - case 1: - if (x > 0) - x--; - else - snake->gameover = true; - break; - case 2: - if (x < SNAKE_NUM_BLOCKS_X - 1) - x++; - else - snake->gameover = true; - break; - case 3: - if (y > 0) - y--; - else - snake->gameover = true; - break; - case 4: - if (y < SNAKE_NUM_BLOCKS_Y - 1) - y++; - else - snake->gameover = true; - break; - } - - // Check collision with snake - if (snake->snakebonus != SNAKE_BONUS_GHOST) - for (i = 1; i < snake->snakelength - 1; i++) - if (x == snake->snakex[i] && y == snake->snakey[i]) - { - if (snake->snakebonus == SNAKE_BONUS_SCISSORS) - { - snake->snakebonus = SNAKE_BONUS_NONE; - snake->snakelength = i; - S_StartSound(NULL, sfx_adderr); - } - else - snake->gameover = true; - } - - if (snake->gameover) - { - S_StartSound(NULL, sfx_lose); - return; - } - - // Check collision with apple - if (x == snake->applex && y == snake->appley) - { - if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y) - { - snake->snakelength++; - snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2]; - snake->snakey [snake->snakelength - 1] = snake->snakey [snake->snakelength - 2]; - snake->snakedir[snake->snakelength - 1] = snake->snakedir[snake->snakelength - 2]; - } - - // Spawn new apple - Snake_FindFreeSlot(&snake->applex, &snake->appley, x, y); - - // Spawn new bonus - if (!(snake->snakelength % 5)) - { - do - { - snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1; - } while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4 - && (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE)); - - Snake_FindFreeSlot(&snake->bonusx, &snake->bonusy, x, y); - } - - S_StartSound(NULL, sfx_s3k6b); - } - - if (snake->snakelength > 1 && snake->snakedir[0]) - { - UINT8 dir = snake->snakedir[0]; - - oldx = snake->snakex[1]; - oldy = snake->snakey[1]; - - // Move - for (i = snake->snakelength - 1; i > 0; i--) - { - snake->snakex[i] = snake->snakex[i - 1]; - snake->snakey[i] = snake->snakey[i - 1]; - snake->snakedir[i] = snake->snakedir[i - 1]; - } - - // Handle corners - if (x < oldx && dir == 3) - dir = 5; - else if (x > oldx && dir == 3) - dir = 6; - else if (x < oldx && dir == 4) - dir = 7; - else if (x > oldx && dir == 4) - dir = 8; - else if (y < oldy && dir == 1) - dir = 9; - else if (y < oldy && dir == 2) - dir = 10; - else if (y > oldy && dir == 1) - dir = 11; - else if (y > oldy && dir == 2) - dir = 12; - snake->snakedir[1] = dir; - } - - snake->snakex[0] = x; - snake->snakey[0] = y; - - // Check collision with bonus - if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy) - { - S_StartSound(NULL, sfx_ncchip); - - switch (snake->bonustype) - { - case SNAKE_BONUS_SLOW: - snake->snakebonus = SNAKE_BONUS_SLOW; - snake->snakebonustime = 20 * TICRATE; - break; - case SNAKE_BONUS_FAST: - snake->snakebonus = SNAKE_BONUS_FAST; - snake->snakebonustime = 20 * TICRATE; - break; - case SNAKE_BONUS_GHOST: - snake->snakebonus = SNAKE_BONUS_GHOST; - snake->snakebonustime = 10 * TICRATE; - break; - case SNAKE_BONUS_NUKE: - for (i = 0; i < snake->snakelength; i++) - { - snake->snakex [i] = snake->snakex [0]; - snake->snakey [i] = snake->snakey [0]; - snake->snakedir[i] = snake->snakedir[0]; - } - - S_StartSound(NULL, sfx_bkpoof); - break; - case SNAKE_BONUS_SCISSORS: - snake->snakebonus = SNAKE_BONUS_SCISSORS; - snake->snakebonustime = 60 * TICRATE; - break; - case SNAKE_BONUS_REVERSE: - for (i = 0; i < (snake->snakelength + 1) / 2; i++) - { - UINT16 i2 = snake->snakelength - 1 - i; - UINT8 tmpx = snake->snakex [i]; - UINT8 tmpy = snake->snakey [i]; - UINT8 tmpdir = snake->snakedir[i]; - - // Swap first segment with last segment - snake->snakex [i] = snake->snakex [i2]; - snake->snakey [i] = snake->snakey [i2]; - snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]); - snake->snakex [i2] = tmpx; - snake->snakey [i2] = tmpy; - snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir); - } - - snake->snakedir[0] = 0; - - S_StartSound(NULL, sfx_gravch); - break; - default: - if (snake->snakebonus != SNAKE_BONUS_GHOST) - { - snake->gameover = true; - S_StartSound(NULL, sfx_lose); - } - } - - snake->bonustype = SNAKE_BONUS_NONE; - } -} - -static void Snake_Draw(void) -{ - INT16 i; - - // Background - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - - V_DrawFlatFill( - SNAKE_LEFT_X + SNAKE_BORDER_SIZE, - SNAKE_TOP_Y + SNAKE_BORDER_SIZE, - SNAKE_MAP_WIDTH, - SNAKE_MAP_HEIGHT, - W_GetNumForName(snake_backgrounds[snake->background]) - ); - - // Borders - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left - - // Apple - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - FRACUNIT / 4, - 0, - W_CachePatchLongName("DL_APPLE", PU_HUDGFX), - NULL - ); - - // Bonus - if (snake->bonustype != SNAKE_BONUS_NONE) - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT, - FRACUNIT / 2, - 0, - W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX), - NULL - ); - - // Snake - if (!snake->gameover || snake->time % 8 < 8 / 2) // Blink if game over - { - for (i = snake->snakelength - 1; i >= 0; i--) - { - const char *patchname; - UINT8 dir = snake->snakedir[i]; - - if (i == 0) // Head - { - switch (dir) - { - case 1: patchname = "DL_SNAKEHEAD_L"; break; - case 2: patchname = "DL_SNAKEHEAD_R"; break; - case 3: patchname = "DL_SNAKEHEAD_T"; break; - case 4: patchname = "DL_SNAKEHEAD_B"; break; - default: patchname = "DL_SNAKEHEAD_M"; - } - } - else // Body - { - switch (dir) - { - case 1: patchname = "DL_SNAKEBODY_L"; break; - case 2: patchname = "DL_SNAKEBODY_R"; break; - case 3: patchname = "DL_SNAKEBODY_T"; break; - case 4: patchname = "DL_SNAKEBODY_B"; break; - case 5: patchname = "DL_SNAKEBODY_LT"; break; - case 6: patchname = "DL_SNAKEBODY_RT"; break; - case 7: patchname = "DL_SNAKEBODY_LB"; break; - case 8: patchname = "DL_SNAKEBODY_RB"; break; - case 9: patchname = "DL_SNAKEBODY_TL"; break; - case 10: patchname = "DL_SNAKEBODY_TR"; break; - case 11: patchname = "DL_SNAKEBODY_BL"; break; - case 12: patchname = "DL_SNAKEBODY_BR"; break; - default: patchname = "DL_SNAKEBODY_B"; - } - } - - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2, - snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0, - W_CachePatchLongName(patchname, PU_HUDGFX), - NULL - ); - } - } - - // Length - V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); - - // Bonus - if (snake->snakebonus != SNAKE_BONUS_NONE - && (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2)) - V_DrawFixedPatch( - (SNAKE_RIGHT_X + 10) * FRACUNIT, - (SNAKE_TOP_Y + 24) * FRACUNIT, - FRACUNIT / 2, - 0, - W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX), - NULL - ); -} +static void *snake = NULL; static void CL_DrawConnectionStatusBox(void) { @@ -1167,7 +670,7 @@ static inline void CL_DrawConnectionStatus(void) char *filename; if (snake) - Snake_Draw(); + Snake_Draw(snake); // Draw the bottom box. CL_DrawConnectionStatusBox(); @@ -1213,7 +716,7 @@ static inline void CL_DrawConnectionStatus(void) else { if (snake) - Snake_Draw(); + Snake_Draw(snake); CL_DrawConnectionStatusBox(); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, @@ -1950,7 +1453,7 @@ static void M_ConfirmConnect(event_t *ev) if (CL_SendFileRequest()) { cl_mode = CL_DOWNLOADFILES; - Snake_Initialise(); + Snake_Allocate(&snake); } } else @@ -2300,13 +1803,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (waitmore) break; // exit the case -#ifndef NONET - if (snake) - { - free(snake); - snake = NULL; - } -#endif + Snake_Free(&snake); cl_mode = CL_LOADFILES; break; @@ -2401,13 +1898,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic CONS_Printf(M_GetText("Network game synchronization aborted.\n")); M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); -#ifndef NONET - if (snake) - { - free(snake); - snake = NULL; - } -#endif + Snake_Free(&snake); D_QuitNetGame(); CL_Reset(); @@ -2417,7 +1908,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } #ifndef NONET else if (cl_mode == CL_DOWNLOADFILES && snake) - Snake_Handle(); + Snake_Update(snake); #endif if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) diff --git a/src/snake.c b/src/snake.c new file mode 100644 index 000000000..2c80adeb9 --- /dev/null +++ b/src/snake.c @@ -0,0 +1,535 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023-2023 by Louis-Antoine de Moulins de Rochefort. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file snake.c +/// \brief Snake minigame for the download screen. + +#include "snake.h" +#include "g_input.h" +#include "m_random.h" +#include "s_sound.h" +#include "screen.h" +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" + +#define SNAKE_SPEED 5 + +#define SNAKE_NUM_BLOCKS_X 20 +#define SNAKE_NUM_BLOCKS_Y 10 +#define SNAKE_BLOCK_SIZE 12 +#define SNAKE_BORDER_SIZE 12 + +#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE) +#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE) + +#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE) +#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1) +#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48) +#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1) + +enum snake_bonustype_s { + SNAKE_BONUS_NONE = 0, + SNAKE_BONUS_SLOW, + SNAKE_BONUS_FAST, + SNAKE_BONUS_GHOST, + SNAKE_BONUS_NUKE, + SNAKE_BONUS_SCISSORS, + SNAKE_BONUS_REVERSE, + SNAKE_BONUS_EGGMAN, + SNAKE_NUM_BONUSES, +}; + +typedef struct snake_s +{ + boolean paused; + boolean pausepressed; + tic_t time; + tic_t nextupdate; + boolean gameover; + UINT8 background; + + UINT16 snakelength; + enum snake_bonustype_s snakebonus; + tic_t snakebonustime; + UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + + UINT8 applex; + UINT8 appley; + + enum snake_bonustype_s bonustype; + UINT8 bonusx; + UINT8 bonusy; +} snake_t; + +static const char *snake_bonuspatches[] = { + NULL, + "DL_SLOW", + "TVSSC0", + "TVIVC0", + "TVARC0", + "DL_SCISSORS", + "TVRCC0", + "TVEGC0", +}; + +static const char *snake_backgrounds[] = { + "RVPUMICF", + "FRSTRCKF", + "TAR", + "MMFLRB4", + "RVDARKF1", + "RVZWALF1", + "RVZWALF4", + "RVZWALF5", + "RVZGRS02", + "RVZGRS04", +}; + +static void Snake_Initialise(snake_t *snake) +{ + snake->paused = false; + snake->pausepressed = false; + snake->time = 0; + snake->nextupdate = SNAKE_SPEED; + snake->gameover = false; + snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds)); + + snake->snakelength = 1; + snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X); + snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + snake->snakedir[0] = 0; + snake->snakedir[1] = 0; + + snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X); + snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + + snake->bonustype = SNAKE_BONUS_NONE; +} + +static UINT8 Snake_GetOppositeDir(UINT8 dir) +{ + if (dir == 1 || dir == 3) + return dir + 1; + else if (dir == 2 || dir == 4) + return dir - 1; + else + return 12 + 5 - dir; +} + +static void Snake_FindFreeSlot(snake_t *snake, UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) +{ + UINT8 x, y; + UINT16 i; + + do + { + x = M_RandomKey(SNAKE_NUM_BLOCKS_X); + y = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + + for (i = 0; i < snake->snakelength; i++) + if (x == snake->snakex[i] && y == snake->snakey[i]) + break; + } while (i < snake->snakelength || (x == headx && y == heady) + || (x == snake->applex && y == snake->appley) + || (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); + + *freex = x; + *freey = y; +} + +void Snake_Allocate(void **opaque) +{ + if (*opaque) + Snake_Free(opaque); + *opaque = malloc(sizeof(snake_t)); + Snake_Initialise(*opaque); +} + +void Snake_Update(void *opaque) +{ + UINT8 x, y; + UINT8 oldx, oldy; + UINT16 i; + UINT16 joystate = 0; + + snake_t *snake = opaque; + + // Handle retry + if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER])) + { + Snake_Initialise(snake); + snake->pausepressed = true; // Avoid accidental pause on respawn + } + + // Handle pause + if (G_PlayerInputDown(0, GC_PAUSE) || gamekeydown[KEY_ENTER]) + { + if (!snake->pausepressed) + snake->paused = !snake->paused; + snake->pausepressed = true; + } + else + snake->pausepressed = false; + + if (snake->paused) + return; + + snake->time++; + + x = snake->snakex[0]; + y = snake->snakey[0]; + oldx = snake->snakex[1]; + oldy = snake->snakey[1]; + + // Update direction + if (G_PlayerInputDown(0, GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) + { + if (snake->snakelength < 2 || x <= oldx) + snake->snakedir[0] = 1; + } + else if (G_PlayerInputDown(0, GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) + { + if (snake->snakelength < 2 || x >= oldx) + snake->snakedir[0] = 2; + } + else if (G_PlayerInputDown(0, GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) + { + if (snake->snakelength < 2 || y <= oldy) + snake->snakedir[0] = 3; + } + else if (G_PlayerInputDown(0, GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) + { + if (snake->snakelength < 2 || y >= oldy) + snake->snakedir[0] = 4; + } + + if (snake->snakebonustime) + { + snake->snakebonustime--; + if (!snake->snakebonustime) + snake->snakebonus = SNAKE_BONUS_NONE; + } + + snake->nextupdate--; + if (snake->nextupdate) + return; + if (snake->snakebonus == SNAKE_BONUS_SLOW) + snake->nextupdate = SNAKE_SPEED * 2; + else if (snake->snakebonus == SNAKE_BONUS_FAST) + snake->nextupdate = SNAKE_SPEED * 2 / 3; + else + snake->nextupdate = SNAKE_SPEED; + + if (snake->gameover) + return; + + // Find new position + switch (snake->snakedir[0]) + { + case 1: + if (x > 0) + x--; + else + snake->gameover = true; + break; + case 2: + if (x < SNAKE_NUM_BLOCKS_X - 1) + x++; + else + snake->gameover = true; + break; + case 3: + if (y > 0) + y--; + else + snake->gameover = true; + break; + case 4: + if (y < SNAKE_NUM_BLOCKS_Y - 1) + y++; + else + snake->gameover = true; + break; + } + + // Check collision with snake + if (snake->snakebonus != SNAKE_BONUS_GHOST) + for (i = 1; i < snake->snakelength - 1; i++) + if (x == snake->snakex[i] && y == snake->snakey[i]) + { + if (snake->snakebonus == SNAKE_BONUS_SCISSORS) + { + snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakelength = i; + S_StartSound(NULL, sfx_adderr); + } + else + snake->gameover = true; + } + + if (snake->gameover) + { + S_StartSound(NULL, sfx_lose); + return; + } + + // Check collision with apple + if (x == snake->applex && y == snake->appley) + { + if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y) + { + snake->snakelength++; + snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2]; + snake->snakey [snake->snakelength - 1] = snake->snakey [snake->snakelength - 2]; + snake->snakedir[snake->snakelength - 1] = snake->snakedir[snake->snakelength - 2]; + } + + // Spawn new apple + Snake_FindFreeSlot(snake, &snake->applex, &snake->appley, x, y); + + // Spawn new bonus + if (!(snake->snakelength % 5)) + { + do + { + snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1; + } while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4 + && (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE)); + + Snake_FindFreeSlot(snake, &snake->bonusx, &snake->bonusy, x, y); + } + + S_StartSound(NULL, sfx_s3k6b); + } + + if (snake->snakelength > 1 && snake->snakedir[0]) + { + UINT8 dir = snake->snakedir[0]; + + oldx = snake->snakex[1]; + oldy = snake->snakey[1]; + + // Move + for (i = snake->snakelength - 1; i > 0; i--) + { + snake->snakex[i] = snake->snakex[i - 1]; + snake->snakey[i] = snake->snakey[i - 1]; + snake->snakedir[i] = snake->snakedir[i - 1]; + } + + // Handle corners + if (x < oldx && dir == 3) + dir = 5; + else if (x > oldx && dir == 3) + dir = 6; + else if (x < oldx && dir == 4) + dir = 7; + else if (x > oldx && dir == 4) + dir = 8; + else if (y < oldy && dir == 1) + dir = 9; + else if (y < oldy && dir == 2) + dir = 10; + else if (y > oldy && dir == 1) + dir = 11; + else if (y > oldy && dir == 2) + dir = 12; + snake->snakedir[1] = dir; + } + + snake->snakex[0] = x; + snake->snakey[0] = y; + + // Check collision with bonus + if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy) + { + S_StartSound(NULL, sfx_ncchip); + + switch (snake->bonustype) + { + case SNAKE_BONUS_SLOW: + snake->snakebonus = SNAKE_BONUS_SLOW; + snake->snakebonustime = 20 * TICRATE; + break; + case SNAKE_BONUS_FAST: + snake->snakebonus = SNAKE_BONUS_FAST; + snake->snakebonustime = 20 * TICRATE; + break; + case SNAKE_BONUS_GHOST: + snake->snakebonus = SNAKE_BONUS_GHOST; + snake->snakebonustime = 10 * TICRATE; + break; + case SNAKE_BONUS_NUKE: + for (i = 0; i < snake->snakelength; i++) + { + snake->snakex [i] = snake->snakex [0]; + snake->snakey [i] = snake->snakey [0]; + snake->snakedir[i] = snake->snakedir[0]; + } + + S_StartSound(NULL, sfx_bkpoof); + break; + case SNAKE_BONUS_SCISSORS: + snake->snakebonus = SNAKE_BONUS_SCISSORS; + snake->snakebonustime = 60 * TICRATE; + break; + case SNAKE_BONUS_REVERSE: + for (i = 0; i < (snake->snakelength + 1) / 2; i++) + { + UINT16 i2 = snake->snakelength - 1 - i; + UINT8 tmpx = snake->snakex [i]; + UINT8 tmpy = snake->snakey [i]; + UINT8 tmpdir = snake->snakedir[i]; + + // Swap first segment with last segment + snake->snakex [i] = snake->snakex [i2]; + snake->snakey [i] = snake->snakey [i2]; + snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]); + snake->snakex [i2] = tmpx; + snake->snakey [i2] = tmpy; + snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir); + } + + snake->snakedir[0] = 0; + + S_StartSound(NULL, sfx_gravch); + break; + default: + if (snake->snakebonus != SNAKE_BONUS_GHOST) + { + snake->gameover = true; + S_StartSound(NULL, sfx_lose); + } + } + + snake->bonustype = SNAKE_BONUS_NONE; + } +} + +void Snake_Draw(void *opaque) +{ + INT16 i; + + snake_t *snake = opaque; + + // Background + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + V_DrawFlatFill( + SNAKE_LEFT_X + SNAKE_BORDER_SIZE, + SNAKE_TOP_Y + SNAKE_BORDER_SIZE, + SNAKE_MAP_WIDTH, + SNAKE_MAP_HEIGHT, + W_GetNumForName(snake_backgrounds[snake->background]) + ); + + // Borders + V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top + V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right + V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom + V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left + + // Apple + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + FRACUNIT / 4, + 0, + W_CachePatchLongName("DL_APPLE", PU_HUDGFX), + NULL + ); + + // Bonus + if (snake->bonustype != SNAKE_BONUS_NONE) + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT, + FRACUNIT / 2, + 0, + W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX), + NULL + ); + + // Snake + if (!snake->gameover || snake->time % 8 < 8 / 2) // Blink if game over + { + for (i = snake->snakelength - 1; i >= 0; i--) + { + const char *patchname; + UINT8 dir = snake->snakedir[i]; + + if (i == 0) // Head + { + switch (dir) + { + case 1: patchname = "DL_SNAKEHEAD_L"; break; + case 2: patchname = "DL_SNAKEHEAD_R"; break; + case 3: patchname = "DL_SNAKEHEAD_T"; break; + case 4: patchname = "DL_SNAKEHEAD_B"; break; + default: patchname = "DL_SNAKEHEAD_M"; + } + } + else // Body + { + switch (dir) + { + case 1: patchname = "DL_SNAKEBODY_L"; break; + case 2: patchname = "DL_SNAKEBODY_R"; break; + case 3: patchname = "DL_SNAKEBODY_T"; break; + case 4: patchname = "DL_SNAKEBODY_B"; break; + case 5: patchname = "DL_SNAKEBODY_LT"; break; + case 6: patchname = "DL_SNAKEBODY_RT"; break; + case 7: patchname = "DL_SNAKEBODY_LB"; break; + case 8: patchname = "DL_SNAKEBODY_RB"; break; + case 9: patchname = "DL_SNAKEBODY_TL"; break; + case 10: patchname = "DL_SNAKEBODY_TR"; break; + case 11: patchname = "DL_SNAKEBODY_BL"; break; + case 12: patchname = "DL_SNAKEBODY_BR"; break; + default: patchname = "DL_SNAKEBODY_B"; + } + } + + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2, + snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0, + W_CachePatchLongName(patchname, PU_HUDGFX), + NULL + ); + } + } + + // Length + V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); + + // Bonus + if (snake->snakebonus != SNAKE_BONUS_NONE + && (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2)) + V_DrawFixedPatch( + (SNAKE_RIGHT_X + 10) * FRACUNIT, + (SNAKE_TOP_Y + 24) * FRACUNIT, + FRACUNIT / 2, + 0, + W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX), + NULL + ); +} + +void Snake_Free(void **opaque) +{ + if (*opaque) + { + free(opaque); + *opaque = NULL; + } +} diff --git a/src/snake.h b/src/snake.h new file mode 100644 index 000000000..a3106bb0f --- /dev/null +++ b/src/snake.h @@ -0,0 +1,20 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023-2023 by Louis-Antoine de Moulins de Rochefort. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file snake.h +/// \brief Snake minigame for the download screen. + +#ifndef __SNAKE__ +#define __SNAKE__ + +void Snake_Allocate(void **opaque); +void Snake_Update(void *opaque); +void Snake_Draw(void *opaque); +void Snake_Free(void **opaque); + +#endif From 60f150a826e608d3fe57eaa67d44b160ecbc198e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Wed, 28 Dec 2022 18:50:00 +0100 Subject: [PATCH 20/93] Remove snake_ prefix --- src/snake.c | 198 ++++++++++++++++++++++++++-------------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/src/snake.c b/src/snake.c index 2c80adeb9..21e79401d 100644 --- a/src/snake.c +++ b/src/snake.c @@ -18,31 +18,31 @@ #include "w_wad.h" #include "z_zone.h" -#define SNAKE_SPEED 5 +#define SPEED 5 -#define SNAKE_NUM_BLOCKS_X 20 -#define SNAKE_NUM_BLOCKS_Y 10 -#define SNAKE_BLOCK_SIZE 12 -#define SNAKE_BORDER_SIZE 12 +#define NUM_BLOCKS_X 20 +#define NUM_BLOCKS_Y 10 +#define BLOCK_SIZE 12 +#define BORDER_SIZE 12 -#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE) -#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE) +#define MAP_WIDTH (NUM_BLOCKS_X * BLOCK_SIZE) +#define MAP_HEIGHT (NUM_BLOCKS_Y * BLOCK_SIZE) -#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE) -#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1) -#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48) -#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1) +#define LEFT_X ((BASEVIDWIDTH - MAP_WIDTH) / 2 - BORDER_SIZE) +#define RIGHT_X (LEFT_X + MAP_WIDTH + BORDER_SIZE * 2 - 1) +#define BOTTOM_Y (BASEVIDHEIGHT - 48) +#define TOP_Y (BOTTOM_Y - MAP_HEIGHT - BORDER_SIZE * 2 + 1) -enum snake_bonustype_s { - SNAKE_BONUS_NONE = 0, - SNAKE_BONUS_SLOW, - SNAKE_BONUS_FAST, - SNAKE_BONUS_GHOST, - SNAKE_BONUS_NUKE, - SNAKE_BONUS_SCISSORS, - SNAKE_BONUS_REVERSE, - SNAKE_BONUS_EGGMAN, - SNAKE_NUM_BONUSES, +enum bonustype_s { + BONUS_NONE = 0, + BONUS_SLOW, + BONUS_FAST, + BONUS_GHOST, + BONUS_NUKE, + BONUS_SCISSORS, + BONUS_REVERSE, + BONUS_EGGMAN, + NUM_BONUSES, }; typedef struct snake_s @@ -55,21 +55,21 @@ typedef struct snake_s UINT8 background; UINT16 snakelength; - enum snake_bonustype_s snakebonus; + enum bonustype_s snakebonus; tic_t snakebonustime; - UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + UINT8 snakex[NUM_BLOCKS_X * NUM_BLOCKS_Y]; + UINT8 snakey[NUM_BLOCKS_X * NUM_BLOCKS_Y]; + UINT8 snakedir[NUM_BLOCKS_X * NUM_BLOCKS_Y]; UINT8 applex; UINT8 appley; - enum snake_bonustype_s bonustype; + enum bonustype_s bonustype; UINT8 bonusx; UINT8 bonusy; } snake_t; -static const char *snake_bonuspatches[] = { +static const char *bonuspatches[] = { NULL, "DL_SLOW", "TVSSC0", @@ -80,7 +80,7 @@ static const char *snake_bonuspatches[] = { "TVEGC0", }; -static const char *snake_backgrounds[] = { +static const char *backgrounds[] = { "RVPUMICF", "FRSTRCKF", "TAR", @@ -93,29 +93,29 @@ static const char *snake_backgrounds[] = { "RVZGRS04", }; -static void Snake_Initialise(snake_t *snake) +static void Initialise(snake_t *snake) { snake->paused = false; snake->pausepressed = false; snake->time = 0; - snake->nextupdate = SNAKE_SPEED; + snake->nextupdate = SPEED; snake->gameover = false; - snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds)); + snake->background = M_RandomKey(sizeof(backgrounds) / sizeof(*backgrounds)); snake->snakelength = 1; - snake->snakebonus = SNAKE_BONUS_NONE; - snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + snake->snakebonus = BONUS_NONE; + snake->snakex[0] = M_RandomKey(NUM_BLOCKS_X); + snake->snakey[0] = M_RandomKey(NUM_BLOCKS_Y); snake->snakedir[0] = 0; snake->snakedir[1] = 0; - snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + snake->applex = M_RandomKey(NUM_BLOCKS_X); + snake->appley = M_RandomKey(NUM_BLOCKS_Y); - snake->bonustype = SNAKE_BONUS_NONE; + snake->bonustype = BONUS_NONE; } -static UINT8 Snake_GetOppositeDir(UINT8 dir) +static UINT8 GetOppositeDir(UINT8 dir) { if (dir == 1 || dir == 3) return dir + 1; @@ -125,22 +125,22 @@ static UINT8 Snake_GetOppositeDir(UINT8 dir) return 12 + 5 - dir; } -static void Snake_FindFreeSlot(snake_t *snake, UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) +static void FindFreeSlot(snake_t *snake, UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) { UINT8 x, y; UINT16 i; do { - x = M_RandomKey(SNAKE_NUM_BLOCKS_X); - y = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + x = M_RandomKey(NUM_BLOCKS_X); + y = M_RandomKey(NUM_BLOCKS_Y); for (i = 0; i < snake->snakelength; i++) if (x == snake->snakex[i] && y == snake->snakey[i]) break; } while (i < snake->snakelength || (x == headx && y == heady) || (x == snake->applex && y == snake->appley) - || (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); + || (snake->bonustype != BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); *freex = x; *freey = y; @@ -151,7 +151,7 @@ void Snake_Allocate(void **opaque) if (*opaque) Snake_Free(opaque); *opaque = malloc(sizeof(snake_t)); - Snake_Initialise(*opaque); + Initialise(*opaque); } void Snake_Update(void *opaque) @@ -166,7 +166,7 @@ void Snake_Update(void *opaque) // Handle retry if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER])) { - Snake_Initialise(snake); + Initialise(snake); snake->pausepressed = true; // Avoid accidental pause on respawn } @@ -216,18 +216,18 @@ void Snake_Update(void *opaque) { snake->snakebonustime--; if (!snake->snakebonustime) - snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakebonus = BONUS_NONE; } snake->nextupdate--; if (snake->nextupdate) return; - if (snake->snakebonus == SNAKE_BONUS_SLOW) - snake->nextupdate = SNAKE_SPEED * 2; - else if (snake->snakebonus == SNAKE_BONUS_FAST) - snake->nextupdate = SNAKE_SPEED * 2 / 3; + if (snake->snakebonus == BONUS_SLOW) + snake->nextupdate = SPEED * 2; + else if (snake->snakebonus == BONUS_FAST) + snake->nextupdate = SPEED * 2 / 3; else - snake->nextupdate = SNAKE_SPEED; + snake->nextupdate = SPEED; if (snake->gameover) return; @@ -242,7 +242,7 @@ void Snake_Update(void *opaque) snake->gameover = true; break; case 2: - if (x < SNAKE_NUM_BLOCKS_X - 1) + if (x < NUM_BLOCKS_X - 1) x++; else snake->gameover = true; @@ -254,7 +254,7 @@ void Snake_Update(void *opaque) snake->gameover = true; break; case 4: - if (y < SNAKE_NUM_BLOCKS_Y - 1) + if (y < NUM_BLOCKS_Y - 1) y++; else snake->gameover = true; @@ -262,13 +262,13 @@ void Snake_Update(void *opaque) } // Check collision with snake - if (snake->snakebonus != SNAKE_BONUS_GHOST) + if (snake->snakebonus != BONUS_GHOST) for (i = 1; i < snake->snakelength - 1; i++) if (x == snake->snakex[i] && y == snake->snakey[i]) { - if (snake->snakebonus == SNAKE_BONUS_SCISSORS) + if (snake->snakebonus == BONUS_SCISSORS) { - snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakebonus = BONUS_NONE; snake->snakelength = i; S_StartSound(NULL, sfx_adderr); } @@ -285,7 +285,7 @@ void Snake_Update(void *opaque) // Check collision with apple if (x == snake->applex && y == snake->appley) { - if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y) + if (snake->snakelength + 3 < NUM_BLOCKS_X * NUM_BLOCKS_Y) { snake->snakelength++; snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2]; @@ -294,18 +294,18 @@ void Snake_Update(void *opaque) } // Spawn new apple - Snake_FindFreeSlot(snake, &snake->applex, &snake->appley, x, y); + FindFreeSlot(snake, &snake->applex, &snake->appley, x, y); // Spawn new bonus if (!(snake->snakelength % 5)) { do { - snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1; - } while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4 - && (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE)); + snake->bonustype = M_RandomKey(NUM_BONUSES - 1) + 1; + } while (snake->snakelength > NUM_BLOCKS_X * NUM_BLOCKS_Y * 3 / 4 + && (snake->bonustype == BONUS_EGGMAN || snake->bonustype == BONUS_FAST || snake->bonustype == BONUS_REVERSE)); - Snake_FindFreeSlot(snake, &snake->bonusx, &snake->bonusy, x, y); + FindFreeSlot(snake, &snake->bonusx, &snake->bonusy, x, y); } S_StartSound(NULL, sfx_s3k6b); @@ -350,25 +350,25 @@ void Snake_Update(void *opaque) snake->snakey[0] = y; // Check collision with bonus - if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy) + if (snake->bonustype != BONUS_NONE && x == snake->bonusx && y == snake->bonusy) { S_StartSound(NULL, sfx_ncchip); switch (snake->bonustype) { - case SNAKE_BONUS_SLOW: - snake->snakebonus = SNAKE_BONUS_SLOW; + case BONUS_SLOW: + snake->snakebonus = BONUS_SLOW; snake->snakebonustime = 20 * TICRATE; break; - case SNAKE_BONUS_FAST: - snake->snakebonus = SNAKE_BONUS_FAST; + case BONUS_FAST: + snake->snakebonus = BONUS_FAST; snake->snakebonustime = 20 * TICRATE; break; - case SNAKE_BONUS_GHOST: - snake->snakebonus = SNAKE_BONUS_GHOST; + case BONUS_GHOST: + snake->snakebonus = BONUS_GHOST; snake->snakebonustime = 10 * TICRATE; break; - case SNAKE_BONUS_NUKE: + case BONUS_NUKE: for (i = 0; i < snake->snakelength; i++) { snake->snakex [i] = snake->snakex [0]; @@ -378,11 +378,11 @@ void Snake_Update(void *opaque) S_StartSound(NULL, sfx_bkpoof); break; - case SNAKE_BONUS_SCISSORS: - snake->snakebonus = SNAKE_BONUS_SCISSORS; + case BONUS_SCISSORS: + snake->snakebonus = BONUS_SCISSORS; snake->snakebonustime = 60 * TICRATE; break; - case SNAKE_BONUS_REVERSE: + case BONUS_REVERSE: for (i = 0; i < (snake->snakelength + 1) / 2; i++) { UINT16 i2 = snake->snakelength - 1 - i; @@ -393,10 +393,10 @@ void Snake_Update(void *opaque) // Swap first segment with last segment snake->snakex [i] = snake->snakex [i2]; snake->snakey [i] = snake->snakey [i2]; - snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]); + snake->snakedir[i] = GetOppositeDir(snake->snakedir[i2]); snake->snakex [i2] = tmpx; snake->snakey [i2] = tmpy; - snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir); + snake->snakedir[i2] = GetOppositeDir(tmpdir); } snake->snakedir[0] = 0; @@ -404,14 +404,14 @@ void Snake_Update(void *opaque) S_StartSound(NULL, sfx_gravch); break; default: - if (snake->snakebonus != SNAKE_BONUS_GHOST) + if (snake->snakebonus != BONUS_GHOST) { snake->gameover = true; S_StartSound(NULL, sfx_lose); } } - snake->bonustype = SNAKE_BONUS_NONE; + snake->bonustype = BONUS_NONE; } } @@ -425,23 +425,23 @@ void Snake_Draw(void *opaque) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFlatFill( - SNAKE_LEFT_X + SNAKE_BORDER_SIZE, - SNAKE_TOP_Y + SNAKE_BORDER_SIZE, - SNAKE_MAP_WIDTH, - SNAKE_MAP_HEIGHT, - W_GetNumForName(snake_backgrounds[snake->background]) + LEFT_X + BORDER_SIZE, + TOP_Y + BORDER_SIZE, + MAP_WIDTH, + MAP_HEIGHT, + W_GetNumForName(backgrounds[snake->background]) ); // Borders - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left + V_DrawFill(LEFT_X, TOP_Y, BORDER_SIZE + MAP_WIDTH, BORDER_SIZE, 242); // Top + V_DrawFill(LEFT_X + BORDER_SIZE + MAP_WIDTH, TOP_Y, BORDER_SIZE, BORDER_SIZE + MAP_HEIGHT, 242); // Right + V_DrawFill(LEFT_X + BORDER_SIZE, TOP_Y + BORDER_SIZE + MAP_HEIGHT, BORDER_SIZE + MAP_WIDTH, BORDER_SIZE, 242); // Bottom + V_DrawFill(LEFT_X, TOP_Y + BORDER_SIZE, BORDER_SIZE, BORDER_SIZE + MAP_HEIGHT, 242); // Left // Apple V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (LEFT_X + BORDER_SIZE + snake->applex * BLOCK_SIZE + BLOCK_SIZE / 2) * FRACUNIT, + (TOP_Y + BORDER_SIZE + snake->appley * BLOCK_SIZE + BLOCK_SIZE / 2) * FRACUNIT, FRACUNIT / 4, 0, W_CachePatchLongName("DL_APPLE", PU_HUDGFX), @@ -449,13 +449,13 @@ void Snake_Draw(void *opaque) ); // Bonus - if (snake->bonustype != SNAKE_BONUS_NONE) + if (snake->bonustype != BONUS_NONE) V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT, + (LEFT_X + BORDER_SIZE + snake->bonusx * BLOCK_SIZE + BLOCK_SIZE / 2 ) * FRACUNIT, + (TOP_Y + BORDER_SIZE + snake->bonusy * BLOCK_SIZE + BLOCK_SIZE / 2 + 4) * FRACUNIT, FRACUNIT / 2, 0, - W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX), + W_CachePatchLongName(bonuspatches[snake->bonustype], PU_HUDGFX), NULL ); @@ -499,10 +499,10 @@ void Snake_Draw(void *opaque) } V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (LEFT_X + BORDER_SIZE + snake->snakex[i] * BLOCK_SIZE + BLOCK_SIZE / 2) * FRACUNIT, + (TOP_Y + BORDER_SIZE + snake->snakey[i] * BLOCK_SIZE + BLOCK_SIZE / 2) * FRACUNIT, i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2, - snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0, + snake->snakebonus == BONUS_GHOST ? V_TRANSLUCENT : 0, W_CachePatchLongName(patchname, PU_HUDGFX), NULL ); @@ -510,17 +510,17 @@ void Snake_Draw(void *opaque) } // Length - V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); + V_DrawString(RIGHT_X + 4, TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); // Bonus - if (snake->snakebonus != SNAKE_BONUS_NONE + if (snake->snakebonus != BONUS_NONE && (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2)) V_DrawFixedPatch( - (SNAKE_RIGHT_X + 10) * FRACUNIT, - (SNAKE_TOP_Y + 24) * FRACUNIT, + (RIGHT_X + 10) * FRACUNIT, + (TOP_Y + 24) * FRACUNIT, FRACUNIT / 2, 0, - W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX), + W_CachePatchLongName(bonuspatches[snake->snakebonus], PU_HUDGFX), NULL ); } From 27b500ce9aa021493a85ba46824960a1f24f06c7 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 10:23:12 +0100 Subject: [PATCH 21/93] Split packet handling switch into functions --- src/d_clisrv.c | 1111 ++++++++++++++++++++++++------------------------ src/d_netfil.c | 49 ++- src/d_netfil.h | 8 +- 3 files changed, 605 insertions(+), 563 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index be10e4f9b..d3f6854c7 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3677,8 +3677,531 @@ static void HandleServerInfo(SINT8 node) } #endif -static void PT_WillResendGamestate(void) +// Helper function for packets that should only be sent by the server +// If it is NOT from the server, bail out and close the connection! +static boolean ServerOnly(SINT8 node) { + if (node == servernode) + return false; + + Net_CloseConnection(node); + return true; +} + +static void PT_AskInfoViaMS(SINT8 node) +{ + Net_CloseConnection(node); +} + +static void PT_TellFilesNeeded(SINT8 node) +{ + if (server && serverrunning) + { + UINT8 *p; + INT32 firstfile = netbuffer->u.filesneedednum; + + netbuffer->packettype = PT_MOREFILESNEEDED; + netbuffer->u.filesneededcfg.first = firstfile; + netbuffer->u.filesneededcfg.more = 0; + + p = PutFileNeeded(firstfile); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); + } + else // Shouldn't get this if you aren't the server...? + Net_CloseConnection(node); +} + +static void PT_MoreFilesNeeded(SINT8 node) +{ + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) + { + D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); + if (!netbuffer->u.filesneededcfg.more) + cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list + } +} + +static void PT_AskInfo(SINT8 node) +{ + if (server && serverrunning) + { + SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); + SV_SendPlayerInfo(node); // Send extra info + } + Net_CloseConnection(node); +} + +// Negative response of client join request +static void PT_ServerRefuse(SINT8 node) +{ + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + if (cl_mode == CL_WAITJOINRESPONSE) + { + // Save the reason so it can be displayed after quitting the netgame + char *reason = strdup(netbuffer->u.serverrefuse.reason); + if (!reason) + I_Error("Out of memory!\n"); + + 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); + return; + } + + 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. + cl_mode = CL_ABORTED; + } +} + +// Positive response of client join request +static void PT_ServerCFG(SINT8 node) +{ + if (server && serverrunning && node != servernode) + { // but wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + /// \note how would this happen? and is it doing the right thing if it does? + if (cl_mode != CL_WAITJOINRESPONSE) + return; + + if (client) + { + maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); + G_SetGametype(netbuffer->u.servercfg.gametype); + modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + } + + nodeingame[(UINT8)servernode] = true; + serverplayer = netbuffer->u.servercfg.serverplayer; + doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); + mynode = netbuffer->u.servercfg.clientnode; + if (serverplayer >= 0) + playernode[(UINT8)serverplayer] = servernode; + + if (netgame) +#ifndef NONET + CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); +#else + CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); +#endif + DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); + +#ifndef NONET + /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? + /// Shouldn't them be downloaded even at intermission time? + /// Also, according to HandleConnect, the server will send the savegame even during intermission... + if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || + netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) + cl_mode = CL_DOWNLOADSAVEGAME; + else +#endif + cl_mode = CL_CONNECTED; +} + +static void PT_ClientCmd(SINT8 node, INT32 netconsole) +{ + tic_t realend, realstart; + + if (client) + return; + + // To save bytes, only the low byte of tic numbers are sent + // Use ExpandTics to figure out what the rest of the bytes are + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); + + if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS + || netbuffer->packettype == PT_NODEKEEPALIVEMIS + || supposedtics[node] < realend) + { + supposedtics[node] = realend; + } + // Discard out of order packet + if (nettics[node] > realend) + { + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); + return; + } + + // Update the nettics + nettics[node] = realend; + + // Don't do anything for packets of type NODEKEEPALIVE? + if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + return; + + // As long as clients send valid ticcmds, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + freezetimeout[node] = I_GetTime() + connectiontimeout; + + // Copy ticcmd + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + + // Check ticcmd for "speed hacks" + if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE + || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); + //D_Clearticcmd(k); + + SendKick(netconsole, KICK_MSG_CON_FAIL); + return; + } + + // Splitscreen cmd + if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) + && nodetoplayer2[node] >= 0) + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + &netbuffer->u.client2pak.cmd2, 1); + + // Check player consistancy during the level + if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL + && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) +#ifndef NONET + && !SV_ResendingSavegameToAnyone() +#endif + && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()) + { + if (cv_resynchattempts.value) + { + // Tell the client we are about to resend them the gamestate + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + HSendPacket(node, true, 0, 0); + + resendingsavegame[node] = true; + + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + return; + } + else + { + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + return; + } + } +} + +static void PT_TextCmd(SINT8 node, INT32 netconsole) +{ + if (client) + return; + + // splitscreen special + if (netbuffer->packettype == PT_TEXTCMD2) + netconsole = nodetoplayer2[node]; + + if (netconsole < 0 || netconsole >= MAXPLAYERS) + Net_UnAcknowledgePacket(node); + else + { + size_t j; + tic_t tic = maketic; + UINT8 *textcmd; + + // ignore if the textcmd has a reported size of zero + // this shouldn't be sent at all + if (!netbuffer->u.textcmd[0]) + { + DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // ignore if the textcmd size var is actually larger than it should be + // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) + { + DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // check if tic that we are making isn't too large else we cannot send it :( + // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time + j = software_MAXPACKETLENGTH + - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + + (doomcom->numslots+1)*sizeof(ticcmd_t)); + + // search a tic that have enougth space in the ticcmd + while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), + (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) + && tic < firstticstosend + BACKUPTICS) + tic++; + + if (tic >= firstticstosend + BACKUPTICS) + { + DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " + "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), + maketic, firstticstosend, node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // Make sure we have a buffer + if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); + + DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", + tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); + + M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; + } +} + +static void PT_Login(SINT8 node, INT32 netconsole) +{ + (void)node; + + if (client) + return; + +#ifndef NOMD5 + UINT8 finalmd5[16];/* Well, it's the cool thing to do? */ + + if (doomcom->datalength < 16)/* ignore partial sends */ + return; + + if (!adminpasswordset) + { + CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]); + return; + } + + // Do the final pass to compare with the sent md5 + D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5); + + if (!memcmp(netbuffer->u.md5sum, finalmd5, 16)) + { + CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]); + COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately + } + else + CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); +#else + (void)netconsole; +#endif +} + +static void PT_ClientQuit(SINT8 node, INT32 netconsole) +{ + if (client) + return; + + if (!nodeingame[node]) + { + Net_CloseConnection(node); + return; + } + + // nodeingame will be put false in the execution of kick command + // this allow to send some packets to the quitting client to have their ack back + nodewaiting[node] = 0; + if (netconsole != -1 && playeringame[netconsole]) + { + UINT8 kickmsg; + + if (netbuffer->packettype == PT_NODETIMEOUT) + kickmsg = KICK_MSG_TIMEOUT; + else + kickmsg = KICK_MSG_PLAYER_QUIT; + kickmsg |= KICK_MSG_KEEP_BODY; + + SendKick(netconsole, kickmsg); + nodetoplayer[node] = -1; + + if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 + && playeringame[(UINT8)nodetoplayer2[node]]) + { + SendKick(nodetoplayer2[node], kickmsg); + nodetoplayer2[node] = -1; + } + } + Net_CloseConnection(node); + nodeingame[node] = false; +} + +static void PT_CanReceiveGamestate(SINT8 node) +{ +#ifndef NONET + if (client || sendingsavegame[node]) + return; + + CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); + + SV_SendSaveGame(node, true); // Resend a complete game state + resendingsavegame[node] = true; +#else + (void)node; +#endif +} + +static void PT_AskLuaFile(SINT8 node) +{ + if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) + AddLuaFileToSendQueue(node, luafiletransfers->realfilename); +} + +static void PT_HasLuaFile(SINT8 node) +{ + if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING) + SV_HandleLuaFileSent(node); +} + +static void PT_ReceivedGamestate(SINT8 node) +{ + sendingsavegame[node] = false; + resendingsavegame[node] = false; + savegameresendcooldown[node] = I_GetTime() + 5 * TICRATE; +} + +static void PT_ServerTics(SINT8 node, INT32 netconsole) +{ + UINT8 *pak, *txtpak, numtxtpak; + tic_t realend, realstart; + + if (!nodeingame[node]) + { + // Do not remove my own server (we have just get a out of order packet) + if (node != servernode) + { + DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); + Net_CloseConnection(node); + } + return; + } + + // Only accept PT_SERVERTICS from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + realstart = netbuffer->u.serverpak.starttic; + realend = realstart + netbuffer->u.serverpak.numtics; + + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; + + if (realend > gametic + CLIENTBACKUPTICS) + realend = gametic + CLIENTBACKUPTICS; + cl_packetmissed = realstart > neededtic; + + if (realstart <= neededtic && realend > neededtic) + { + tic_t i, j; + pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realstart; i < realend; i++) + { + // clear first + D_Clearticcmd(i); + + // copy the tics + pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + + // copy the textcmds + numtxtpak = *txtpak++; + for (j = 0; j < numtxtpak; j++) + { + INT32 k = *txtpak++; // playernum + const size_t txtsize = txtpak[0]+1; + + if (i >= gametic) // Don't copy old net commands + M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); + txtpak += txtsize; + } + } + + neededtic = realend; + } + else + { + DEBFILE(va("frame not in bound: %u\n", neededtic)); + /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) + I_Error("Received an out of order PT_SERVERTICS packet!\n" + "Got tics %d-%d, needed tic %d\n\n" + "Please report this crash on the Master Board,\n" + "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ + } +} + +static void PT_Ping(SINT8 node, INT32 netconsole) +{ + // Only accept PT_PING from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + //Update client ping table from the server. + if (client) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + + servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; + } +} + +static void PT_WillResendGamestate(SINT8 node) +{ + (void)node; + #ifndef NONET char tmpsave[256]; @@ -3705,19 +4228,12 @@ static void PT_WillResendGamestate(void) #endif } -static void PT_CanReceiveGamestate(SINT8 node) +static void PT_SendingLuaFile(SINT8 node) { -#ifndef NONET - if (client || sendingsavegame[node]) - return; - - CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); - - SV_SendSaveGame(node, true); // Resend a complete game state - resendingsavegame[node] = true; -#else (void)node; -#endif + + if (client) + CL_PrepareDownloadLuaFile(); } /** Handles a packet received from a node that isn't in game @@ -3733,202 +4249,27 @@ static void HandlePacketFromAwayNode(SINT8 node) if (node != servernode) DEBFILE(va("Received packet from unknown host %d\n", node)); -// macro for packets that should only be sent by the server -// if it is NOT from the server, bail out and close the connection! -#define SERVERONLY \ - if (node != servernode) \ - { \ - Net_CloseConnection(node); \ - break; \ - } switch (netbuffer->packettype) { - case PT_ASKINFOVIAMS: - Net_CloseConnection(node); - break; - - case PT_TELLFILESNEEDED: - if (server && serverrunning) - { - UINT8 *p; - INT32 firstfile = netbuffer->u.filesneedednum; - - netbuffer->packettype = PT_MOREFILESNEEDED; - netbuffer->u.filesneededcfg.first = firstfile; - netbuffer->u.filesneededcfg.more = 0; - - p = PutFileNeeded(firstfile); - - HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); - } - else // Shouldn't get this if you aren't the server...? - Net_CloseConnection(node); - break; - - case PT_MOREFILESNEEDED: - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) - { - D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); - if (!netbuffer->u.filesneededcfg.more) - cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list - } - break; - - case PT_ASKINFO: - if (server && serverrunning) - { - SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); - SV_SendPlayerInfo(node); // Send extra info - } - Net_CloseConnection(node); - break; - - case PT_SERVERREFUSE: // Negative response of client join request - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - if (cl_mode == CL_WAITJOINRESPONSE) - { - // Save the reason so it can be displayed after quitting the netgame - char *reason = strdup(netbuffer->u.serverrefuse.reason); - if (!reason) - I_Error("Out of memory!\n"); - - 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. - cl_mode = CL_ABORTED; - } - break; - - case PT_SERVERCFG: // Positive response of client join request - { - if (server && serverrunning && node != servernode) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - /// \note how would this happen? and is it doing the right thing if it does? - if (cl_mode != CL_WAITJOINRESPONSE) - break; - - if (client) - { - maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - G_SetGametype(netbuffer->u.servercfg.gametype); - modifiedgame = netbuffer->u.servercfg.modifiedgame; - memcpy(server_context, netbuffer->u.servercfg.server_context, 8); - } - - nodeingame[(UINT8)servernode] = true; - serverplayer = netbuffer->u.servercfg.serverplayer; - doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); - mynode = netbuffer->u.servercfg.clientnode; - if (serverplayer >= 0) - playernode[(UINT8)serverplayer] = servernode; - - if (netgame) -#ifndef NONET - CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); -#else - CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); -#endif - DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); - -#ifndef NONET - /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? - /// Shouldn't them be downloaded even at intermission time? - /// Also, according to HandleConnect, the server will send the savegame even during intermission... - if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || - netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) - cl_mode = CL_DOWNLOADSAVEGAME; - else -#endif - cl_mode = CL_CONNECTED; - break; - } - - // Handled in d_netfil.c - case PT_FILEFRAGMENT: - if (server) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - PT_FileFragment(); - break; - - case PT_FILEACK: - if (server) - PT_FileAck(); - break; - - case PT_FILERECEIVED: - if (server) - PT_FileReceived(); - break; - - case PT_REQUESTFILE: - if (server) - { - if (!cv_downloading.value || !PT_RequestFile(node)) - Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway - } - else - Net_CloseConnection(node); // nope - break; - - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (server) - Net_CloseConnection(node); - break; - - case PT_CLIENTCMD: - break; // This is not an "unknown packet" - - case PT_SERVERTICS: - // Do not remove my own server (we have just get a out of order packet) - if (node == servernode) - break; - /* FALLTHRU */ + case PT_ASKINFOVIAMS : PT_AskInfoViaMS (node ); break; + case PT_TELLFILESNEEDED: PT_TellFilesNeeded(node ); break; + case PT_MOREFILESNEEDED: PT_MoreFilesNeeded(node ); break; + case PT_ASKINFO : PT_AskInfo (node ); break; + case PT_SERVERREFUSE : PT_ServerRefuse (node ); break; + case PT_SERVERCFG : PT_ServerCFG (node ); break; + case PT_FILEFRAGMENT : PT_FileFragment (node, -1); break; + case PT_FILEACK : PT_FileAck (node ); break; + case PT_FILERECEIVED : PT_FileReceived (node ); break; + case PT_REQUESTFILE : PT_RequestFile (node ); break; + case PT_NODETIMEOUT : PT_ClientQuit (node, -1); break; + case PT_CLIENTQUIT : PT_ClientQuit (node, -1); break; + case PT_SERVERTICS : PT_ServerTics (node, -1); break; + case PT_CLIENTCMD : break; // This is not an "unknown packet" default: DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); Net_CloseConnection(node); - break; // Ignore it - } -#undef SERVERONLY } /** Handles a packet received from a node that is in game @@ -3942,13 +4283,6 @@ static void HandlePacketFromAwayNode(SINT8 node) static void HandlePacketFromPlayer(SINT8 node) { INT32 netconsole; - tic_t realend, realstart; - UINT8 *pak, *txtpak, numtxtpak; -#ifndef NOMD5 - UINT8 finalmd5[16];/* Well, it's the cool thing to do? */ -#endif - - txtpak = NULL; if (dedicated && node == 0) netconsole = 0; @@ -3961,358 +4295,39 @@ static void HandlePacketFromPlayer(SINT8 node) switch (netbuffer->packettype) { -// -------------------------------------------- SERVER RECEIVE ---------- + // SERVER RECEIVE case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: case PT_CLIENT2MIS: case PT_NODEKEEPALIVE: case PT_NODEKEEPALIVEMIS: - if (client) - break; - - // To save bytes, only the low byte of tic numbers are sent - // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); - - if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS - || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || supposedtics[node] < realend) - { - supposedtics[node] = realend; - } - // Discard out of order packet - if (nettics[node] > realend) - { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); - break; - } - - // Update the nettics - nettics[node] = realend; - - // Don't do anything for packets of type NODEKEEPALIVE? - if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) - break; - - // As long as clients send valid ticcmds, the server can keep running, so reset the timeout - /// \todo Use a separate cvar for that kind of timeout? - freezetimeout[node] = I_GetTime() + connectiontimeout; - - // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); - - // Check ticcmd for "speed hacks" - if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) - { - CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); - //D_Clearticcmd(k); - - SendKick(netconsole, KICK_MSG_CON_FAIL); - break; - } - - // Splitscreen cmd - if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) - && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], - &netbuffer->u.client2pak.cmd2, 1); - - // Check player consistancy during the level - if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) -#ifndef NONET - && !SV_ResendingSavegameToAnyone() -#endif - && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()) - { - if (cv_resynchattempts.value) - { - // Tell the client we are about to resend them the gamestate - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - HSendPacket(node, true, 0, 0); - - resendingsavegame[node] = true; - - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), - netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy)); - DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - else - { - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - } + PT_ClientCmd(node, netconsole); break; - case PT_TEXTCMD2: // splitscreen special - netconsole = nodetoplayer2[node]; - /* FALLTHRU */ - case PT_TEXTCMD: - if (client) - break; + case PT_TEXTCMD : PT_TextCmd (node, netconsole); break; + case PT_TEXTCMD2 : PT_TextCmd (node, netconsole); break; + case PT_LOGIN : PT_Login (node, netconsole); break; + case PT_NODETIMEOUT : PT_ClientQuit (node, netconsole); break; + case PT_CLIENTQUIT : PT_ClientQuit (node, netconsole); break; + case PT_CANRECEIVEGAMESTATE: PT_CanReceiveGamestate(node ); break; + case PT_ASKLUAFILE : PT_AskLuaFile (node ); break; + case PT_HASLUAFILE : PT_HasLuaFile (node ); break; + case PT_RECEIVEDGAMESTATE : PT_ReceivedGamestate (node ); break; - if (netconsole < 0 || netconsole >= MAXPLAYERS) - Net_UnAcknowledgePacket(node); - else - { - size_t j; - tic_t tic = maketic; - UINT8 *textcmd; + // CLIENT RECEIVE + case PT_SERVERTICS : PT_ServerTics (node, netconsole); break; + case PT_PING : PT_Ping (node, netconsole); break; + case PT_FILEFRAGMENT : PT_FileFragment (node, netconsole); break; + case PT_FILEACK : PT_FileAck (node ); break; + case PT_FILERECEIVED : PT_FileReceived (node ); break; + case PT_WILLRESENDGAMESTATE: PT_WillResendGamestate(node ); break; + case PT_SENDINGLUAFILE : PT_SendingLuaFile (node ); break; + case PT_SERVERCFG : break; - // ignore if the textcmd has a reported size of zero - // this shouldn't be sent at all - if (!netbuffer->u.textcmd[0]) - { - DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", - node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // ignore if the textcmd size var is actually larger than it should be - // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength - if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) - { - DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", - netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), - node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // check if tic that we are making isn't too large else we cannot send it :( - // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time - j = software_MAXPACKETLENGTH - - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE - + (doomcom->numslots+1)*sizeof(ticcmd_t)); - - // search a tic that have enougth space in the ticcmd - while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), - (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) - tic++; - - if (tic >= firstticstosend + BACKUPTICS) - { - DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " - "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), - maketic, firstticstosend, node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // Make sure we have a buffer - if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); - - DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", - tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); - - M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); - textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; - } - break; - case PT_LOGIN: - if (client) - break; - -#ifndef NOMD5 - if (doomcom->datalength < 16)/* ignore partial sends */ - break; - - if (!adminpasswordset) - { - CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]); - break; - } - - // Do the final pass to compare with the sent md5 - D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5); - - if (!memcmp(netbuffer->u.md5sum, finalmd5, 16)) - { - CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]); - COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately - } - else - CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); -#endif - break; - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (client) - break; - - // nodeingame will be put false in the execution of kick command - // this allow to send some packets to the quitting client to have their ack back - nodewaiting[node] = 0; - if (netconsole != -1 && playeringame[netconsole]) - { - UINT8 kickmsg; - - if (netbuffer->packettype == PT_NODETIMEOUT) - kickmsg = KICK_MSG_TIMEOUT; - else - kickmsg = KICK_MSG_PLAYER_QUIT; - kickmsg |= KICK_MSG_KEEP_BODY; - - SendKick(netconsole, kickmsg); - nodetoplayer[node] = -1; - - if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 - && playeringame[(UINT8)nodetoplayer2[node]]) - { - SendKick(nodetoplayer2[node], kickmsg); - nodetoplayer2[node] = -1; - } - } - Net_CloseConnection(node); - nodeingame[node] = false; - break; - case PT_CANRECEIVEGAMESTATE: - PT_CanReceiveGamestate(node); - break; - case PT_ASKLUAFILE: - if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) - AddLuaFileToSendQueue(node, luafiletransfers->realfilename); - break; - case PT_HASLUAFILE: - if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING) - SV_HandleLuaFileSent(node); - break; - case PT_RECEIVEDGAMESTATE: - sendingsavegame[node] = false; - resendingsavegame[node] = false; - savegameresendcooldown[node] = I_GetTime() + 5 * TICRATE; - break; -// -------------------------------------------- CLIENT RECEIVE ---------- - case PT_SERVERTICS: - // Only accept PT_SERVERTICS from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - - realstart = netbuffer->u.serverpak.starttic; - realend = realstart + netbuffer->u.serverpak.numtics; - - if (!txtpak) - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; - - if (realend > gametic + CLIENTBACKUPTICS) - realend = gametic + CLIENTBACKUPTICS; - cl_packetmissed = realstart > neededtic; - - if (realstart <= neededtic && realend > neededtic) - { - tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realstart; i < realend; i++) - { - // clear first - D_Clearticcmd(i); - - // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - - // copy the textcmds - numtxtpak = *txtpak++; - for (j = 0; j < numtxtpak; j++) - { - INT32 k = *txtpak++; // playernum - const size_t txtsize = txtpak[0]+1; - - if (i >= gametic) // Don't copy old net commands - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); - txtpak += txtsize; - } - } - - neededtic = realend; - } - else - { - DEBFILE(va("frame not in bound: %u\n", neededtic)); - /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) - I_Error("Received an out of order PT_SERVERTICS packet!\n" - "Got tics %d-%d, needed tic %d\n\n" - "Please report this crash on the Master Board,\n" - "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ - } - break; - case PT_PING: - // Only accept PT_PING from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - - //Update client ping table from the server. - if (client) - { - UINT8 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; - - servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; - } - - break; - case PT_SERVERCFG: - break; - case PT_FILEFRAGMENT: - // Only accept PT_FILEFRAGMENT from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - if (client) - PT_FileFragment(); - break; - case PT_FILEACK: - if (server) - PT_FileAck(); - break; - case PT_FILERECEIVED: - if (server) - PT_FileReceived(); - break; - case PT_WILLRESENDGAMESTATE: - PT_WillResendGamestate(); - break; - case PT_SENDINGLUAFILE: - if (client) - CL_PrepareDownloadLuaFile(); - break; default: DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", netbuffer->packettype, node)); - } // end switch + } } /** Handles all received packets, if any diff --git a/src/d_netfil.c b/src/d_netfil.c index edbef30bb..7c9ed54d8 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -413,12 +413,17 @@ boolean CL_SendFileRequest(void) } // get request filepak and put it on the send queue -// returns false if a requested file was not found or cannot be sent -boolean PT_RequestFile(INT32 node) +void PT_RequestFile(SINT8 node) { UINT8 *p = netbuffer->u.textcmd; UINT8 id; + if (client || !cv_downloading.value) + { + Net_CloseConnection(node); // close connection if you are not the server or disabled downloading + return; + } + while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow { id = READUINT8(p); @@ -428,11 +433,12 @@ boolean PT_RequestFile(INT32 node) if (!AddFileToSendQueue(node, id)) { SV_AbortSendFiles(node); - return false; // don't read the rest of the files + Net_CloseConnection(node); // close connection if one of the requested files could not be sent + return; // don't read the rest of the files } } - return true; // no problems with any files + return; // no problems with any files } /** Checks if the files needed aren't already loaded or on the disk @@ -1137,13 +1143,15 @@ void FileSendTicker(void) } } -void PT_FileAck(void) +void PT_FileAck(SINT8 node) { fileack_pak *packet = &netbuffer->u.fileack; - INT32 node = doomcom->remotenode; filetran_t *trans = &transfer[node]; INT32 i, j; + if (client) + return; + // Wrong file id? Ignore it, it's probably a late packet if (!(trans->txlist && packet->fileid == trans->txlist->fileid)) return; @@ -1190,12 +1198,12 @@ void PT_FileAck(void) } } -void PT_FileReceived(void) +void PT_FileReceived(SINT8 node) { - filetx_t *trans = transfer[doomcom->remotenode].txlist; + filetx_t *trans = transfer[node].txlist; - if (trans && netbuffer->u.filereceived == trans->fileid) - SV_EndFileSend(doomcom->remotenode); + if (server && trans && netbuffer->u.filereceived == trans->fileid) + SV_EndFileSend(node); } static void SendAckPacket(fileack_pak *packet, UINT8 fileid) @@ -1281,8 +1289,27 @@ void FileReceiveTicker(void) } } -void PT_FileFragment(void) +void PT_FileFragment(SINT8 node, INT32 netconsole) { + if (nodeingame[node]) + { + // Only accept PT_FILEFRAGMENT from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + if (server) + return; + } + else if (server || node != servernode) + { + Net_CloseConnection(node); + return; + } + INT32 filenum = netbuffer->u.filetxpak.fileid; fileneeded_t *file = &fileneeded[filenum]; UINT32 fragmentpos = LONG(netbuffer->u.filetxpak.position); diff --git a/src/d_netfil.h b/src/d_netfil.h index f778a518f..5c7f4ef49 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -90,16 +90,16 @@ void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemet UINT8 fileid); void FileSendTicker(void); -void PT_FileAck(void); -void PT_FileReceived(void); +void PT_FileAck(SINT8 node); +void PT_FileReceived(SINT8 node); boolean SendingFile(INT32 node); void FileReceiveTicker(void); -void PT_FileFragment(void); +void PT_FileFragment(SINT8 node, INT32 netconsole); boolean CL_CheckDownloadable(void); boolean CL_SendFileRequest(void); -boolean PT_RequestFile(INT32 node); +void PT_RequestFile(SINT8 node); typedef enum { From 4c0705008e46051bdae26dd1e3cdbbd148ccf33a Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 15:52:45 +0100 Subject: [PATCH 22/93] Merge node arrays into a structure --- src/d_clisrv.c | 202 ++++++++++++++++++++++++------------------------- src/d_net.h | 23 +++++- src/d_netfil.c | 4 +- src/i_tcp.c | 14 ++-- 4 files changed, 125 insertions(+), 118 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d3f6854c7..e311bf15a 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -84,6 +84,8 @@ boolean serverrunning = false; INT32 serverplayer = 0; char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) +netnode_t netnodes[MAXNETNODES]; + // Server specific vars UINT8 playernode[MAXPLAYERS]; char playeraddress[MAXPLAYERS][64]; @@ -91,10 +93,6 @@ char playeraddress[MAXPLAYERS][64]; // Minimum timeout for sending the savegame // The actual timeout will be longer depending on the savegame length tic_t jointimeout = (10*TICRATE); -static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? -static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame? -static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again? -static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? // Incremented by cv_joindelay when a client joins, decremented each tic. // If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. @@ -103,14 +101,8 @@ static tic_t joindelay = 0; UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. -SINT8 nodetoplayer[MAXNETNODES]; -SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) -UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen -boolean nodeingame[MAXNETNODES]; // set false as nodes leave game tic_t servermaxping = 800; // server's max ping. Defaults to 800 -static tic_t nettics[MAXNETNODES]; // what tic the client have received -static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet -static UINT8 nodewaiting[MAXNETNODES]; + static tic_t firstticstosend; // min of the nettics static tic_t tictoclear = 0; // optimize d_clearticcmd static tic_t maketic; @@ -218,14 +210,14 @@ tic_t ExpandTics(INT32 low, INT32 node) { INT32 delta; - delta = low - (nettics[node] & UINT8_MAX); + delta = low - (netnodes[node].tic & UINT8_MAX); if (delta >= -64 && delta <= 64) - return (nettics[node] & ~UINT8_MAX) + low; + return (netnodes[node].tic & ~UINT8_MAX) + low; else if (delta > 64) - return (nettics[node] & ~UINT8_MAX) - 256 + low; + return (netnodes[node].tic & ~UINT8_MAX) - 256 + low; else //if (delta < -64) - return (nettics[node] & ~UINT8_MAX) + 256 + low; + return (netnodes[node].tic & ~UINT8_MAX) + 256 + low; } // ----------------------------------------------------------------- @@ -999,7 +991,7 @@ static boolean SV_ResendingSavegameToAnyone(void) INT32 i; for (i = 0; i < MAXNETNODES; i++) - if (resendingsavegame[i]) + if (netnodes[i].resendingsavegame) return true; return false; } @@ -1068,8 +1060,8 @@ static void SV_SendSaveGame(INT32 node, boolean resending) save_p = NULL; // Remember when we started sending the savegame so we can handle timeouts - sendingsavegame[node] = true; - freezetimeout[node] = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte + netnodes[node].sendingsavegame = true; + netnodes[node].freezetimeout = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte } #ifdef DUMPCONSISTENCY @@ -2034,7 +2026,7 @@ static void CL_ConnectToServer(void) { pnumnodes = 0; for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) + if (netnodes[i].ingame) pnumnodes++; } } @@ -2316,10 +2308,10 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) if (server && !demoplayback && playernode[playernum] != UINT8_MAX) { INT32 node = playernode[playernum]; - playerpernode[node]--; - if (playerpernode[node] <= 0) + netnodes[node].numplayers--; + if (netnodes[node].numplayers <= 0) { - nodeingame[node] = false; + netnodes[node].ingame = false; Net_CloseConnection(node); ResetNode(node); } @@ -2431,7 +2423,7 @@ void CL_Reset(void) if (servernode > 0 && servernode < MAXNETNODES) { - nodeingame[(UINT8)servernode] = false; + netnodes[(UINT8)servernode].ingame = false; Net_CloseConnection(servernode); } D_CloseConnection(); // netgame = false @@ -2674,7 +2666,7 @@ static void Command_Kick(void) // Special case if we are trying to kick a player who is downloading the game state: // trigger a timeout instead of kicking them, because a kick would only // take effect after they have finished downloading - if (server && playernode[pn] != UINT8_MAX && sendingsavegame[playernode[pn]]) + if (server && playernode[pn] != UINT8_MAX && netnodes[playernode[pn]].sendingsavegame) { Net_ConnectionTimeout(playernode[pn]); return; @@ -2763,8 +2755,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) // Is playernum authorized to make this kick? if (playernum != serverplayer && !IsPlayerAdmin(playernum) - && !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2 - && nodetoplayer2[playernode[playernum]] == pnum)) + && !(playernode[playernum] != UINT8_MAX && netnodes[playernode[playernum]].numplayers == 2 + && netnodes[playernode[playernum]].player2 == pnum)) { // We received a kick command from someone who isn't the // server or admin, and who isn't in splitscreen removing @@ -2802,10 +2794,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) "\n" "If you think this is a bug, please report it, including all of the details above.\n", playernum, pnum, - playernode[playernum], playerpernode[playernode[playernum]], - nodetoplayer2[playernode[playernum]], - playernode[pnum], playerpernode[playernode[pnum]], - nodetoplayer2[playernode[pnum]]); + playernode[playernum], netnodes[playernode[playernum]].numplayers, + netnodes[playernode[playernum]].player2, + playernode[pnum], netnodes[playernode[pnum]].numplayers, + netnodes[playernode[pnum]].player2); */ pnum = playernum; msg = KICK_MSG_CON_FAIL; @@ -2926,10 +2918,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (server && !demoplayback && playernode[pnum] != UINT8_MAX) { INT32 node = playernode[pnum]; - playerpernode[node]--; - if (playerpernode[node] <= 0) + netnodes[node].numplayers--; + if (netnodes[node].numplayers <= 0) { - nodeingame[node] = false; + netnodes[node].ingame = false; Net_CloseConnection(node); ResetNode(node); } @@ -3017,19 +3009,19 @@ void D_ClientServerInit(void) static void ResetNode(INT32 node) { - nodeingame[node] = false; - nodewaiting[node] = 0; + netnodes[node].ingame = false; + netnodes[node].numplayerswaiting = 0; - nettics[node] = gametic; - supposedtics[node] = gametic; + netnodes[node].tic = gametic; + netnodes[node].supposedtic = gametic; - nodetoplayer[node] = -1; - nodetoplayer2[node] = -1; - playerpernode[node] = 0; + netnodes[node].player = -1; + netnodes[node].player2 = -1; + netnodes[node].numplayers = 0; - sendingsavegame[node] = false; - resendingsavegame[node] = false; - savegameresendcooldown[node] = 0; + netnodes[node].sendingsavegame = false; + netnodes[node].resendingsavegame = false; + netnodes[node].savegameresendcooldown = 0; } void SV_ResetServer(void) @@ -3067,7 +3059,7 @@ void SV_ResetServer(void) if (dedicated) { - nodeingame[0] = true; + netnodes[0].ingame = true; serverplayer = 0; } else @@ -3130,14 +3122,14 @@ void D_QuitNetGame(void) netbuffer->packettype = PT_SERVERSHUTDOWN; for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) + if (netnodes[i].ingame) HSendPacket(i, true, 0, 0); #ifdef MASTERSERVER if (serverrunning && ms_RoomId > 0) UnregisterServer(); #endif } - else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]) + else if (servernode > 0 && servernode < MAXNETNODES && netnodes[(UINT8)servernode].ingame) { netbuffer->packettype = PT_CLIENTQUIT; HSendPacket(servernode, true, 0, 0); @@ -3161,12 +3153,12 @@ void D_QuitNetGame(void) // Adds a node to the game (player will follow at map change or at savegame....) static inline void SV_AddNode(INT32 node) { - nettics[node] = gametic; - supposedtics[node] = gametic; + netnodes[node].tic = gametic; + netnodes[node].supposedtic = gametic; // little hack because the server connects to itself and puts // nodeingame when connected not here if (node) - nodeingame[node] = true; + netnodes[node].ingame = true; } // Xcmd XD_ADDPLAYER @@ -3311,7 +3303,7 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) for (node = 0; node < MAXNETNODES; node++) { // splitscreen can allow 2 player in one node - for (; nodewaiting[node] > 0; nodewaiting[node]--) + for (; netnodes[node].numplayerswaiting > 0; netnodes[node].numplayerswaiting--) { newplayer = true; @@ -3325,7 +3317,7 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) if (playeringame[newplayernum]) continue; for (n = 0; n < MAXNETNODES; n++) - if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum) + if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) break; if (n == MAXNETNODES) break; @@ -3341,18 +3333,18 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) p = buf + 2; buf[0] = (UINT8)node; buf[1] = newplayernum; - if (playerpernode[node] < 1) + if (netnodes[node].numplayers < 1) { - nodetoplayer[node] = newplayernum; + netnodes[node].player = newplayernum; WRITESTRINGN(p, name, MAXPLAYERNAME); } else { - nodetoplayer2[node] = newplayernum; + netnodes[node].player2 = newplayernum; buf[1] |= 0x80; WRITESTRINGN(p, name2, MAXPLAYERNAME); } - playerpernode[node]++; + netnodes[node].numplayers++; SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); @@ -3571,7 +3563,7 @@ static void HandleConnect(SINT8 node) boolean newnode = false; #endif - for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) + for (i = 0; i < netbuffer->u.clientcfg.localplayers - netnodes[node].numplayers; i++) { strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) @@ -3582,8 +3574,8 @@ static void HandleConnect(SINT8 node) } // client authorised to join - nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); - if (!nodeingame[node]) + netnodes[node].numplayerswaiting = (UINT8)(netbuffer->u.clientcfg.localplayers - netnodes[node].numplayers); + if (!netnodes[node].ingame) { gamestate_t backupstate = gamestate; #ifndef NONET @@ -3608,7 +3600,7 @@ static void HandleConnect(SINT8 node) DEBFILE("new node joined\n"); } #ifndef NONET - if (nodewaiting[node]) + if (netnodes[node].numplayerswaiting) { if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) { @@ -3803,7 +3795,7 @@ static void PT_ServerCFG(SINT8 node) memcpy(server_context, netbuffer->u.servercfg.server_context, 8); } - nodeingame[(UINT8)servernode] = true; + netnodes[(UINT8)servernode].ingame = true; serverplayer = netbuffer->u.servercfg.serverplayer; doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); mynode = netbuffer->u.servercfg.clientnode; @@ -3844,19 +3836,19 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || supposedtics[node] < realend) + || netnodes[node].supposedtic < realend) { - supposedtics[node] = realend; + netnodes[node].supposedtic = realend; } // Discard out of order packet - if (nettics[node] > realend) + if (netnodes[node].tic > realend) { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", netnodes[node].tic)); return; } // Update the nettics - nettics[node] = realend; + netnodes[node].tic = realend; // Don't do anything for packets of type NODEKEEPALIVE? if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE @@ -3865,7 +3857,7 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? - freezetimeout[node] = I_GetTime() + connectiontimeout; + netnodes[node].freezetimeout = I_GetTime() + connectiontimeout; // Copy ticcmd G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); @@ -3883,8 +3875,8 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) - && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + && netnodes[node].player2 >= 0) + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)netnodes[node].player2], &netbuffer->u.client2pak.cmd2, 1); // Check player consistancy during the level @@ -3893,7 +3885,7 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) #ifndef NONET && !SV_ResendingSavegameToAnyone() #endif - && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()) + && !netnodes[node].resendingsavegame && netnodes[node].savegameresendcooldown <= I_GetTime()) { if (cv_resynchattempts.value) { @@ -3901,7 +3893,7 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) netbuffer->packettype = PT_WILLRESENDGAMESTATE; HSendPacket(node, true, 0, 0); - resendingsavegame[node] = true; + netnodes[node].resendingsavegame = true; if (cv_blamecfail.value) CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), @@ -3931,7 +3923,7 @@ static void PT_TextCmd(SINT8 node, INT32 netconsole) // splitscreen special if (netbuffer->packettype == PT_TEXTCMD2) - netconsole = nodetoplayer2[node]; + netconsole = netnodes[node].player2; if (netconsole < 0 || netconsole >= MAXPLAYERS) Net_UnAcknowledgePacket(node); @@ -4033,7 +4025,7 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) if (client) return; - if (!nodeingame[node]) + if (!netnodes[node].ingame) { Net_CloseConnection(node); return; @@ -4041,7 +4033,7 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) // nodeingame will be put false in the execution of kick command // this allow to send some packets to the quitting client to have their ack back - nodewaiting[node] = 0; + netnodes[node].numplayerswaiting = 0; if (netconsole != -1 && playeringame[netconsole]) { UINT8 kickmsg; @@ -4053,29 +4045,29 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) kickmsg |= KICK_MSG_KEEP_BODY; SendKick(netconsole, kickmsg); - nodetoplayer[node] = -1; + netnodes[node].player = -1; - if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 - && playeringame[(UINT8)nodetoplayer2[node]]) + if (netnodes[node].player2 != -1 && netnodes[node].player2 >= 0 + && playeringame[(UINT8)netnodes[node].player2]) { - SendKick(nodetoplayer2[node], kickmsg); - nodetoplayer2[node] = -1; + SendKick(netnodes[node].player2, kickmsg); + netnodes[node].player2 = -1; } } Net_CloseConnection(node); - nodeingame[node] = false; + netnodes[node].ingame = false; } static void PT_CanReceiveGamestate(SINT8 node) { #ifndef NONET - if (client || sendingsavegame[node]) + if (client || netnodes[node].sendingsavegame) return; - CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); + CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[netnodes[node].player]); SV_SendSaveGame(node, true); // Resend a complete game state - resendingsavegame[node] = true; + netnodes[node].resendingsavegame = true; #else (void)node; #endif @@ -4095,9 +4087,9 @@ static void PT_HasLuaFile(SINT8 node) static void PT_ReceivedGamestate(SINT8 node) { - sendingsavegame[node] = false; - resendingsavegame[node] = false; - savegameresendcooldown[node] = I_GetTime() + 5 * TICRATE; + netnodes[node].sendingsavegame = false; + netnodes[node].resendingsavegame = false; + netnodes[node].savegameresendcooldown = I_GetTime() + 5 * TICRATE; } static void PT_ServerTics(SINT8 node, INT32 netconsole) @@ -4105,7 +4097,7 @@ static void PT_ServerTics(SINT8 node, INT32 netconsole) UINT8 *pak, *txtpak, numtxtpak; tic_t realend, realstart; - if (!nodeingame[node]) + if (!netnodes[node].ingame) { // Do not remove my own server (we have just get a out of order packet) if (node != servernode) @@ -4287,7 +4279,7 @@ static void HandlePacketFromPlayer(SINT8 node) if (dedicated && node == 0) netconsole = 0; else - netconsole = nodetoplayer[node]; + netconsole = netnodes[node].player; #ifdef PARANOIA if (netconsole >= MAXPLAYERS) I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); @@ -4376,7 +4368,7 @@ static void GetPackets(void) continue; // We do nothing with PLAYERINFO, that's for the MS browser. // Packet received from someone already playing - if (nodeingame[node]) + if (netnodes[node].ingame) HandlePacketFromPlayer(node); // Packet received from someone not playing else @@ -4572,13 +4564,13 @@ static void SV_SendTics(void) // send to all client but not to me // for each node create a packet with x tics and send it - // x is computed using supposedtics[n], max packet size and maketic + // x is computed using netnodes[n].supposedtic, max packet size and maketic for (n = 1; n < MAXNETNODES; n++) - if (nodeingame[n]) + if (netnodes[n].ingame) { - // assert supposedtics[n]>=nettics[n] - realfirsttic = supposedtics[n]; - lasttictosend = min(maketic, nettics[n] + CLIENTBACKUPTICS); + // assert netnodes[n].supposedtic>=netnodes[n].tic + realfirsttic = netnodes[n].supposedtic; + lasttictosend = min(maketic, netnodes[n].tic + CLIENTBACKUPTICS); if (realfirsttic >= lasttictosend) { @@ -4587,8 +4579,8 @@ static void SV_SendTics(void) // packet detection work when we have received packet with firsttic > neededtic // (getpacket servertics case) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, supposedtics[n], nettics[n])); - realfirsttic = nettics[n]; + n, maketic, netnodes[n].supposedtic, netnodes[n].tic)); + realfirsttic = netnodes[n].tic; if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) // all tic are ok continue; @@ -4666,13 +4658,13 @@ static void SV_SendTics(void) HSendPacket(n, false, 0, packsize); // when tic are too large, only one tic is sent so don't go backward! if (lasttictosend-doomcom->extratics > realfirsttic) - supposedtics[n] = lasttictosend-doomcom->extratics; + netnodes[n].supposedtic = lasttictosend-doomcom->extratics; else - supposedtics[n] = lasttictosend; - if (supposedtics[n] < nettics[n]) supposedtics[n] = nettics[n]; + netnodes[n].supposedtic = lasttictosend; + if (netnodes[n].supposedtic < netnodes[n].tic) netnodes[n].supposedtic = netnodes[n].tic; } // node 0 is me! - supposedtics[0] = maketic; + netnodes[0].supposedtic = maketic; } // @@ -4915,7 +4907,7 @@ static inline void PingUpdate(void) //send out our ping packets for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) + if (netnodes[i].ingame) HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); pingmeasurecount = 1; //Reset count @@ -4993,11 +4985,11 @@ void NetUpdate(void) firstticstosend = gametic; for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i] && nettics[i] < firstticstosend) + if (netnodes[i].ingame && netnodes[i].tic < firstticstosend) { - firstticstosend = nettics[i]; + firstticstosend = netnodes[i].tic; - if (maketic + 1 >= nettics[i] + BACKUPTICS) + if (maketic + 1 >= netnodes[i].tic + BACKUPTICS) Net_ConnectionTimeout(i); } @@ -5025,7 +5017,7 @@ void NetUpdate(void) if (server) { for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && freezetimeout[i] < I_GetTime()) + if (netnodes[i].ingame && netnodes[i].freezetimeout < I_GetTime()) Net_ConnectionTimeout(i); // In case the cvar value was lowered @@ -5066,7 +5058,7 @@ INT32 D_NumPlayers(void) tic_t GetLag(INT32 node) { - return gametic - nettics[node]; + return gametic - netnodes[node].tic; } void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest) diff --git a/src/d_net.h b/src/d_net.h index 5baa593a0..9eee53894 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -37,10 +37,25 @@ boolean Net_GetNetStat(void); extern INT32 getbytes; extern INT64 sendbytes; // Realtime updated -extern SINT8 nodetoplayer[MAXNETNODES]; -extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen) -extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen -extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game +typedef struct netnode_s +{ + boolean ingame; // set false as nodes leave game + tic_t freezetimeout; // Until when can this node freeze the server before getting a timeout? + + SINT8 player; + SINT8 player2; // say the numplayer for this node if any (splitscreen) + UINT8 numplayers; // used specialy for scplitscreen + UINT8 numplayerswaiting; + + tic_t tic; // what tic the client have received + tic_t supposedtic; // nettics prevision for smaller packet + + boolean sendingsavegame; // Are we sending the savegame? + boolean resendingsavegame; // Are we resending the savegame? + tic_t savegameresendcooldown; // How long before we can resend again? +} netnode_t; + +extern netnode_t netnodes[MAXNETNODES]; extern boolean serverrunning; diff --git a/src/d_netfil.c b/src/d_netfil.c index 7c9ed54d8..1fee1df81 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -667,7 +667,7 @@ void SV_PrepareSendLuaFile(void) // Set status to "waiting" for everyone for (i = 0; i < MAXNETNODES; i++) - luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE); + luafiletransfers->nodestatus[i] = (netnodes[i].ingame ? LFTNS_WAITING : LFTNS_NONE); if (FIL_ReadFileOK(luafiletransfers->realfilename)) { @@ -1291,7 +1291,7 @@ void FileReceiveTicker(void) void PT_FileFragment(SINT8 node, INT32 netconsole) { - if (nodeingame[node]) + if (netnodes[node].ingame) { // Only accept PT_FILEFRAGMENT from the server. if (node != servernode) diff --git a/src/i_tcp.c b/src/i_tcp.c index 8838ba725..00aebddd3 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -449,7 +449,7 @@ static void cleanupnodes(void) // Why can't I start at zero? for (j = 1; j < MAXNETNODES; j++) - if (!(nodeingame[j] || SendingFile(j))) + if (!(netnodes[j].ingame || SendingFile(j))) nodeconnected[j] = false; } @@ -473,7 +473,7 @@ static SINT8 getfreenode(void) */ /*I_Error("No more free nodes!!1!11!11!!1111\n"); for (j = 1; j < MAXNETNODES; j++) - if (!nodeingame[j]) + if (!netnodes[j].ingame) return j;*/ return -1; @@ -488,24 +488,24 @@ void Command_Numnodes(void) for (i = 1; i < MAXNETNODES; i++) { - if (!(nodeconnected[i] || nodeingame[i])) + if (!(nodeconnected[i] || netnodes[i].ingame)) continue; if (nodeconnected[i]) connected++; - if (nodeingame[i]) + if (netnodes[i].ingame) ingame++; CONS_Printf("%2d - ", i); - if (nodetoplayer[i] != -1) - CONS_Printf("player %.2d", nodetoplayer[i]); + if (netnodes[i].player != -1) + CONS_Printf("player %.2d", netnodes[i].player); else CONS_Printf(" "); if (nodeconnected[i]) CONS_Printf(" - connected"); else CONS_Printf(" - "); - if (nodeingame[i]) + if (netnodes[i].ingame) CONS_Printf(" - ingame"); else CONS_Printf(" - "); From f1117095b76a6cb8d85c6ea809bd47ddaa64f914 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 20:45:56 +0100 Subject: [PATCH 23/93] Cleanup ResetNode --- src/d_clisrv.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e311bf15a..3ab0df1d0 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2278,7 +2278,12 @@ static void Command_connect(void) } #endif -static void ResetNode(INT32 node); +static void ResetNode(INT32 node) +{ + memset(&netnodes[node], 0, sizeof(*netnodes)); + netnodes[node].player = -1; + netnodes[node].player2 = -1; +} // // CL_ClearPlayer @@ -3007,23 +3012,6 @@ void D_ClientServerInit(void) SV_SpawnServer(); } -static void ResetNode(INT32 node) -{ - netnodes[node].ingame = false; - netnodes[node].numplayerswaiting = 0; - - netnodes[node].tic = gametic; - netnodes[node].supposedtic = gametic; - - netnodes[node].player = -1; - netnodes[node].player2 = -1; - netnodes[node].numplayers = 0; - - netnodes[node].sendingsavegame = false; - netnodes[node].resendingsavegame = false; - netnodes[node].savegameresendcooldown = 0; -} - void SV_ResetServer(void) { INT32 i; From ecacb14fc19fd312ca049a9df666c8b4c30f4274 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 20:48:17 +0100 Subject: [PATCH 24/93] Move player-node unlinking to a function --- src/d_clisrv.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3ab0df1d0..1fee20a3f 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2298,6 +2298,24 @@ void CL_ClearPlayer(INT32 playernum) memset(playeraddress[playernum], 0, sizeof(*playeraddress)); } +static void UnlinkPlayerFromNode(INT32 playernum) +{ + INT32 node = playernode[playernum]; + + if (node == UINT8_MAX) + return; + + playernode[playernum] = UINT8_MAX; + + netnodes[node].numplayers--; + if (netnodes[node].numplayers <= 0) + { + netnodes[node].ingame = false; + Net_CloseConnection(node); + ResetNode(node); + } +} + // // CL_RemovePlayer // @@ -2310,17 +2328,8 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) if (!playeringame[playernum]) return; - if (server && !demoplayback && playernode[playernum] != UINT8_MAX) - { - INT32 node = playernode[playernum]; - netnodes[node].numplayers--; - if (netnodes[node].numplayers <= 0) - { - netnodes[node].ingame = false; - Net_CloseConnection(node); - ResetNode(node); - } - } + if (server) + UnlinkPlayerFromNode(playernum); if (gametyperules & GTR_TEAMFLAGS) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! @@ -2392,7 +2401,6 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) // remove avatar of player playeringame[playernum] = false; - playernode[playernum] = UINT8_MAX; while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1) doomcom->numslots--; @@ -2920,20 +2928,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) } else if (keepbody) { - if (server && !demoplayback && playernode[pnum] != UINT8_MAX) - { - INT32 node = playernode[pnum]; - netnodes[node].numplayers--; - if (netnodes[node].numplayers <= 0) - { - netnodes[node].ingame = false; - Net_CloseConnection(node); - ResetNode(node); - } - } - - playernode[pnum] = UINT8_MAX; - + if (server) + UnlinkPlayerFromNode(pnum); players[pnum].quittime = 1; } else From 2de6b623c09c33cca862b553ce925c8340cd5a4a Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 21:28:53 +0100 Subject: [PATCH 25/93] Move sphere redistribution to its own function --- src/d_clisrv.c | 106 ++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1fee20a3f..eee820db2 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2316,6 +2316,61 @@ static void UnlinkPlayerFromNode(INT32 playernum) } } +// If in a special stage, redistribute the player's +// spheres across the remaining players. +// I feel like this shouldn't even be in this file at all, but well. +static void RedistributeSpecialStageSpheres(INT32 playernum) +{ + INT32 i, count, sincrement, spheres, rincrement, rings; + + if (!G_IsSpecialStage(gamemap)) + return; + + for (i = 0, count = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + count++; + } + + count--; + sincrement = spheres = players[playernum].spheres; + rincrement = rings = players[playernum].rings; + + if (count) + { + sincrement /= count; + rincrement /= count; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && i != playernum) + { + if (spheres < 2*sincrement) + { + P_GivePlayerSpheres(&players[i], spheres); + spheres = 0; + } + else + { + P_GivePlayerSpheres(&players[i], sincrement); + spheres -= sincrement; + } + + if (rings < 2*rincrement) + { + P_GivePlayerRings(&players[i], rings); + rings = 0; + } + else + { + P_GivePlayerRings(&players[i], rincrement); + rings -= rincrement; + } + } + } +} + // // CL_RemovePlayer // @@ -2334,56 +2389,7 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) if (gametyperules & GTR_TEAMFLAGS) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! - // If in a special stage, redistribute the player's spheres across - // the remaining players. - if (G_IsSpecialStage(gamemap)) - { - INT32 i, count, sincrement, spheres, rincrement, rings; - - for (i = 0, count = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - count++; - } - - count--; - sincrement = spheres = players[playernum].spheres; - rincrement = rings = players[playernum].rings; - - if (count) - { - sincrement /= count; - rincrement /= count; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && i != playernum) - { - if (spheres < 2*sincrement) - { - P_GivePlayerSpheres(&players[i], spheres); - spheres = 0; - } - else - { - P_GivePlayerSpheres(&players[i], sincrement); - spheres -= sincrement; - } - - if (rings < 2*rincrement) - { - P_GivePlayerRings(&players[i], rings); - rings = 0; - } - else - { - P_GivePlayerRings(&players[i], rincrement); - rings -= rincrement; - } - } - } - } + RedistributeSpecialStageSpheres(playernum); LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting From 0053eaac009a1a675fcf57a7c67f488faf0f1882 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 22:16:08 +0100 Subject: [PATCH 26/93] Fix sphere redistribution --- src/d_clisrv.c | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index eee820db2..432001b80 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2333,39 +2333,39 @@ static void RedistributeSpecialStageSpheres(INT32 playernum) } count--; - sincrement = spheres = players[playernum].spheres; - rincrement = rings = players[playernum].rings; + spheres = players[playernum].spheres; + rings = players[playernum].rings; - if (count) + while (count && (spheres || rings)) { - sincrement /= count; - rincrement /= count; - } + sincrement = max(spheres / count, 1); + rincrement = max(rings / count, 1); - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && i != playernum) + for (i = 0; i < MAXPLAYERS; i++) { - if (spheres < 2*sincrement) + if (playeringame[i] && i != playernum) { - P_GivePlayerSpheres(&players[i], spheres); - spheres = 0; - } - else - { - P_GivePlayerSpheres(&players[i], sincrement); - spheres -= sincrement; - } + if (spheres < sincrement) + { + P_GivePlayerSpheres(&players[i], spheres); + spheres = 0; + } + else + { + P_GivePlayerSpheres(&players[i], sincrement); + spheres -= sincrement; + } - if (rings < 2*rincrement) - { - P_GivePlayerRings(&players[i], rings); - rings = 0; - } - else - { - P_GivePlayerRings(&players[i], rincrement); - rings -= rincrement; + if (rings < rincrement) + { + P_GivePlayerRings(&players[i], rings); + rings = 0; + } + else + { + P_GivePlayerRings(&players[i], rincrement); + rings -= rincrement; + } } } } From 394e925c16c7bab4fc8906046b3bf23a1ceee823 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 29 Dec 2022 22:30:26 +0100 Subject: [PATCH 27/93] Cleanup sphere redistribution --- src/d_clisrv.c | 57 ++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 432001b80..1b344a0de 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2321,52 +2321,31 @@ static void UnlinkPlayerFromNode(INT32 playernum) // I feel like this shouldn't even be in this file at all, but well. static void RedistributeSpecialStageSpheres(INT32 playernum) { - INT32 i, count, sincrement, spheres, rincrement, rings; - - if (!G_IsSpecialStage(gamemap)) + if (!G_IsSpecialStage(gamemap) || D_NumPlayers() <= 1) return; - for (i = 0, count = 0; i < MAXPLAYERS; i++) + INT32 count = D_NumPlayers() - 1; + INT32 spheres = players[playernum].spheres; + INT32 rings = players[playernum].rings; + + while (spheres || rings) { - if (playeringame[i]) - count++; - } - - count--; - spheres = players[playernum].spheres; - rings = players[playernum].rings; - - while (count && (spheres || rings)) - { - sincrement = max(spheres / count, 1); - rincrement = max(rings / count, 1); + INT32 sincrement = max(spheres / count, 1); + INT32 rincrement = max(rings / count, 1); + INT32 i, n; for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && i != playernum) - { - if (spheres < sincrement) - { - P_GivePlayerSpheres(&players[i], spheres); - spheres = 0; - } - else - { - P_GivePlayerSpheres(&players[i], sincrement); - spheres -= sincrement; - } + if (!playeringame[i] || i == playernum) + continue; - if (rings < rincrement) - { - P_GivePlayerRings(&players[i], rings); - rings = 0; - } - else - { - P_GivePlayerRings(&players[i], rincrement); - rings -= rincrement; - } - } + n = min(spheres, sincrement); + P_GivePlayerSpheres(&players[i], n); + spheres -= n; + + n = min(rings, rincrement); + P_GivePlayerRings(&players[i], n); + rings -= n; } } } From 160db6383c1f04075491a0522196e9edd7b7d2c7 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 00:24:06 +0100 Subject: [PATCH 28/93] Remove useless return value for SV_AddWaitingPlayers --- src/d_clisrv.c | 12 +++--------- src/d_clisrv.h | 2 +- src/d_netcmd.c | 3 +-- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1b344a0de..0c6960236 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3262,9 +3262,9 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) LUA_HookInt(newplayernum, HOOK(PlayerJoin)); } -static boolean SV_AddWaitingPlayers(const char *name, const char *name2) +static void SV_AddWaitingPlayers(const char *name, const char *name2) { - INT32 node, n, newplayer = false; + INT32 node, n; UINT8 buf[2 + MAXPLAYERNAME]; UINT8 *p; INT32 newplayernum; @@ -3274,8 +3274,6 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) // splitscreen can allow 2 player in one node for (; netnodes[node].numplayerswaiting > 0; netnodes[node].numplayerswaiting--) { - newplayer = true; - newplayernum = FindRejoinerNum(node); if (newplayernum == -1) { @@ -3320,8 +3318,6 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2) DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); } } - - return newplayer; } void CL_AddSplitscreenPlayer(void) @@ -3344,7 +3340,7 @@ boolean Playing(void) return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); } -boolean SV_SpawnServer(void) +void SV_SpawnServer(void) { if (demoplayback) G_StopDemo(); // reset engine parameter @@ -3371,8 +3367,6 @@ boolean SV_SpawnServer(void) CL_ConnectToServer(); else doomcom->numslots = 1; } - - return SV_AddWaitingPlayers(cv_playername.zstring, cv_playername2.zstring); } void SV_StopServer(void) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e07864122..b3ee95c0c 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -412,7 +412,7 @@ void SendKick(UINT8 playernum, UINT8 msg); void NetUpdate(void); void SV_StartSinglePlayerServer(void); -boolean SV_SpawnServer(void); +void SV_SpawnServer(void); void SV_StopServer(void); void SV_ResetServer(void); void CL_AddSplitscreenPlayer(void); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5f02bc2de..243501ba4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1850,8 +1850,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese // reset players if there is a new one if (!IsPlayerAdmin(consoleplayer)) { - if (SV_SpawnServer()) - buf[0] &= ~(1<<1); + SV_SpawnServer(); if (!Playing()) // you failed to start a server somehow, so cancel the map change return; } From 6ab9b9ae8a29fda62129650c757bd9e2d72a2e64 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 01:48:26 +0100 Subject: [PATCH 29/93] Remove useless condition --- src/d_clisrv.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 0c6960236..bc0992539 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3563,17 +3563,14 @@ static void HandleConnect(SINT8 node) DEBFILE("new node joined\n"); } #ifndef NONET - if (netnodes[node].numplayerswaiting) + if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) { - if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) - { - SV_SendSaveGame(node, false); // send a complete game state - DEBFILE("send savegame\n"); - } - SV_AddWaitingPlayers(names[0], names[1]); - joindelay += cv_joindelay.value * TICRATE; - player_joining = true; + SV_SendSaveGame(node, false); // send a complete game state + DEBFILE("send savegame\n"); } + SV_AddWaitingPlayers(names[0], names[1]); + joindelay += cv_joindelay.value * TICRATE; + player_joining = true; #endif } } From f501c4b25072a063141649353f86bfbada89d83e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 02:46:59 +0100 Subject: [PATCH 30/93] Remove unneeded numplayerswaiting field --- src/d_clisrv.c | 98 ++++++++++++++++++++++++-------------------------- src/d_net.h | 1 - 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bc0992539..7aafdf539 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3262,62 +3262,54 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) LUA_HookInt(newplayernum, HOOK(PlayerJoin)); } -static void SV_AddWaitingPlayers(const char *name, const char *name2) +static void SV_AddPlayer(SINT8 node, const char *name) { - INT32 node, n; + INT32 n; UINT8 buf[2 + MAXPLAYERNAME]; UINT8 *p; INT32 newplayernum; - for (node = 0; node < MAXNETNODES; node++) + newplayernum = FindRejoinerNum(node); + if (newplayernum == -1) { - // splitscreen can allow 2 player in one node - for (; netnodes[node].numplayerswaiting > 0; netnodes[node].numplayerswaiting--) + // search for a free playernum + // we can't use playeringame since it is not updated here + for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) { - newplayernum = FindRejoinerNum(node); - if (newplayernum == -1) - { - // search for a free playernum - // we can't use playeringame since it is not updated here - for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) - { - if (playeringame[newplayernum]) - continue; - for (n = 0; n < MAXNETNODES; n++) - if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) - break; - if (n == MAXNETNODES) - break; - } - } - - // should never happen since we check the playernum - // before accepting the join - I_Assert(newplayernum < MAXPLAYERS); - - playernode[newplayernum] = (UINT8)node; - - p = buf + 2; - buf[0] = (UINT8)node; - buf[1] = newplayernum; - if (netnodes[node].numplayers < 1) - { - netnodes[node].player = newplayernum; - WRITESTRINGN(p, name, MAXPLAYERNAME); - } - else - { - netnodes[node].player2 = newplayernum; - buf[1] |= 0x80; - WRITESTRINGN(p, name2, MAXPLAYERNAME); - } - netnodes[node].numplayers++; - - SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); - - DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); + if (playeringame[newplayernum]) + continue; + for (n = 0; n < MAXNETNODES; n++) + if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) + break; + if (n == MAXNETNODES) + break; } } + + // should never happen since we check the playernum + // before accepting the join + I_Assert(newplayernum < MAXPLAYERS); + + playernode[newplayernum] = (UINT8)node; + + p = buf + 2; + buf[0] = (UINT8)node; + buf[1] = newplayernum; + if (netnodes[node].numplayers < 1) + { + netnodes[node].player = newplayernum; + } + else + { + netnodes[node].player2 = newplayernum; + buf[1] |= 0x80; + } + WRITESTRINGN(p, name, MAXPLAYERNAME); + netnodes[node].numplayers++; + + SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); + + DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); } void CL_AddSplitscreenPlayer(void) @@ -3522,11 +3514,12 @@ static void HandleConnect(SINT8 node) SV_SendRefuse(node, refuse); else { + INT32 numplayers = netbuffer->u.clientcfg.localplayers; #ifndef NONET boolean newnode = false; #endif - for (i = 0; i < netbuffer->u.clientcfg.localplayers - netnodes[node].numplayers; i++) + for (i = 0; i < numplayers; i++) { strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) @@ -3537,7 +3530,6 @@ static void HandleConnect(SINT8 node) } // client authorised to join - netnodes[node].numplayerswaiting = (UINT8)(netbuffer->u.clientcfg.localplayers - netnodes[node].numplayers); if (!netnodes[node].ingame) { gamestate_t backupstate = gamestate; @@ -3568,7 +3560,12 @@ static void HandleConnect(SINT8 node) SV_SendSaveGame(node, false); // send a complete game state DEBFILE("send savegame\n"); } - SV_AddWaitingPlayers(names[0], names[1]); + + // Splitscreen can allow 2 players in one node + SV_AddPlayer(node, names[0]); + if (numplayers > 1) + SV_AddPlayer(node, names[1]); + joindelay += cv_joindelay.value * TICRATE; player_joining = true; #endif @@ -3993,7 +3990,6 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) // nodeingame will be put false in the execution of kick command // this allow to send some packets to the quitting client to have their ack back - netnodes[node].numplayerswaiting = 0; if (netconsole != -1 && playeringame[netconsole]) { UINT8 kickmsg; diff --git a/src/d_net.h b/src/d_net.h index 9eee53894..c6c9e2894 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -45,7 +45,6 @@ typedef struct netnode_s SINT8 player; SINT8 player2; // say the numplayer for this node if any (splitscreen) UINT8 numplayers; // used specialy for scplitscreen - UINT8 numplayerswaiting; tic_t tic; // what tic the client have received tic_t supposedtic; // nettics prevision for smaller packet From b66353932d80f27ba780ac474061a8c1cc841708 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 13:10:01 +0100 Subject: [PATCH 31/93] Remove broken joinnextround console variable --- src/d_clisrv.c | 6 ------ src/d_clisrv.h | 2 +- src/d_netcmd.c | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7aafdf539..31a19001a 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2925,7 +2925,6 @@ static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, N consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; @@ -3532,17 +3531,13 @@ static void HandleConnect(SINT8 node) // client authorised to join if (!netnodes[node].ingame) { - gamestate_t backupstate = gamestate; #ifndef NONET newnode = true; #endif SV_AddNode(node); - if (cv_joinnextround.value && gameaction == ga_nothing) - G_SetGamestate(GS_WAITINGPLAYERS); if (!SV_SendServerConfig(node)) { - G_SetGamestate(backupstate); /// \note Shouldn't SV_SendRefuse be called before ResetNode? ResetNode(node); SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); @@ -3551,7 +3546,6 @@ static void HandleConnect(SINT8 node) } //if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc? // SV_SendPlayerConfigs(node); // send bare minimum player info - G_SetGamestate(backupstate); DEBFILE("new node joined\n"); } #ifndef NONET diff --git a/src/d_clisrv.h b/src/d_clisrv.h index b3ee95c0c..99d859924 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -394,7 +394,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout; +extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_joindelay, cv_rejointimeout; extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 243501ba4..64f478ff7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -630,7 +630,6 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_downloadspeed); #ifndef NONET CV_RegisterVar(&cv_allownewplayer); - CV_RegisterVar(&cv_joinnextround); CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); #endif From d816e4d111499a820f09df3fbc9acaa57a1859bc Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 14:01:03 +0100 Subject: [PATCH 32/93] Cleanup HandleConnect --- src/d_clisrv.c | 96 +++++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 55 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 31a19001a..699c372d7 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3501,69 +3501,55 @@ ConnectionRefused (SINT8 node, INT32 rejoinernum) static void HandleConnect(SINT8 node) { char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; + INT32 numplayers = netbuffer->u.clientcfg.localplayers; INT32 rejoinernum; INT32 i; - const char *refuse; rejoinernum = FindRejoinerNum(node); - refuse = ConnectionRefused(node, rejoinernum); - + const char *refuse = ConnectionRefused(node, rejoinernum); if (refuse) - SV_SendRefuse(node, refuse); - else { - INT32 numplayers = netbuffer->u.clientcfg.localplayers; -#ifndef NONET - boolean newnode = false; -#endif - - for (i = 0; i < numplayers; i++) - { - strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); - if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) - { - SV_SendRefuse(node, "Bad player name"); - return; - } - } - - // client authorised to join - if (!netnodes[node].ingame) - { -#ifndef NONET - newnode = true; -#endif - SV_AddNode(node); - - if (!SV_SendServerConfig(node)) - { - /// \note Shouldn't SV_SendRefuse be called before ResetNode? - ResetNode(node); - SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); - /// \todo fix this !!! - return; // restart the while - } - //if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc? - // SV_SendPlayerConfigs(node); // send bare minimum player info - DEBFILE("new node joined\n"); - } -#ifndef NONET - if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) - { - SV_SendSaveGame(node, false); // send a complete game state - DEBFILE("send savegame\n"); - } - - // Splitscreen can allow 2 players in one node - SV_AddPlayer(node, names[0]); - if (numplayers > 1) - SV_AddPlayer(node, names[1]); - - joindelay += cv_joindelay.value * TICRATE; - player_joining = true; -#endif + SV_SendRefuse(node, refuse); + return; } + + for (i = 0; i < numplayers; i++) + { + strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); + if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) + { + SV_SendRefuse(node, "Bad player name"); + return; + } + } + + SV_AddNode(node); + + if (!SV_SendServerConfig(node)) + { + /// \note Shouldn't SV_SendRefuse be called before ResetNode? + ResetNode(node); + SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); + /// \todo fix this !!! + return; // restart the while + } + DEBFILE("new node joined\n"); + +#ifndef NONET + if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) + { + SV_SendSaveGame(node, false); // send a complete game state + DEBFILE("send savegame\n"); + } + + // Splitscreen can allow 2 players in one node + for (i = 0; i < numplayers; i++) + SV_AddPlayer(node, names[i]); + + joindelay += cv_joindelay.value * TICRATE; + player_joining = true; +#endif } /** Called when a PT_SERVERSHUTDOWN packet is received From 7b96efc17964972753bc38ca310dcd64732d9ca9 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 14:01:37 +0100 Subject: [PATCH 33/93] Rename ConnectionRefused to be more descriptive --- 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 699c372d7..d7d02f9bb 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3422,7 +3422,7 @@ static size_t TotalTextCmdPerTic(tic_t tic) } static const char * -ConnectionRefused (SINT8 node, INT32 rejoinernum) +GetRefuseMessage (SINT8 node, INT32 rejoinernum) { clientconfig_pak *cc = &netbuffer->u.clientcfg; @@ -3507,7 +3507,7 @@ static void HandleConnect(SINT8 node) rejoinernum = FindRejoinerNum(node); - const char *refuse = ConnectionRefused(node, rejoinernum); + const char *refuse = GetRefuseMessage(node, rejoinernum); if (refuse) { SV_SendRefuse(node, refuse); From 1f4c71739ab57fbd035bd1f13d178b981a2836f4 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 14:03:32 +0100 Subject: [PATCH 34/93] Ignore duplicate PT_CLIENTJOIN packets --- src/d_clisrv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d7d02f9bb..b25e34c56 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3505,6 +3505,10 @@ static void HandleConnect(SINT8 node) INT32 rejoinernum; INT32 i; + // Ignore duplicate packets + if (netnodes[node].ingame) + return; + rejoinernum = FindRejoinerNum(node); const char *refuse = GetRefuseMessage(node, rejoinernum); From 07bc9222737a026859bc99d56b598c8973a66bb9 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 30 Dec 2022 15:07:57 +0100 Subject: [PATCH 35/93] Delete netcode Just kidding, I just deleted NONET --- src/Makefile | 1 - src/Makefile.d/features.mk | 4 +- src/Makefile.d/win32.mk | 2 - src/d_clisrv.c | 85 +------------ src/d_clisrv.h | 2 - src/d_net.c | 48 -------- src/d_net.h | 2 - src/d_netcmd.c | 2 - src/d_netfil.c | 6 - src/d_netfil.h | 2 - src/deh_tables.c | 2 +- src/doomdef.h | 3 +- src/hu_stuff.c | 31 ----- src/i_tcp.c | 238 ++++++++++++++----------------------- src/m_menu.c | 57 +-------- src/m_menu.h | 2 +- src/mserv.c | 6 - src/sdl/i_system.c | 4 - 18 files changed, 97 insertions(+), 400 deletions(-) diff --git a/src/Makefile b/src/Makefile index 36b1a7efa..7fe7f8990 100644 --- a/src/Makefile +++ b/src/Makefile @@ -64,7 +64,6 @@ # # Netplay incompatible # -------------------- -# NONET=1 - Disable online capability. # NOMD5=1 - Disable MD5 checksum (validation tool). # NOPOSTPROCESSING=1 - ? # MOBJCONSISTANCY=1 - ?? diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk index 8ba33383b..9acbb4d86 100644 --- a/src/Makefile.d/features.mk +++ b/src/Makefile.d/features.mk @@ -3,7 +3,7 @@ # passthru_opts+=\ - NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\ + NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\ MOBJCONSISTANCY PACKETDROP ZDEBUG\ HAVE_MINIUPNPC\ @@ -46,13 +46,11 @@ sources+=apng.c endif endif -ifndef NONET ifndef NOCURL CURLCONFIG?=curl-config $(eval $(call Configure,CURL,$(CURLCONFIG))) opts+=-DHAVE_CURL endif -endif ifdef HAVE_MINIUPNPC libs+=-lminiupnpc diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk index 0e48ed683..e7269e1e7 100644 --- a/src/Makefile.d/win32.mk +++ b/src/Makefile.d/win32.mk @@ -35,12 +35,10 @@ libs+=-lws2_32 endif endif -ifndef NONET ifndef MINGW64 # miniupnc is broken with MINGW64 opts+=-I../libs -DSTATIC_MINIUPNPC libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi endif -endif ifndef MINGW64 32=32 diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b25e34c56..cb1ccd539 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -53,12 +53,10 @@ // aaaaaa #include "i_gamepad.h" -#ifndef NONET // cl loading screen #include "v_video.h" #include "f_finale.h" #include "snake.h" -#endif // // NETWORKING @@ -535,7 +533,6 @@ static cl_mode_t cl_mode = CL_SEARCHING; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list -#ifndef NONET static void *snake = NULL; static void CL_DrawConnectionStatusBox(void) @@ -716,7 +713,6 @@ static inline void CL_DrawConnectionStatus(void) } } } -#endif static boolean CL_AskFileList(INT32 firstfile) { @@ -983,7 +979,6 @@ static boolean SV_SendServerConfig(INT32 node) return waspacketsent; } -#ifndef NONET #define SAVEGAMESIZE (768*1024) static boolean SV_ResendingSavegameToAnyone(void) @@ -1210,9 +1205,7 @@ static void CL_ReloadReceivedSavegame(void) CONS_Printf(M_GetText("Game state reloaded\n")); } -#endif -#ifndef NONET static void SendAskInfo(INT32 node) { const tic_t asktime = I_GetTime(); @@ -1430,12 +1423,8 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif/*MASTERSERVER*/ } -#endif // ifndef NONET - static void M_ConfirmConnect(event_t *ev) { -#ifndef NONET - if (ev->type == ev_keydown || ev->type == ev_gamepad_down) { if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A)) @@ -1459,9 +1448,6 @@ static void M_ConfirmConnect(event_t *ev) M_ClearMenus(true); } } -#else - (void)ev; -#endif } static boolean CL_FinishedFileList(void) @@ -1541,7 +1527,6 @@ static boolean CL_FinishedFileList(void) return false; } -#ifndef NONET downloadcompletednum = 0; downloadcompletedsize = 0; totalfilesrequestednum = 0; @@ -1561,7 +1546,6 @@ static boolean CL_FinishedFileList(void) downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20)); else downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10)); -#endif if (serverisfull) M_StartMessage(va(M_GetText( @@ -1586,7 +1570,6 @@ static boolean CL_FinishedFileList(void) return true; } -#ifndef NONET static const char * InvalidServerReason (serverinfo_pak *info) { #define EOT "\nPress ESC\n" @@ -1650,7 +1633,6 @@ static const char * InvalidServerReason (serverinfo_pak *info) #undef EOT } -#endif // ifndef NONET /** Called by CL_ServerConnectionTicker * @@ -1662,7 +1644,6 @@ static const char * InvalidServerReason (serverinfo_pak *info) */ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) { -#ifndef NONET INT32 i; // serverlist is updated by GetPacket function @@ -1732,11 +1713,6 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) SendAskInfo(servernode); *asksent = I_GetTime(); } -#else - (void)asksent; - // No netgames, so we skip this state. - cl_mode = CL_ASKJOIN; -#endif // ifndef NONET/else return true; } @@ -1756,10 +1732,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic boolean waitmore; INT32 i; -#ifdef NONET - (void)tmpsave; -#endif - switch (cl_mode) { case CL_SEARCHING: @@ -1824,12 +1796,12 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic ), NULL, MM_NOTHING); return false; } -#ifndef NONET + // 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 (I_GetTime() >= *asksent && CL_SendJoin()) { *asksent = I_GetTime() + NEWTICRATE*3; @@ -1842,7 +1814,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic cl_mode = CL_ASKJOIN; } break; -#ifndef NONET case CL_DOWNLOADSAVEGAME: // At this state, the first (and only) needed file is the gamestate if (fileneeded[0].status == FS_FOUND) @@ -1853,7 +1824,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } // don't break case continue to CL_CONNECTED else break; -#endif case CL_CONNECTED: case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect @@ -1898,10 +1868,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic memset(gamekeydown, 0, NUMKEYS); return false; } -#ifndef NONET else if (cl_mode == CL_DOWNLOADFILES && snake) Snake_Update(snake); -#endif if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) FileReceiveTicker(); @@ -1912,7 +1880,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic //FileSendTicker(); *oldtic = I_GetTime(); -#ifndef NONET if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) { if (!snake) @@ -1935,10 +1902,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic S_UpdateSounds(); S_UpdateClosedCaptions(); } -#else - CON_Drawer(); - I_UpdateNoVsync(); -#endif } else { @@ -1958,22 +1921,18 @@ static void CL_ConnectToServer(void) { INT32 pnumnodes, nodewaited = doomcom->numnodes, i; tic_t oldtic; -#ifndef NONET tic_t asksent; char tmpsave[256]; sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); lastfilenum = -1; -#endif cl_mode = CL_SEARCHING; -#ifndef NONET // Don't get a corrupt savegame error because tmpsave already exists if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) I_Error("Can't delete %s\n", tmpsave); -#endif if (netgame) { @@ -1994,7 +1953,6 @@ static void CL_ConnectToServer(void) pnumnodes = 1; oldtic = I_GetTime() - 1; -#ifndef NONET asksent = (tic_t) - TICRATE; firstconnectattempttime = I_GetTime(); @@ -2010,16 +1968,11 @@ static void CL_ConnectToServer(void) serverlist[i].info.version%100, serverlist[i].info.subversion); } SL_ClearServerList(servernode); -#endif do { // If the connection was aborted for some reason, leave -#ifndef NONET if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) -#else - if (!CL_ServerConnectionTicker((char*)NULL, &oldtic, (tic_t *)NULL)) -#endif return; if (server) @@ -2037,7 +1990,6 @@ static void CL_ConnectToServer(void) displayplayer = consoleplayer; } -#ifndef NONET typedef struct banreason_s { char *reason; @@ -2276,7 +2228,6 @@ static void Command_connect(void) botskin = 0; CL_ConnectToServer(); } -#endif static void ResetNode(INT32 node) { @@ -2437,10 +2388,8 @@ void CL_Reset(void) FreeFileNeeded(); fileneedednum = 0; -#ifndef NONET totalfilesrequestednum = 0; totalfilesrequestedsize = 0; -#endif firstconnectattempttime = 0; serverisfull = false; connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack @@ -2448,7 +2397,6 @@ void CL_Reset(void) // D_StartTitle should get done now, but the calling function will handle it } -#ifndef NONET static void Command_GetPlayerNum(void) { INT32 i; @@ -2726,7 +2674,6 @@ static void Command_ResendGamestate(void) return; } } -#endif static void Got_KickCmd(UINT8 **p, INT32 playernum) { @@ -2810,10 +2757,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { if (I_Ban && !I_Ban(playernode[(INT32)pnum])) CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); -#ifndef NONET else Ban_Add(reason); -#endif } switch (msg) @@ -2953,7 +2898,6 @@ void D_ClientServerInit(void) DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", VERSION/100, VERSION%100, SUBVERSION)); -#ifndef NONET COM_AddCommand("getplayernum", Command_GetPlayerNum); COM_AddCommand("kick", Command_Kick); COM_AddCommand("ban", Command_Ban); @@ -2970,17 +2914,14 @@ void D_ClientServerInit(void) #endif #ifdef _DEBUG COM_AddCommand("numnodes", Command_Numnodes); -#endif #endif RegisterNetXCmd(XD_KICK, Got_KickCmd); RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); -#ifndef NONET #ifdef DUMPCONSISTENCY CV_RegisterVar(&cv_dumpconsistency); #endif Ban_Load_File(false); -#endif gametic = 0; localgametic = 0; @@ -3540,7 +3481,6 @@ static void HandleConnect(SINT8 node) } DEBFILE("new node joined\n"); -#ifndef NONET if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) { SV_SendSaveGame(node, false); // send a complete game state @@ -3553,7 +3493,6 @@ static void HandleConnect(SINT8 node) joindelay += cv_joindelay.value * TICRATE; player_joining = true; -#endif } /** Called when a PT_SERVERSHUTDOWN packet is received @@ -3586,7 +3525,6 @@ static void HandleTimeout(SINT8 node) M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); } -#ifndef NONET /** Called when a PT_SERVERINFO packet is received * * \param node The packet sender @@ -3608,7 +3546,6 @@ static void HandleServerInfo(SINT8 node) SL_InsertServer(&netbuffer->u.serverinfo, node); } -#endif // Helper function for packets that should only be sent by the server // If it is NOT from the server, bail out and close the connection! @@ -3744,14 +3681,9 @@ static void PT_ServerCFG(SINT8 node) playernode[(UINT8)serverplayer] = servernode; if (netgame) -#ifndef NONET CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); -#else - CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); -#endif DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); -#ifndef NONET /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? /// Shouldn't them be downloaded even at intermission time? /// Also, according to HandleConnect, the server will send the savegame even during intermission... @@ -3759,7 +3691,6 @@ static void PT_ServerCFG(SINT8 node) netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) cl_mode = CL_DOWNLOADSAVEGAME; else -#endif cl_mode = CL_CONNECTED; } @@ -3823,9 +3754,7 @@ static void PT_ClientCmd(SINT8 node, INT32 netconsole) // Check player consistancy during the level if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) -#ifndef NONET && !SV_ResendingSavegameToAnyone() -#endif && !netnodes[node].resendingsavegame && netnodes[node].savegameresendcooldown <= I_GetTime()) { if (cv_resynchattempts.value) @@ -4000,7 +3929,6 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) static void PT_CanReceiveGamestate(SINT8 node) { -#ifndef NONET if (client || netnodes[node].sendingsavegame) return; @@ -4008,9 +3936,6 @@ static void PT_CanReceiveGamestate(SINT8 node) SV_SendSaveGame(node, true); // Resend a complete game state netnodes[node].resendingsavegame = true; -#else - (void)node; -#endif } static void PT_AskLuaFile(SINT8 node) @@ -4134,7 +4059,6 @@ static void PT_WillResendGamestate(SINT8 node) { (void)node; -#ifndef NONET char tmpsave[256]; if (server || cl_redownloadinggamestate) @@ -4157,7 +4081,6 @@ static void PT_WillResendGamestate(SINT8 node) CL_PrepareDownloadSaveGame(tmpsave); cl_redownloadinggamestate = true; -#endif } static void PT_SendingLuaFile(SINT8 node) @@ -4296,13 +4219,11 @@ static void GetPackets(void) } } -#ifndef NONET if (netbuffer->packettype == PT_SERVERINFO) { HandleServerInfo(node); continue; } -#endif if (netbuffer->packettype == PT_PLAYERINFO) continue; // We do nothing with PLAYERINFO, that's for the MS browser. @@ -4906,11 +4827,9 @@ void NetUpdate(void) if (client) { -#ifndef NONET // If the client just finished redownloading the game state, load it if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) CL_ReloadReceivedSavegame(); -#endif CL_SendClientCmd(); // Send tic cmd hu_redownloadinggamestate = cl_redownloadinggamestate; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 99d859924..0d6add13a 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -437,11 +437,9 @@ boolean TryRunTics(tic_t realtic); /*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum); void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum);*/ -#ifndef NONET // translate a playername in a player number return -1 if not found and // print a error message in the console SINT8 nametonum(const char *name); -#endif extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; diff --git a/src/d_net.c b/src/d_net.c index a7e1eb16d..9e3759d32 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -138,7 +138,6 @@ boolean Net_GetNetStat(void) #define URGENTFREESLOTNUM 10 #define ACKTOSENDTIMEOUT (TICRATE/11) -#ifndef NONET typedef struct { UINT8 acknum; @@ -152,7 +151,6 @@ typedef struct doomdata_t data; } pak; } ackpak_t; -#endif typedef enum { @@ -160,10 +158,8 @@ typedef enum NF_TIMEOUT = 2, // Flag is set when the node got a timeout } node_flags_t; -#ifndef NONET // Table of packets that were not acknowleged can be resent (the sender window) static ackpak_t ackpak[MAXACKPACKETS]; -#endif typedef struct { @@ -191,7 +187,6 @@ typedef struct static node_t nodes[MAXNETNODES]; #define NODETIMEOUT 14 -#ifndef NONET // return <0 if a < b (mod 256) // 0 if a = n (mod 256) // >0 if a > b (mod 256) @@ -426,21 +421,15 @@ static boolean Processackpak(void) } return goodpacket; } -#endif // send special packet with only ack on it void Net_SendAcks(INT32 node) { -#ifdef NONET - (void)node; -#else netbuffer->packettype = PT_NOTHING; M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND); HSendPacket(node, false, 0, MAXACKTOSEND); -#endif } -#ifndef NONET static void GotAcks(void) { INT32 i, j; @@ -463,7 +452,6 @@ static void GotAcks(void) } } } -#endif void Net_ConnectionTimeout(INT32 node) { @@ -489,7 +477,6 @@ void Net_ConnectionTimeout(INT32 node) // Resend the data if needed void Net_AckTicker(void) { -#ifndef NONET INT32 i; for (i = 0; i < MAXACKPACKETS; i++) @@ -536,16 +523,12 @@ void Net_AckTicker(void) } } } -#endif } // Remove last packet received ack before resending the ackreturn // (the higher layer doesn't have room, or something else ....) void Net_UnAcknowledgePacket(INT32 node) { -#ifdef NONET - (void)node; -#else INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND; DEBFILE(va("UnAcknowledge node %d\n", node)); if (!node) @@ -577,10 +560,8 @@ void Net_UnAcknowledgePacket(INT32 node) if (!nodes[node].firstacktosend) nodes[node].firstacktosend = 1; } -#endif } -#ifndef NONET /** Checks if all acks have been received * * \return True if all acks have been received @@ -596,7 +577,6 @@ static boolean Net_AllAcksReceived(void) return true; } -#endif /** Waits for all ackreturns * @@ -605,9 +585,6 @@ static boolean Net_AllAcksReceived(void) */ void Net_WaitAllAckReceived(UINT32 timeout) { -#ifdef NONET - (void)timeout; -#else tic_t tictac = I_GetTime(); timeout = tictac + timeout*NEWTICRATE; @@ -623,7 +600,6 @@ void Net_WaitAllAckReceived(UINT32 timeout) HGetPacket(); Net_AckTicker(); } -#endif } static void InitNode(node_t *node) @@ -639,10 +615,8 @@ static void InitAck(void) { INT32 i; -#ifndef NONET for (i = 0; i < MAXACKPACKETS; i++) ackpak[i].acknum = 0; -#endif for (i = 0; i < MAXNETNODES; i++) InitNode(&nodes[i]); @@ -655,9 +629,6 @@ static void InitAck(void) */ void Net_AbortPacketType(UINT8 packettype) { -#ifdef NONET - (void)packettype; -#else INT32 i; for (i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype @@ -665,7 +636,6 @@ void Net_AbortPacketType(UINT8 packettype) { ackpak[i].acknum = 0; } -#endif } // ----------------------------------------------------------------- @@ -675,9 +645,6 @@ void Net_AbortPacketType(UINT8 packettype) // remove a node, clear all ack from this node and reset askret void Net_CloseConnection(INT32 node) { -#ifdef NONET - (void)node; -#else INT32 i; boolean forceclose = (node & FORCECLOSE) != 0; @@ -722,10 +689,8 @@ void Net_CloseConnection(INT32 node) if (server) SV_AbortLuaFileTransfer(node); I_NetFreeNodenum(node); -#endif } -#ifndef NONET // // Checksum // @@ -741,7 +706,6 @@ static UINT32 NetbufferChecksum(void) return LONG(c); } -#endif #ifdef DEBUGFILE @@ -983,14 +947,12 @@ void Command_Droprate(void) packetdroprate = droprate; } -#ifndef NONET static boolean ShouldDropPacket(void) { return (packetdropquantity[netbuffer->packettype]) || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; } #endif -#endif // // HSendPacket @@ -1025,11 +987,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen if (!netgame) I_Error("Tried to transmit to another node"); -#ifdef NONET - (void)node; - (void)reliable; - (void)acknum; -#else // do this before GetFreeAcknum because this function backups // the current packet doomcom->remotenode = (INT16)node; @@ -1090,8 +1047,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen } #endif -#endif // ndef NONET - return true; } @@ -1125,8 +1080,6 @@ boolean HGetPacket(void) if (!netgame) return false; -#ifndef NONET - while(true) { //nodejustjoined = I_NetGet(); @@ -1186,7 +1139,6 @@ boolean HGetPacket(void) } break; } -#endif // ndef NONET return true; } diff --git a/src/d_net.h b/src/d_net.h index c6c9e2894..803b49d74 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -66,9 +66,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength); boolean HGetPacket(void); void D_SetDoomcom(void); -#ifndef NONET void D_SaveBan(void); -#endif boolean D_CheckNetGame(void); void D_CloseConnection(void); void Net_UnAcknowledgePacket(INT32 node); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 64f478ff7..69eed90de 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -628,11 +628,9 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_downloadspeed); -#ifndef NONET CV_RegisterVar(&cv_allownewplayer); CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); -#endif COM_AddCommand("ping", Command_Ping_f); CV_RegisterVar(&cv_nettimeout); diff --git a/src/d_netfil.c b/src/d_netfil.c index 1fee1df81..bf3952cc9 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -103,14 +103,12 @@ typedef struct } pauseddownload_t; static pauseddownload_t *pauseddownload = NULL; -#ifndef NONET // for cl loading screen INT32 lastfilenum = -1; INT32 downloadcompletednum = 0; UINT32 downloadcompletedsize = 0; INT32 totalfilesrequestednum = 0; UINT32 totalfilesrequestedsize = 0; -#endif luafiletransfer_t *luafiletransfers = NULL; boolean waitingforluafiletransfer = false; @@ -250,9 +248,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi void CL_PrepareDownloadSaveGame(const char *tmpsave) { -#ifndef NONET lastfilenum = -1; -#endif FreeFileNeeded(); AllocFileNeeded(1); @@ -1466,9 +1462,7 @@ void PT_FileFragment(SINT8 node, INT32 netconsole) I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s); } -#ifndef NONET lastfilenum = filenum; -#endif } /** \brief Checks if a node is downloading a file diff --git a/src/d_netfil.h b/src/d_netfil.h index 5c7f4ef49..ec53be587 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -70,13 +70,11 @@ extern INT32 fileneedednum; extern fileneeded_t *fileneeded; extern char downloaddir[512]; -#ifndef NONET extern INT32 lastfilenum; extern INT32 downloadcompletednum; extern UINT32 downloadcompletedsize; extern INT32 totalfilesrequestednum; extern UINT32 totalfilesrequestedsize; -#endif void AllocFileNeeded(INT32 size); void FreeFileNeeded(void); diff --git a/src/deh_tables.c b/src/deh_tables.c index 6a815b6ea..5607142e5 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4879,7 +4879,7 @@ const char *const MENUTYPES_LIST[] = { "MP_SERVER", "MP_CONNECT", "MP_ROOM", - "MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET + "MP_PLAYERSETUP", "MP_SERVER_OPTIONS", // Options diff --git a/src/doomdef.h b/src/doomdef.h index 84404d6ed..22cafa190 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -56,7 +56,6 @@ #endif #ifdef _WINDOWS -#define NONET #if !defined (HWRENDER) && !defined (NOHW) #define HWRENDER #endif @@ -707,7 +706,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Maintain compatibility with older 2.2 demos #define OLD22DEMOCOMPAT -#if defined (HAVE_CURL) && ! defined (NONET) +#ifdef HAVE_CURL #define MASTERSERVER #else #undef UPDATE_ALERT diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 091e2b2fb..c423f2905 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -175,14 +175,12 @@ static huddrawlist_h luahuddrawlist_scores; static tic_t resynch_ticker = 0; -#ifndef NONET // just after static void Command_Say_f(void); static void Command_Sayto_f(void); static void Command_Sayteam_f(void); static void Command_CSay_f(void); static void Got_Saycmd(UINT8 **p, INT32 playernum); -#endif void HU_LoadGraphics(void) { @@ -327,13 +325,11 @@ void HU_LoadGraphics(void) // void HU_Init(void) { -#ifndef NONET COM_AddCommand("say", Command_Say_f, COM_LUA); COM_AddCommand("sayto", Command_Sayto_f, COM_LUA); COM_AddCommand("sayteam", Command_Sayteam_f, COM_LUA); COM_AddCommand("csay", Command_CSay_f, COM_LUA); RegisterNetXCmd(XD_SAY, Got_Saycmd); -#endif // set shift translation table shiftxform = english_shiftxform; @@ -363,8 +359,6 @@ void HU_Start(void) // EXECUTION //====================================================================== -#ifndef NONET - // EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM static UINT32 chat_nummsg_log = 0; @@ -412,11 +406,9 @@ static void HU_removeChatText_Log(void) } chat_nummsg_log--; // lost 1 msg. } -#endif void HU_AddChatText(const char *text, boolean playsound) { -#ifndef NONET if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat. S_StartSound(NULL, sfx_radio); // reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game. @@ -438,14 +430,8 @@ void HU_AddChatText(const char *text, boolean playsound) CONS_Printf("%s\n", text); else // if we aren't, still save the message to log.txt CON_LogMessage(va("%s\n", text)); -#else - (void)playsound; - CONS_Printf("%s\n", text); -#endif } -#ifndef NONET - /** Runs a say command, sending an ::XD_SAY message. * A say command consists of a signed 8-bit integer for the target, an * unsigned 8-bit flag variable, and then the message itself. @@ -865,8 +851,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) #endif } -#endif - // // void HU_Ticker(void) @@ -882,7 +866,6 @@ void HU_Ticker(void) else hu_showscores = false; -#ifndef NONET if (chat_on) { // count down the scroll timer. @@ -910,7 +893,6 @@ void HU_Ticker(void) HU_removeChatText_Mini(); } } -#endif if (cechotimer > 0) --cechotimer; @@ -918,8 +900,6 @@ void HU_Ticker(void) resynch_ticker++; } -#ifndef NONET - static boolean teamtalk = false; static boolean justscrolleddown; static boolean justscrolledup; @@ -1027,8 +1007,6 @@ static void HU_sendChatMessage(void) } } -#endif - void HU_clearChatChars(void) { memset(w_chat, '\0', sizeof(w_chat)); @@ -1043,9 +1021,7 @@ void HU_clearChatChars(void) // boolean HU_Responder(event_t *ev) { -#ifndef NONET INT32 c=0; -#endif if (ev->type != ev_keydown) return false; @@ -1072,7 +1048,6 @@ boolean HU_Responder(event_t *ev) return false; }*/ //We don't actually care about that unless we get splitscreen netgames. :V -#ifndef NONET c = (INT32)ev->key; if (!chat_on) @@ -1222,7 +1197,6 @@ boolean HU_Responder(event_t *ev) return true; } -#endif return false; } @@ -1232,8 +1206,6 @@ boolean HU_Responder(event_t *ev) // HEADS UP DRAWING //====================================================================== -#ifndef NONET - // Precompile a wordwrapped string to any given width. // This is a muuuch better method than V_WORDWRAP. // again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. @@ -1813,7 +1785,6 @@ static void HU_DrawChat_Old(void) if (hu_tick < 4) V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true); } -#endif // Draw crosshairs at the exact center of the view. // In splitscreen, crosshairs are stretched vertically to compensate for V_PERPLAYER squishing them. @@ -1953,7 +1924,6 @@ static void HU_DrawDemoInfo(void) // void HU_Drawer(void) { -#ifndef NONET // draw chat string plus cursor if (chat_on) { @@ -1970,7 +1940,6 @@ void HU_Drawer(void) if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden) HU_drawMiniChat(); // draw messages in a cool fashion. } -#endif if (cechotimer) HU_DrawCEcho(); diff --git a/src/i_tcp.c b/src/i_tcp.c index 00aebddd3..ec3d1ae93 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -38,96 +38,87 @@ #include "doomdef.h" -#if defined (NOMD5) && !defined (NONET) - //#define NONET +#ifdef USE_WINSOCK1 + #include +#else + #ifndef USE_WINSOCK + #include + #ifdef __APPLE_CC__ + #ifndef _BSD_SOCKLEN_T_ + #define _BSD_SOCKLEN_T_ + #endif //_BSD_SOCKLEN_T_ + #endif //__APPLE_CC__ + #include + #include + #include + #include + #endif //normal BSD API + + #include + #include + + #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) + #include + #endif // UNIXCOMMON #endif -#ifdef NONET - #undef HAVE_MINIUPNPC -#else - #ifdef USE_WINSOCK1 - #include - #else - #ifndef USE_WINSOCK - #include - #ifdef __APPLE_CC__ - #ifndef _BSD_SOCKLEN_T_ - #define _BSD_SOCKLEN_T_ - #endif //_BSD_SOCKLEN_T_ - #endif //__APPLE_CC__ - #include - #include - #include - #include - #endif //normal BSD API - - #include - #include - - #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) - #include - #endif // UNIXCOMMON +#ifdef USE_WINSOCK + // some undefined under win32 + #undef errno + //#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right? + #define errno h_errno // some very strange things happen when not using h_error?!? + #ifdef EWOULDBLOCK + #undef EWOULDBLOCK #endif - - #ifdef USE_WINSOCK - // some undefined under win32 - #undef errno - //#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right? - #define errno h_errno // some very strange things happen when not using h_error?!? - #ifdef EWOULDBLOCK - #undef EWOULDBLOCK - #endif - #define EWOULDBLOCK WSAEWOULDBLOCK - #ifdef EMSGSIZE - #undef EMSGSIZE - #endif - #define EMSGSIZE WSAEMSGSIZE - #ifdef ECONNREFUSED - #undef ECONNREFUSED - #endif - #define ECONNREFUSED WSAECONNREFUSED - #ifdef ETIMEDOUT - #undef ETIMEDOUT - #endif - #define ETIMEDOUT WSAETIMEDOUT - #ifndef IOC_VENDOR - #define IOC_VENDOR 0x18000000 - #endif - #ifndef _WSAIOW - #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) - #endif - #ifndef SIO_UDP_CONNRESET - #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) - #endif - #ifndef AI_ADDRCONFIG - #define AI_ADDRCONFIG 0x00000400 - #endif - #ifndef STATUS_INVALID_PARAMETER - #define STATUS_INVALID_PARAMETER 0xC000000D - #endif - #endif // USE_WINSOCK - - typedef union - { - struct sockaddr any; - struct sockaddr_in ip4; - #ifdef HAVE_IPV6 - struct sockaddr_in6 ip6; + #define EWOULDBLOCK WSAEWOULDBLOCK + #ifdef EMSGSIZE + #undef EMSGSIZE #endif - } mysockaddr_t; + #define EMSGSIZE WSAEMSGSIZE + #ifdef ECONNREFUSED + #undef ECONNREFUSED + #endif + #define ECONNREFUSED WSAECONNREFUSED + #ifdef ETIMEDOUT + #undef ETIMEDOUT + #endif + #define ETIMEDOUT WSAETIMEDOUT + #ifndef IOC_VENDOR + #define IOC_VENDOR 0x18000000 + #endif + #ifndef _WSAIOW + #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) + #endif + #ifndef SIO_UDP_CONNRESET + #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) + #endif + #ifndef AI_ADDRCONFIG + #define AI_ADDRCONFIG 0x00000400 + #endif + #ifndef STATUS_INVALID_PARAMETER + #define STATUS_INVALID_PARAMETER 0xC000000D + #endif +#endif // USE_WINSOCK - #ifdef HAVE_MINIUPNPC - #ifdef STATIC_MINIUPNPC - #define STATICLIB - #endif - #include "miniupnpc/miniwget.h" - #include "miniupnpc/miniupnpc.h" - #include "miniupnpc/upnpcommands.h" - #undef STATICLIB - static UINT8 UPNP_support = TRUE; - #endif // HAVE_MINIUPNC +typedef union +{ + struct sockaddr any; + struct sockaddr_in ip4; +#ifdef HAVE_IPV6 + struct sockaddr_in6 ip6; +#endif +} mysockaddr_t; -#endif // !NONET +#ifdef HAVE_MINIUPNPC + #ifdef STATIC_MINIUPNPC + #define STATICLIB + #endif + #include "miniupnpc/miniwget.h" + #include "miniupnpc/miniupnpc.h" + #include "miniupnpc/upnpcommands.h" + #undef STATICLIB + static UINT8 UPNP_support = TRUE; +#endif // HAVE_MINIUPNC #define MAXBANS 100 @@ -151,7 +142,7 @@ #define SELECTTEST #define DEFAULTPORT "5029" -#if defined (USE_WINSOCK) && !defined (NONET) +#ifdef USE_WINSOCK typedef SOCKET SOCKET_TYPE; #define ERRSOCKET (SOCKET_ERROR) #else @@ -163,22 +154,20 @@ #define ERRSOCKET (-1) #endif -#ifndef NONET - // define socklen_t in DOS/Windows if it is not already defined - #ifdef USE_WINSOCK1 - typedef int socklen_t; - #endif - static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; - static size_t mysocketses = 0; - static int myfamily[MAXNETNODES+1] = {0}; - static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET}; - static mysockaddr_t clientaddress[MAXNETNODES+1]; - static mysockaddr_t broadcastaddress[MAXNETNODES+1]; - static size_t broadcastaddresses = 0; - static boolean nodeconnected[MAXNETNODES+1]; - static mysockaddr_t banned[MAXBANS]; - static UINT8 bannedmask[MAXBANS]; +// define socklen_t in DOS/Windows if it is not already defined +#ifdef USE_WINSOCK1 + typedef int socklen_t; #endif +static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; +static size_t mysocketses = 0; +static int myfamily[MAXNETNODES+1] = {0}; +static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET}; +static mysockaddr_t clientaddress[MAXNETNODES+1]; +static mysockaddr_t broadcastaddress[MAXNETNODES+1]; +static size_t broadcastaddresses = 0; +static boolean nodeconnected[MAXNETNODES+1]; +static mysockaddr_t banned[MAXBANS]; +static UINT8 bannedmask[MAXBANS]; static size_t numbans = 0; static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? @@ -187,7 +176,6 @@ static boolean init_tcp_driver = false; static const char *serverport_name = DEFAULTPORT; static const char *clientport_name;/* any port */ -#ifndef NONET #ifdef USE_WINSOCK // stupid microsoft makes things complicated static char *get_WSAErrorStr(int e) @@ -374,47 +362,33 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) #endif return s; } -#endif static const char *SOCK_GetNodeAddress(INT32 node) { if (node == 0) return "self"; -#ifdef NONET - return NULL; -#else if (!nodeconnected[node]) return NULL; return SOCK_AddrToStr(&clientaddress[node]); -#endif } static const char *SOCK_GetBanAddress(size_t ban) { if (ban >= numbans) return NULL; -#ifdef NONET - return NULL; -#else return SOCK_AddrToStr(&banned[ban]); -#endif } static const char *SOCK_GetBanMask(size_t ban) { -#ifdef NONET - (void)ban; -#else static char s[16]; //255.255.255.255 netmask? no, just CDIR for only if (ban >= numbans) return NULL; if (sprintf(s,"%d",bannedmask[ban]) > 0) return s; -#endif return NULL; } -#ifndef NONET static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) { UINT32 bitmask = INADDR_NONE; @@ -518,9 +492,7 @@ void Command_Numnodes(void) connected, ingame); } #endif -#endif -#ifndef NONET // Returns true if a packet was received from a new node, false in all other cases static boolean SOCK_Get(void) { @@ -583,10 +555,8 @@ static boolean SOCK_Get(void) doomcom->remotenode = -1; // no packet return false; } -#endif // check if we can send (do not go over the buffer) -#ifndef NONET static fd_set masterset; @@ -636,9 +606,7 @@ static boolean SOCK_CanGet(void) return false; } #endif -#endif -#ifndef NONET static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) { socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); @@ -701,9 +669,7 @@ static void SOCK_Send(void) SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); } } -#endif -#ifndef NONET static void SOCK_FreeNodenum(INT32 numnode) { // can't disconnect from self :) @@ -718,12 +684,10 @@ static void SOCK_FreeNodenum(INT32 numnode) // put invalid address memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode])); } -#endif // // UDPsocket // -#ifndef NONET // allocate a socket static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen) @@ -1044,12 +1008,10 @@ static boolean UDP_Socket(void) return true; } -#endif boolean I_InitTcpDriver(void) { boolean tcp_was_up = init_tcp_driver; -#ifndef NONET if (!init_tcp_driver) { #ifdef USE_WINSOCK @@ -1104,7 +1066,7 @@ boolean I_InitTcpDriver(void) #endif init_tcp_driver = true; } -#endif + if (!tcp_was_up && init_tcp_driver) { I_AddExitFunc(I_ShutdownTcpDriver); @@ -1118,7 +1080,6 @@ boolean I_InitTcpDriver(void) return init_tcp_driver; } -#ifndef NONET static void SOCK_CloseSocket(void) { size_t i; @@ -1133,11 +1094,9 @@ static void SOCK_CloseSocket(void) mysockets[i] = ERRSOCKET; } } -#endif void I_ShutdownTcpDriver(void) { -#ifndef NONET SOCK_CloseSocket(); CONS_Printf("I_ShutdownTcpDriver: "); @@ -1147,10 +1106,8 @@ void I_ShutdownTcpDriver(void) #endif CONS_Printf("shut down\n"); init_tcp_driver = false; -#endif } -#ifndef NONET static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) { SINT8 newnode = -1; @@ -1194,11 +1151,9 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) I_freeaddrinfo(ai); return newnode; } -#endif static boolean SOCK_OpenSocket(void) { -#ifndef NONET size_t i; memset(clientaddress, 0, sizeof (clientaddress)); @@ -1222,18 +1177,12 @@ static boolean SOCK_OpenSocket(void) // build the socket but close it first SOCK_CloseSocket(); return UDP_Socket(); -#else - return false; -#endif } static boolean SOCK_Ban(INT32 node) { if (node > MAXNETNODES) return false; -#ifdef NONET - return false; -#else if (numbans == MAXBANS) return false; @@ -1252,16 +1201,10 @@ static boolean SOCK_Ban(INT32 node) #endif numbans++; return true; -#endif } static boolean SOCK_SetBanAddress(const char *address, const char *mask) { -#ifdef NONET - (void)address; - (void)mask; - return false; -#else struct my_addrinfo *ai, *runp, hints; int gaie; @@ -1306,7 +1249,6 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) I_freeaddrinfo(ai); return true; -#endif } static void SOCK_ClearBans(void) diff --git a/src/m_menu.c b/src/m_menu.c index 21ba98dd2..3e1d30feb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -149,9 +149,7 @@ levellist_mode_t levellistmode = LLM_CREATESERVER; UINT8 maplistoption = 0; static char joystickInfo[MAX_JOYSTICKS+1][29]; -#ifndef NONET static UINT32 serverlistpage; -#endif static UINT8 numsaves = 0; static saveinfo_t* savegameinfo = NULL; // Extra info about the save games. @@ -190,10 +188,8 @@ static void M_GoBack(INT32 choice); static void M_StopMessage(INT32 choice); static boolean stopstopmessage = false; -#ifndef NONET static void M_HandleServerPage(INT32 choice); static void M_RoomMenu(INT32 choice); -#endif // Prototyping is fun, innit? // ========================================================================== @@ -296,7 +292,6 @@ static void M_SetupMultiPlayer2(INT32 choice); static void M_StartSplitServerMenu(INT32 choice); static void M_StartServer(INT32 choice); static void M_ServerOptions(INT32 choice); -#ifndef NONET static void M_StartServerMenu(INT32 choice); static void M_ConnectMenu(INT32 choice); static void M_ConnectMenuModChecks(INT32 choice); @@ -304,7 +299,6 @@ static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); static void M_ChooseRoom(INT32 choice); menu_t MP_MainDef; -#endif // Options // Split into multiple parts due to size @@ -382,11 +376,9 @@ static void M_DrawVideoMode(void); static void M_DrawColorMenu(void); static void M_DrawScreenshotMenu(void); static void M_DrawMonitorToggles(void); -#ifndef NONET static void M_DrawConnectMenu(void); static void M_DrawMPMainMenu(void); static void M_DrawRoomMenu(void); -#endif static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color); @@ -401,10 +393,8 @@ static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); static void M_HandleLevelStats(INT32 choice); static void M_HandlePlaystyleMenu(INT32 choice); -#ifndef NONET static boolean M_CancelConnect(void); static void M_HandleConnectIP(INT32 choice); -#endif static void M_HandleSetupMultiPlayer(INT32 choice); static void M_HandleVideoMode(INT32 choice); @@ -503,11 +493,7 @@ consvar_t cv_dummyloadless = CVAR_INIT ("dummyloadless", "In-game", CV_HIDEN, lo static menuitem_t MainMenu[] = { {IT_STRING|IT_CALL, NULL, "1 Player", M_SinglePlayerMenu, 76}, -#ifndef NONET {IT_STRING|IT_SUBMENU, NULL, "Multiplayer", &MP_MainDef, 84}, -#else - {IT_STRING|IT_CALL, NULL, "Multiplayer", M_StartSplitServerMenu, 84}, -#endif {IT_STRING|IT_CALL, NULL, "Extras", M_SecretsMenu, 92}, {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 100}, {IT_STRING|IT_CALL, NULL, "Options", M_Options, 108}, @@ -930,16 +916,10 @@ static menuitem_t SP_PlayerMenu[] = static menuitem_t MP_SplitServerMenu[] = { {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_MapChange, 100}, -#ifdef NONET // In order to keep player setup accessible. - {IT_STRING|IT_CALL, NULL, "Player 1 setup...", M_SetupMultiPlayer, 110}, - {IT_STRING|IT_CALL, NULL, "Player 2 setup...", M_SetupMultiPlayer2, 120}, -#endif {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; -#ifndef NONET - static menuitem_t MP_MainMenu[] = { {IT_HEADER, NULL, "Join a game", NULL, 0}, @@ -1026,8 +1006,6 @@ menuitem_t MP_RoomMenu[] = {IT_DISABLED, NULL, "", M_ChooseRoom, 162}, }; -#endif - static menuitem_t MP_PlayerSetupMenu[] = { {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name @@ -1586,14 +1564,12 @@ enum static menuitem_t OP_ServerOptionsMenu[] = { {IT_HEADER, NULL, "General", NULL, 0}, -#ifndef NONET {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Server name", &cv_servername, 7}, {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21}, {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31}, {IT_STRING | IT_CVAR, NULL, "Minutes for reconnecting", &cv_rejointimeout, 36}, -#endif {IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 41}, {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46}, @@ -1632,7 +1608,6 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216}, {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221}, -#ifndef NONET {IT_HEADER, NULL, "Advanced", NULL, 230}, {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236}, @@ -1640,7 +1615,6 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256}, {IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261}, -#endif }; static menuitem_t OP_MonitorToggleMenu[] = @@ -1954,11 +1928,7 @@ menu_t MP_SplitServerDef = MTREE2(MN_MP_MAIN, MN_MP_SPLITSCREEN), "M_MULTI", sizeof (MP_SplitServerMenu)/sizeof (menuitem_t), -#ifndef NONET &MP_MainDef, -#else - &MainDef, -#endif MP_SplitServerMenu, M_DrawServerMenu, 27, 30 - 50, @@ -1966,8 +1936,6 @@ menu_t MP_SplitServerDef = NULL }; -#ifndef NONET - menu_t MP_MainDef = { MN_MP_MAIN, @@ -2019,15 +1987,10 @@ menu_t MP_RoomDef = 0, NULL }; -#endif menu_t MP_PlayerSetupDef = { -#ifdef NONET - MTREE2(MN_MP_MAIN, MN_MP_PLAYERSETUP), -#else MTREE3(MN_MP_MAIN, MN_MP_SPLITSCREEN, MN_MP_PLAYERSETUP), -#endif "M_SPLAYR", sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t), &MainDef, // doesn't matter @@ -3956,9 +3919,7 @@ void M_Init(void) OP_JoystickSetMenu[i].itemaction = M_AssignJoystick; } -#ifndef NONET CV_RegisterVar(&cv_serversort); -#endif } void M_InitCharacterTables(void) @@ -11110,7 +11071,6 @@ static void M_EndGame(INT32 choice) #define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT) -#ifndef NONET static UINT32 localservercount; static void M_HandleServerPage(INT32 choice) @@ -11382,11 +11342,9 @@ static int ServerListEntryComparator_modified(const void *entry1, const void *en // Default to strcmp. return strcmp(sa->info.servername, sb->info.servername); } -#endif void M_SortServerList(void) { -#ifndef NONET switch(cv_serversort.value) { case 0: // Ping. @@ -11408,10 +11366,8 @@ void M_SortServerList(void) qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); break; } -#endif } -#ifndef NONET #ifdef UPDATE_ALERT static boolean M_CheckMODVersion(int id) { @@ -11610,7 +11566,6 @@ static void M_ChooseRoom(INT32 choice) if (currentMenu == &MP_ConnectDef) M_Refresh(0); } -#endif //NONET //=========================================================================== // Start Server Menu @@ -11658,7 +11613,6 @@ static void M_DrawServerMenu(void) { M_DrawGenericMenu(); -#ifndef NONET // Room name if (currentMenu == &MP_ServerDef) { @@ -11670,15 +11624,10 @@ static void M_DrawServerMenu(void) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, room_list[menuRoomIndex].name); } -#endif if (cv_nextmap.value) { -#ifndef NONET #define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey -#else -#define imgheight 100 -#endif patch_t *PictureOfLevel; lumpnum_t lumpnum; char headerstr[40]; @@ -11730,7 +11679,6 @@ static void M_ServerOptions(INT32 choice) { (void)choice; -#ifndef NONET if ((splitscreen && !netgame) || currentMenu == &MP_SplitServerDef) { OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name @@ -11751,7 +11699,6 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR; } -#endif /* Disable fading because of different menu head. */ if (currentMenu == &OP_MainDef)/* from Options menu */ @@ -11763,7 +11710,6 @@ static void M_ServerOptions(INT32 choice) M_SetupNextMenu(&OP_ServerOptionsDef); } -#ifndef NONET static void M_StartServerMenu(INT32 choice) { (void)choice; @@ -12030,7 +11976,6 @@ static void M_HandleConnectIP(INT32 choice) M_ClearMenus(true); } } -#endif //!NONET // ======================== // MULTIPLAYER PLAYER SETUP @@ -12544,7 +12489,7 @@ static void M_SetupMultiPlayer2(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; - + strcpy (setupm_name, cv_playername2.string); // set for splitscreen secondary player diff --git a/src/m_menu.h b/src/m_menu.h index c925c7f49..e91b91013 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -74,7 +74,7 @@ typedef enum MN_MP_SERVER, MN_MP_CONNECT, MN_MP_ROOM, - MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET + MN_MP_PLAYERSETUP, MN_MP_SERVER_OPTIONS, // Options diff --git a/src/mserv.c b/src/mserv.c index bff562c95..90091d241 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -45,9 +45,7 @@ static I_cond MSCond; # define Unlock_state() #endif/*HAVE_THREADS*/ -#ifndef NONET static void Command_Listserv_f(void); -#endif #endif/*MASTERSERVER*/ @@ -89,7 +87,6 @@ msg_rooms_t room_list[NUM_LIST_ROOMS+1]; // +1 for easy test */ void AddMServCommands(void) { -#ifndef NONET CV_RegisterVar(&cv_masterserver); CV_RegisterVar(&cv_masterserver_update_rate); CV_RegisterVar(&cv_masterserver_timeout); @@ -100,7 +97,6 @@ void AddMServCommands(void) COM_AddCommand("listserv", Command_Listserv_f); COM_AddCommand("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident #endif -#endif } #ifdef MASTERSERVER @@ -189,7 +185,6 @@ void GetMODVersion_Console(void) } #endif -#ifndef NONET /** Gets a list of game servers. Called from console. */ static void Command_Listserv_f(void) @@ -200,7 +195,6 @@ static void Command_Listserv_f(void) HMS_list_servers(); } } -#endif static void Finish_registration (void) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c21226ac3..ba4dd7985 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2389,9 +2389,7 @@ void I_Quit(void) SDLforceUngrabMouse(); quiting = SDL_FALSE; M_SaveConfig(NULL); //save game config, cvars.. -#ifndef NONET D_SaveBan(); // save the ban list -#endif G_SaveGameData(clientGamedata); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. @@ -2506,9 +2504,7 @@ void I_Error(const char *error, ...) // --- M_SaveConfig(NULL); // save game config, cvars.. -#ifndef NONET D_SaveBan(); // save the ban list -#endif G_SaveGameData(clientGamedata); // Tails 12-08-2002 // Shutdown. Here might be other errors. From 0b17e3c4180d5d8e6f8002c2a3cadfeaf7b25aff Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 31 Dec 2022 14:10:19 +0100 Subject: [PATCH 36/93] Move netcode files to a new folder --- src/Makefile | 1 + src/Sourcefile | 7 ---- src/android/i_net.c | 2 +- src/blua/liolib.c | 2 +- src/command.c | 4 +- src/d_main.c | 6 +-- src/deh_soc.c | 2 +- src/deh_soc.h | 2 +- src/doomstat.h | 2 +- src/dummy/i_net.c | 2 +- src/f_finale.c | 2 +- src/filesrch.c | 2 +- src/filesrch.h | 2 +- src/g_demo.c | 2 +- src/g_game.c | 2 +- src/g_input.c | 2 +- src/hardware/hw_main.c | 2 +- src/hu_stuff.c | 2 +- src/i_time.c | 2 +- src/lua_baselib.c | 4 +- src/lua_hooklib.c | 2 +- src/lua_script.c | 2 +- src/m_cheat.c | 2 +- src/m_menu.c | 6 +-- src/m_menu.h | 2 +- src/m_perfstats.c | 2 +- src/netcode/Sourcefile | 7 ++++ src/{ => netcode}/d_clisrv.c | 68 +++++++++++++++++----------------- src/{ => netcode}/d_clisrv.h | 6 +-- src/{ => netcode}/d_net.c | 16 ++++---- src/{ => netcode}/d_net.h | 0 src/{ => netcode}/d_netcmd.c | 66 ++++++++++++++++----------------- src/{ => netcode}/d_netcmd.h | 2 +- src/{ => netcode}/d_netfil.c | 30 +++++++-------- src/{ => netcode}/d_netfil.h | 2 +- src/{ => netcode}/http-mserv.c | 10 ++--- src/{ => netcode}/i_addrinfo.c | 0 src/{ => netcode}/i_addrinfo.h | 0 src/{ => netcode}/i_net.h | 4 +- src/{ => netcode}/i_tcp.c | 8 ++-- src/{ => netcode}/i_tcp.h | 0 src/{ => netcode}/mserv.c | 12 +++--- src/{ => netcode}/mserv.h | 2 +- src/p_ceilng.c | 2 +- src/p_lights.c | 2 +- src/p_user.c | 2 +- src/r_segs.c | 2 +- src/r_things.c | 2 +- src/screen.c | 2 +- src/sdl/i_net.c | 6 +-- src/sdl/i_system.c | 4 +- src/sdl/i_ttf.c | 2 +- src/w_wad.c | 4 +- src/y_inter.c | 2 +- 54 files changed, 166 insertions(+), 165 deletions(-) create mode 100644 src/netcode/Sourcefile rename src/{ => netcode}/d_clisrv.c (99%) mode change 100755 => 100644 rename src/{ => netcode}/d_clisrv.h (99%) rename src/{ => netcode}/d_net.c (99%) rename src/{ => netcode}/d_net.h (100%) rename src/{ => netcode}/d_netcmd.c (99%) rename src/{ => netcode}/d_netcmd.h (99%) rename src/{ => netcode}/d_netfil.c (99%) rename src/{ => netcode}/d_netfil.h (99%) rename src/{ => netcode}/http-mserv.c (98%) rename src/{ => netcode}/i_addrinfo.c (100%) rename src/{ => netcode}/i_addrinfo.h (100%) rename src/{ => netcode}/i_net.h (98%) rename src/{ => netcode}/i_tcp.c (99%) rename src/{ => netcode}/i_tcp.h (100%) rename src/{ => netcode}/mserv.c (98%) rename src/{ => netcode}/mserv.h (99%) diff --git a/src/Makefile b/src/Makefile index 7fe7f8990..1968e995b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -207,6 +207,7 @@ objdir:=$(makedir)/objs sources+=\ $(call List,Sourcefile)\ $(call List,blua/Sourcefile)\ + $(call List,netcode/Sourcefile)\ depends:=$(basename $(filter %.c %.s,$(sources))) objects:=$(basename $(filter %.c %.s %.nas,$(sources))) diff --git a/src/Sourcefile b/src/Sourcefile index c55752b09..004673367 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -1,9 +1,5 @@ string.c d_main.c -d_clisrv.c -d_net.c -d_netfil.c -d_netcmd.c dehacked.c deh_soc.c deh_lua.c @@ -77,9 +73,6 @@ s_sound.c sounds.c w_wad.c filesrch.c -mserv.c -http-mserv.c -i_tcp.c lzf.c vid_copy.s b_bot.c diff --git a/src/android/i_net.c b/src/android/i_net.c index f6e642022..4c30dc767 100644 --- a/src/android/i_net.c +++ b/src/android/i_net.c @@ -1,4 +1,4 @@ -#include "../i_net.h" +#include "../netcode/i_net.h" boolean I_InitNetwork(void) { diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 545f9c144..00e31e965 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -19,7 +19,7 @@ #include "lualib.h" #include "../i_system.h" #include "../g_game.h" -#include "../d_netfil.h" +#include "../netcode/d_netfil.h" #include "../lua_libs.h" #include "../byteptr.h" #include "../lua_script.h" diff --git a/src/command.c b/src/command.c index e1a43522d..0256365f3 100644 --- a/src/command.c +++ b/src/command.c @@ -28,11 +28,11 @@ #include "byteptr.h" #include "p_saveg.h" #include "g_game.h" // for player_names -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "hu_stuff.h" #include "p_setup.h" #include "lua_script.h" -#include "d_netfil.h" // findfile +#include "netcode/d_netfil.h" // findfile #include "r_data.h" // Color_cons_t #include "d_main.h" // D_IsPathAllowed diff --git a/src/d_main.c b/src/d_main.c index b7b7f6616..a4238c8b1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -34,7 +34,7 @@ #include "doomdef.h" #include "am_map.h" #include "console.h" -#include "d_net.h" +#include "netcode/d_net.h" #include "f_finale.h" #include "g_game.h" #include "hu_stuff.h" @@ -56,11 +56,11 @@ #include "w_wad.h" #include "z_zone.h" #include "d_main.h" -#include "d_netfil.h" +#include "netcode/d_netfil.h" #include "m_cheat.h" #include "y_inter.h" #include "p_local.h" // chasecam -#include "mserv.h" // ms_RoomId +#include "netcode/mserv.h" // ms_RoomId #include "m_misc.h" // screenshot functionality #include "deh_tables.h" // Dehacked list test #include "m_cond.h" // condition initialization diff --git a/src/deh_soc.c b/src/deh_soc.c index 2193cd875..59eb0a9bd 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -34,7 +34,7 @@ #include "r_sky.h" #include "fastcmp.h" #include "lua_script.h" // Reluctantly included for LUA_EvalMath -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #ifdef HWRENDER #include "hardware/hw_light.h" diff --git a/src/deh_soc.h b/src/deh_soc.h index 0cab545f6..029390133 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -35,7 +35,7 @@ #include "r_sky.h" #include "fastcmp.h" #include "lua_script.h" // Reluctantly included for LUA_EvalMath -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #ifdef HWRENDER #include "hardware/hw_light.h" diff --git a/src/doomstat.h b/src/doomstat.h index a812cc304..27889726e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -633,7 +633,7 @@ extern boolean singletics; // Netgame stuff // ============= -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" extern consvar_t cv_timetic; // display high resolution timer extern consvar_t cv_powerupdisplay; // display powerups diff --git a/src/dummy/i_net.c b/src/dummy/i_net.c index f6e642022..4c30dc767 100644 --- a/src/dummy/i_net.c +++ b/src/dummy/i_net.c @@ -1,4 +1,4 @@ -#include "../i_net.h" +#include "../netcode/i_net.h" boolean I_InitNetwork(void) { diff --git a/src/f_finale.c b/src/f_finale.c index d03795dc4..82c2a4f96 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -14,7 +14,7 @@ #include "doomdef.h" #include "doomstat.h" #include "d_main.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "f_finale.h" #include "g_game.h" #include "hu_stuff.h" diff --git a/src/filesrch.c b/src/filesrch.c index 9ee64f5ba..313f286e1 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -26,7 +26,7 @@ #include #include "filesrch.h" -#include "d_netfil.h" +#include "netcode/d_netfil.h" #include "m_misc.h" #include "z_zone.h" #include "m_menu.h" // Addons_option_Onchange diff --git a/src/filesrch.h b/src/filesrch.h index 59ef5269b..a934c48d6 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -5,7 +5,7 @@ #define __FILESRCH_H__ #include "doomdef.h" -#include "d_netfil.h" +#include "netcode/d_netfil.h" #include "m_menu.h" // MAXSTRINGLENGTH #include "w_wad.h" diff --git a/src/g_demo.c b/src/g_demo.c index adb8e891d..dea80e793 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -15,7 +15,7 @@ #include "console.h" #include "d_main.h" #include "d_player.h" -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #include "p_setup.h" #include "i_time.h" #include "i_system.h" diff --git a/src/g_game.c b/src/g_game.c index b8c434998..f47aa2183 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -15,7 +15,7 @@ #include "console.h" #include "d_main.h" #include "d_player.h" -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #include "f_finale.h" #include "p_setup.h" #include "p_saveg.h" diff --git a/src/g_input.c b/src/g_input.c index 826dcecbd..fa30c1984 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -16,7 +16,7 @@ #include "g_input.h" #include "keys.h" #include "hu_stuff.h" // need HUFONT start & end -#include "d_net.h" +#include "netcode/d_net.h" #include "console.h" #define MAXMOUSESENSITIVITY 100 // sensitivity steps diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 36ff86abd..b14a168a1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -29,7 +29,7 @@ #include "../r_patch.h" #include "../r_picformats.h" #include "../r_bsp.h" -#include "../d_clisrv.h" +#include "../netcode/d_clisrv.h" #include "../w_wad.h" #include "../z_zone.h" #include "../r_splats.h" diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c423f2905..33ef8a404 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -19,7 +19,7 @@ #include "m_cond.h" // emblems #include "m_misc.h" // word jumping -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #include "g_game.h" #include "g_input.h" diff --git a/src/i_time.c b/src/i_time.c index 2a22503f1..fae26abed 100644 --- a/src/i_time.c +++ b/src/i_time.c @@ -17,7 +17,7 @@ #include "command.h" #include "doomtype.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "m_fixed.h" #include "i_system.h" diff --git a/src/lua_baselib.c b/src/lua_baselib.c index bf3fd1dec..42e37e55e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -26,11 +26,11 @@ #include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" -#include "d_netcmd.h" // IsPlayerAdmin +#include "netcode/d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff #include "m_misc.h" // M_MapNumber #include "b_bot.h" // B_UpdateBotleader -#include "d_clisrv.h" // CL_RemovePlayer +#include "netcode/d_clisrv.h" // CL_RemovePlayer #include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision #include "lua_script.h" diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 039a9677f..0fc25ee6c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -24,7 +24,7 @@ #include "lua_hud.h" // hud_running errors #include "m_perfstats.h" -#include "d_netcmd.h" // for cv_perfstats +#include "netcode/d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetPreciseTime /* ========================================================================= diff --git a/src/lua_script.c b/src/lua_script.c index a8263ea5f..ed5adbe3f 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -28,7 +28,7 @@ #include "p_slopes.h" // for P_SlopeById and slopelist #include "p_polyobj.h" // polyobj_t, PolyObjects #ifdef LUA_ALLOW_BYTECODE -#include "d_netfil.h" // for LUA_DumpFile +#include "netcode/d_netfil.h" // for LUA_DumpFile #endif #include "lua_script.h" diff --git a/src/m_cheat.c b/src/m_cheat.c index e370335f8..69b3b643c 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -19,7 +19,7 @@ #include "r_local.h" #include "p_local.h" #include "p_setup.h" -#include "d_net.h" +#include "netcode/d_net.h" #include "m_cheat.h" #include "m_menu.h" diff --git a/src/m_menu.c b/src/m_menu.c index 3e1d30feb..72e50de69 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -20,7 +20,7 @@ #include "doomdef.h" #include "d_main.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "console.h" #include "r_fps.h" #include "r_local.h" @@ -53,8 +53,8 @@ #include "hardware/hw_main.h" #endif -#include "d_net.h" -#include "mserv.h" +#include "netcode/d_net.h" +#include "netcode/mserv.h" #include "m_misc.h" #include "m_anigif.h" #include "byteptr.h" diff --git a/src/m_menu.h b/src/m_menu.h index e91b91013..b8fe3b808 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -20,7 +20,7 @@ #include "command.h" #include "f_finale.h" // for ttmode_enum #include "i_threads.h" -#include "mserv.h" +#include "netcode/mserv.h" #include "r_things.h" // for SKINNAMESIZE // Compatibility with old-style named NiGHTS replay files. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index 17e026b3e..151185932 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -12,7 +12,7 @@ #include "m_perfstats.h" #include "v_video.h" #include "i_video.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "r_main.h" #include "i_system.h" #include "z_zone.h" diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile new file mode 100644 index 000000000..9087917d0 --- /dev/null +++ b/src/netcode/Sourcefile @@ -0,0 +1,7 @@ +d_clisrv.c +d_net.c +d_netcmd.c +d_netfil.c +http-mserv.c +i_tcp.c +mserv.c diff --git a/src/d_clisrv.c b/src/netcode/d_clisrv.c old mode 100755 new mode 100644 similarity index 99% rename from src/d_clisrv.c rename to src/netcode/d_clisrv.c index cb1ccd539..9b11e23ff --- a/src/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -15,48 +15,48 @@ #include //for unlink #endif -#include "i_time.h" +#include "../i_time.h" #include "i_net.h" -#include "i_system.h" -#include "i_video.h" +#include "../i_system.h" +#include "../i_video.h" #include "d_net.h" -#include "d_main.h" -#include "g_game.h" -#include "st_stuff.h" -#include "hu_stuff.h" -#include "keys.h" -#include "g_input.h" -#include "i_gamepad.h" -#include "m_menu.h" -#include "console.h" +#include "../d_main.h" +#include "../g_game.h" +#include "../st_stuff.h" +#include "../hu_stuff.h" +#include "../keys.h" +#include "../g_input.h" +#include "../i_gamepad.h" +#include "../m_menu.h" +#include "../console.h" #include "d_netfil.h" -#include "byteptr.h" -#include "p_saveg.h" -#include "z_zone.h" -#include "p_local.h" -#include "p_haptic.h" -#include "m_misc.h" -#include "am_map.h" -#include "m_random.h" +#include "../byteptr.h" +#include "../p_saveg.h" +#include "../z_zone.h" +#include "../p_local.h" +#include "../p_haptic.h" +#include "../m_misc.h" +#include "../am_map.h" +#include "../m_random.h" #include "mserv.h" -#include "y_inter.h" -#include "r_local.h" -#include "m_argv.h" -#include "p_setup.h" -#include "lzf.h" -#include "lua_script.h" -#include "lua_hook.h" -#include "lua_libs.h" -#include "md5.h" -#include "m_perfstats.h" +#include "../y_inter.h" +#include "../r_local.h" +#include "../m_argv.h" +#include "../p_setup.h" +#include "../lzf.h" +#include "../lua_script.h" +#include "../lua_hook.h" +#include "../lua_libs.h" +#include "../md5.h" +#include "../m_perfstats.h" // aaaaaa -#include "i_gamepad.h" +#include "../i_gamepad.h" // cl loading screen -#include "v_video.h" -#include "f_finale.h" -#include "snake.h" +#include "../v_video.h" +#include "../f_finale.h" +#include "../snake.h" // // NETWORKING diff --git a/src/d_clisrv.h b/src/netcode/d_clisrv.h similarity index 99% rename from src/d_clisrv.h rename to src/netcode/d_clisrv.h index 0d6add13a..50b86e9f0 100644 --- a/src/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -13,12 +13,12 @@ #ifndef __D_CLISRV__ #define __D_CLISRV__ -#include "d_ticcmd.h" +#include "../d_ticcmd.h" #include "d_net.h" #include "d_netcmd.h" #include "d_net.h" -#include "tables.h" -#include "d_player.h" +#include "../tables.h" +#include "../d_player.h" #include "mserv.h" /* diff --git a/src/d_net.c b/src/netcode/d_net.c similarity index 99% rename from src/d_net.c rename to src/netcode/d_net.c index 9e3759d32..ae0605001 100644 --- a/src/d_net.c +++ b/src/netcode/d_net.c @@ -16,19 +16,19 @@ /// This protocol uses a mix of "goback n" and "selective repeat" implementation /// The NOTHING packet is sent when connection is idle to acknowledge packets -#include "doomdef.h" -#include "g_game.h" -#include "i_time.h" +#include "../doomdef.h" +#include "../g_game.h" +#include "../i_time.h" #include "i_net.h" -#include "i_system.h" -#include "m_argv.h" +#include "../i_system.h" +#include "../m_argv.h" #include "d_net.h" -#include "w_wad.h" +#include "../w_wad.h" #include "d_netfil.h" #include "d_clisrv.h" -#include "z_zone.h" +#include "../z_zone.h" #include "i_tcp.h" -#include "d_main.h" // srb2home +#include "../d_main.h" // srb2home // // NETWORKING diff --git a/src/d_net.h b/src/netcode/d_net.h similarity index 100% rename from src/d_net.h rename to src/netcode/d_net.h diff --git a/src/d_netcmd.c b/src/netcode/d_netcmd.c similarity index 99% rename from src/d_netcmd.c rename to src/netcode/d_netcmd.c index 69eed90de..ed310805d 100644 --- a/src/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -12,44 +12,44 @@ /// commands are executed through the command buffer /// like console commands, other miscellaneous commands (at the end) -#include "doomdef.h" +#include "../doomdef.h" -#include "console.h" -#include "command.h" -#include "i_time.h" -#include "i_system.h" -#include "g_game.h" -#include "hu_stuff.h" -#include "g_input.h" -#include "i_gamepad.h" -#include "m_menu.h" -#include "r_local.h" -#include "r_skins.h" -#include "p_local.h" -#include "p_setup.h" -#include "s_sound.h" -#include "i_sound.h" -#include "m_misc.h" -#include "am_map.h" -#include "byteptr.h" +#include "../console.h" +#include "../command.h" +#include "../i_time.h" +#include "../i_system.h" +#include "../g_game.h" +#include "../hu_stuff.h" +#include "../g_input.h" +#include "../i_gamepad.h" +#include "../m_menu.h" +#include "../r_local.h" +#include "../r_skins.h" +#include "../p_local.h" +#include "../p_setup.h" +#include "../s_sound.h" +#include "../i_sound.h" +#include "../m_misc.h" +#include "../am_map.h" +#include "../byteptr.h" #include "d_netfil.h" -#include "p_spec.h" -#include "m_cheat.h" +#include "../p_spec.h" +#include "../m_cheat.h" #include "d_clisrv.h" #include "d_net.h" -#include "v_video.h" -#include "d_main.h" -#include "m_random.h" -#include "f_finale.h" -#include "filesrch.h" +#include "../v_video.h" +#include "../d_main.h" +#include "../m_random.h" +#include "../f_finale.h" +#include "../filesrch.h" #include "mserv.h" -#include "z_zone.h" -#include "lua_script.h" -#include "lua_hook.h" -#include "m_cond.h" -#include "m_anigif.h" -#include "md5.h" -#include "m_perfstats.h" +#include "../z_zone.h" +#include "../lua_script.h" +#include "../lua_hook.h" +#include "../m_cond.h" +#include "../m_anigif.h" +#include "../md5.h" +#include "../m_perfstats.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR diff --git a/src/d_netcmd.h b/src/netcode/d_netcmd.h similarity index 99% rename from src/d_netcmd.h rename to src/netcode/d_netcmd.h index 47f68a17e..797a686a7 100644 --- a/src/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -15,7 +15,7 @@ #ifndef __D_NETCMD__ #define __D_NETCMD__ -#include "command.h" +#include "../command.h" // console vars extern consvar_t cv_playername; diff --git a/src/d_netfil.c b/src/netcode/d_netfil.c similarity index 99% rename from src/d_netfil.c rename to src/netcode/d_netfil.c index bf3952cc9..80fa06852 100644 --- a/src/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -31,24 +31,24 @@ #include #endif -#include "doomdef.h" -#include "doomstat.h" -#include "d_main.h" -#include "g_game.h" -#include "i_time.h" +#include "../doomdef.h" +#include "../doomstat.h" +#include "../d_main.h" +#include "../g_game.h" +#include "../i_time.h" #include "i_net.h" -#include "i_system.h" -#include "m_argv.h" +#include "../i_system.h" +#include "../m_argv.h" #include "d_net.h" -#include "w_wad.h" +#include "../w_wad.h" #include "d_netfil.h" -#include "z_zone.h" -#include "byteptr.h" -#include "p_setup.h" -#include "m_misc.h" -#include "m_menu.h" -#include "md5.h" -#include "filesrch.h" +#include "../z_zone.h" +#include "../byteptr.h" +#include "../p_setup.h" +#include "../m_misc.h" +#include "../m_menu.h" +#include "../md5.h" +#include "../filesrch.h" #include diff --git a/src/d_netfil.h b/src/netcode/d_netfil.h similarity index 99% rename from src/d_netfil.h rename to src/netcode/d_netfil.h index ec53be587..732efcd5e 100644 --- a/src/d_netfil.h +++ b/src/netcode/d_netfil.h @@ -15,7 +15,7 @@ #include "d_net.h" #include "d_clisrv.h" -#include "w_wad.h" +#include "../w_wad.h" typedef enum { diff --git a/src/http-mserv.c b/src/netcode/http-mserv.c similarity index 98% rename from src/http-mserv.c rename to src/netcode/http-mserv.c index b0ef37fa1..72dc1cafb 100644 --- a/src/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -18,14 +18,14 @@ Documentation available here. #include #endif -#include "doomdef.h" +#include "../doomdef.h" #include "d_clisrv.h" -#include "command.h" -#include "m_argv.h" -#include "m_menu.h" +#include "../command.h" +#include "../m_argv.h" +#include "../m_menu.h" #include "mserv.h" #include "i_tcp.h"/* for current_port */ -#include "i_threads.h" +#include "../i_threads.h" /* reasonable default I guess?? */ #define DEFAULT_BUFFER_SIZE (4096) diff --git a/src/i_addrinfo.c b/src/netcode/i_addrinfo.c similarity index 100% rename from src/i_addrinfo.c rename to src/netcode/i_addrinfo.c diff --git a/src/i_addrinfo.h b/src/netcode/i_addrinfo.h similarity index 100% rename from src/i_addrinfo.h rename to src/netcode/i_addrinfo.h diff --git a/src/i_net.h b/src/netcode/i_net.h similarity index 98% rename from src/i_net.h rename to src/netcode/i_net.h index 62b7528d5..66126d050 100644 --- a/src/i_net.h +++ b/src/netcode/i_net.h @@ -18,8 +18,8 @@ #pragma interface #endif -#include "doomdef.h" -#include "command.h" +#include "../doomdef.h" +#include "../command.h" /// \brief program net id #define DOOMCOM_ID (INT32)0x12345678l diff --git a/src/i_tcp.c b/src/netcode/i_tcp.c similarity index 99% rename from src/i_tcp.c rename to src/netcode/i_tcp.c index ec3d1ae93..6baba6275 100644 --- a/src/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -36,7 +36,7 @@ #include #endif -#include "doomdef.h" +#include "../doomdef.h" #ifdef USE_WINSOCK1 #include @@ -122,14 +122,14 @@ typedef union #define MAXBANS 100 -#include "i_system.h" +#include "../i_system.h" #include "i_net.h" #include "d_net.h" #include "d_netfil.h" #include "i_tcp.h" -#include "m_argv.h" +#include "../m_argv.h" -#include "doomstat.h" +#include "../doomstat.h" // win32 #ifdef USE_WINSOCK diff --git a/src/i_tcp.h b/src/netcode/i_tcp.h similarity index 100% rename from src/i_tcp.h rename to src/netcode/i_tcp.h diff --git a/src/mserv.c b/src/netcode/mserv.c similarity index 98% rename from src/mserv.c rename to src/netcode/mserv.c index 90091d241..78301f4d9 100644 --- a/src/mserv.c +++ b/src/netcode/mserv.c @@ -15,13 +15,13 @@ #include #endif -#include "doomstat.h" -#include "doomdef.h" -#include "command.h" -#include "i_threads.h" +#include "../doomstat.h" +#include "../doomdef.h" +#include "../command.h" +#include "../i_threads.h" #include "mserv.h" -#include "m_menu.h" -#include "z_zone.h" +#include "../m_menu.h" +#include "../z_zone.h" #ifdef MASTERSERVER diff --git a/src/mserv.h b/src/netcode/mserv.h similarity index 99% rename from src/mserv.h rename to src/netcode/mserv.h index 23b26fbc5..7fdf3ed1b 100644 --- a/src/mserv.h +++ b/src/netcode/mserv.h @@ -14,7 +14,7 @@ #ifndef _MSERV_H_ #define _MSERV_H_ -#include "i_threads.h" +#include "../i_threads.h" // lowered from 32 due to menu changes #define NUM_LIST_ROOMS 16 diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 98e931362..61430d73f 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -17,7 +17,7 @@ #include "r_main.h" #include "s_sound.h" #include "z_zone.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" // ========================================================================== // CEILINGS diff --git a/src/p_lights.c b/src/p_lights.c index 4b6a3673b..971165e88 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -17,7 +17,7 @@ #include "r_state.h" #include "z_zone.h" #include "m_random.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" /** Removes any active lighting effects in a sector. * diff --git a/src/p_user.c b/src/p_user.c index 1c2e4f7c9..6bbefcb19 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -17,7 +17,7 @@ #include "doomdef.h" #include "i_system.h" #include "d_event.h" -#include "d_net.h" +#include "netcode/d_net.h" #include "g_game.h" #include "p_local.h" #include "r_fps.h" diff --git a/src/r_segs.c b/src/r_segs.c index facab62ab..00ee4fd6d 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -20,7 +20,7 @@ #include "w_wad.h" #include "z_zone.h" -#include "d_netcmd.h" +#include "netcode/d_netcmd.h" #include "m_misc.h" #include "p_local.h" // Camera... #include "p_slopes.h" diff --git a/src/r_things.c b/src/r_things.c index 90b80dda8..642f3a8e2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -34,7 +34,7 @@ #include "p_tick.h" #include "p_local.h" #include "p_slopes.h" -#include "d_netfil.h" // blargh. for nameonly(). +#include "netcode/d_netfil.h" // blargh. for nameonly(). #include "m_cheat.h" // objectplace #ifdef HWRENDER #include "hardware/hw_md2.h" diff --git a/src/screen.c b/src/screen.c index fe5b39995..05bbcfabb 100644 --- a/src/screen.c +++ b/src/screen.c @@ -27,7 +27,7 @@ #include "hu_stuff.h" #include "z_zone.h" #include "d_main.h" -#include "d_clisrv.h" +#include "netcode/d_clisrv.h" #include "f_finale.h" #include "y_inter.h" // usebuffer #include "i_sound.h" // closed captions diff --git a/src/sdl/i_net.c b/src/sdl/i_net.c index ee4a34c13..515a85568 100644 --- a/src/sdl/i_net.c +++ b/src/sdl/i_net.c @@ -21,16 +21,16 @@ #include "../i_system.h" #include "../d_event.h" -#include "../d_net.h" +#include "../netcode/d_net.h" #include "../m_argv.h" #include "../doomstat.h" -#include "../i_net.h" +#include "../netcode/i_net.h" #include "../z_zone.h" -#include "../i_tcp.h" +#include "../netcode/i_tcp.h" #ifdef HAVE_SDL diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ba4dd7985..50ceae34c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -193,7 +193,7 @@ static char returnWadPath[256]; #include "../i_system.h" #include "../i_threads.h" #include "../screen.h" //vid.WndParent -#include "../d_net.h" +#include "../netcode/d_net.h" #include "../g_game.h" #include "../filesrch.h" #include "endtxt.h" @@ -214,7 +214,7 @@ static char returnWadPath[256]; #if !defined(NOMUMBLE) && defined(HAVE_MUMBLE) // Mumble context string -#include "../d_clisrv.h" +#include "../netcode/d_clisrv.h" #include "../byteptr.h" #endif diff --git a/src/sdl/i_ttf.c b/src/sdl/i_ttf.c index f2cd497ee..1f838e9b4 100644 --- a/src/sdl/i_ttf.c +++ b/src/sdl/i_ttf.c @@ -21,7 +21,7 @@ #include "SDL_ttf.h" #include "../doomdef.h" #include "../doomstat.h" -#include "../d_netfil.h" +#include "../netcode/d_netfil.h" #include "../filesrch.h" #include "i_ttf.h" diff --git a/src/w_wad.c b/src/w_wad.c index 171eab4f3..23d84c336 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -51,8 +51,8 @@ #include "filesrch.h" #include "d_main.h" -#include "d_netfil.h" -#include "d_clisrv.h" +#include "netcode/d_netfil.h" +#include "netcode/d_clisrv.h" #include "dehacked.h" #include "r_defs.h" #include "r_data.h" diff --git a/src/y_inter.c b/src/y_inter.c index 1b1f49e0b..c8bd06d91 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -15,7 +15,7 @@ #include "f_finale.h" #include "g_game.h" #include "hu_stuff.h" -#include "i_net.h" +#include "netcode/i_net.h" #include "i_video.h" #include "p_tick.h" #include "r_defs.h" From e090f0e4006e329fc6faf7d66cb508fab7e6be5a Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 31 Dec 2022 21:37:35 +0100 Subject: [PATCH 37/93] Move client connection handling to a new file --- src/m_menu.c | 1 + src/netcode/Sourcefile | 1 + src/netcode/client_connection.c | 1181 ++++++++++++++++++++++++++++++ src/netcode/client_connection.h | 61 ++ src/netcode/d_clisrv.c | 1184 +------------------------------ src/netcode/d_clisrv.h | 16 +- src/netcode/http-mserv.c | 1 + src/netcode/mserv.c | 1 + 8 files changed, 1256 insertions(+), 1190 deletions(-) create mode 100644 src/netcode/client_connection.c create mode 100644 src/netcode/client_connection.h diff --git a/src/m_menu.c b/src/m_menu.c index 72e50de69..f0691c17f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -55,6 +55,7 @@ #include "netcode/d_net.h" #include "netcode/mserv.h" +#include "netcode/client_connection.h" #include "m_misc.h" #include "m_anigif.h" #include "byteptr.h" diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile index 9087917d0..c11b3d6c1 100644 --- a/src/netcode/Sourcefile +++ b/src/netcode/Sourcefile @@ -1,4 +1,5 @@ d_clisrv.c +client_connection.c d_net.c d_netcmd.c d_netfil.c diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c new file mode 100644 index 000000000..bfaea2e81 --- /dev/null +++ b/src/netcode/client_connection.c @@ -0,0 +1,1181 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file client_connection.h +/// \brief Client connection handling + +#include "client_connection.h" +#include "d_clisrv.h" +#include "d_netfil.h" +#include "../d_main.h" +#include "../f_finale.h" +#include "../g_game.h" +#include "../i_gamepad.h" +#include "i_net.h" +#include "../i_system.h" +#include "../i_time.h" +#include "../i_video.h" +#include "../m_menu.h" +#include "../m_misc.h" +#include "../snake.h" +#include "../s_sound.h" +#include "../v_video.h" +#include "../y_inter.h" +#include "../z_zone.h" +#include "../doomtype.h" +#include "../doomstat.h" + +cl_mode_t cl_mode = CL_SEARCHING; +static UINT16 cl_lastcheckedfilecount = 0; // used for full file list +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; +UINT8 mynode; // my address pointofview server +static void *snake = NULL; + +static void CL_DrawConnectionStatusBox(void) +{ + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); + if (cl_mode != CL_CONFIRMCONNECT) + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); +} + +// +// CL_DrawConnectionStatus +// +// Keep the local client informed of our status. +// +static inline void CL_DrawConnectionStatus(void) +{ + INT32 ccstime = I_GetTime(); + + // Draw background fade + V_DrawFadeScreen(0xFF00, 16); // force default + + if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES) + { + INT32 i, animtime = ((ccstime / 4) & 15) + 16; + UINT8 palstart; + const char *cltext; + + // Draw the bottom box. + CL_DrawConnectionStatusBox(); + + if (cl_mode == CL_SEARCHING) + palstart = 32; // Red + else if (cl_mode == CL_CONFIRMCONNECT) + palstart = 48; // Orange + else + palstart = 96; // Green + + if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) + for (i = 0; i < 16; ++i) // 15 pal entries total. + V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); + + switch (cl_mode) + { + case CL_DOWNLOADSAVEGAME: + if (fileneeded && lastfilenum != -1) + { + UINT32 currentsize = fileneeded[lastfilenum].currentsize; + UINT32 totalsize = fileneeded[lastfilenum].totalsize; + INT32 dldlength; + + cltext = M_GetText("Downloading game state..."); + Net_GetNetStat(); + + dldlength = (INT32)((currentsize/(double)totalsize) * 256); + if (dldlength > 256) + dldlength = 256; + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); + + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",currentsize>>10,totalsize>>10)); + + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + cltext = M_GetText("Waiting to download game state..."); + break; + 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: + if (serverisfull) + cltext = M_GetText("Server full, waiting for a slot..."); + else + cltext = M_GetText("Requesting to join..."); + break; + default: + cltext = M_GetText("Connecting to server..."); + break; + } + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, cltext); + } + else + { + if (cl_mode == CL_LOADFILES) + { + INT32 totalfileslength; + INT32 loadcompletednum = 0; + INT32 i; + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); + + //ima just count files here + if (fileneeded) + { + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_OPEN) + loadcompletednum++; + } + + // Loading progress + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, "Loading server addons..."); + totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256); + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %2u/%2u Files",loadcompletednum,fileneedednum)); + } + else if (lastfilenum != -1) + { + INT32 dldlength; + static char tempname[28]; + fileneeded_t *file; + char *filename; + + if (snake) + Snake_Draw(snake); + + // Draw the bottom box. + CL_DrawConnectionStatusBox(); + + if (fileneeded) + { + file = &fileneeded[lastfilenum]; + filename = file->filename; + } + else + return; + + Net_GetNetStat(); + dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); + if (dldlength > 256) + dldlength = 256; + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); + + memset(tempname, 0, sizeof(tempname)); + // offset filename to just the name only part + filename += strlen(filename) - nameonlylength(filename); + + if (strlen(filename) > sizeof(tempname)-1) // too long to display fully + { + size_t endhalfpos = strlen(filename)-10; + // display as first 14 chars + ... + last 10 chars + // which should add up to 27 if our math(s) is correct + snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos); + } + else // we can copy the whole thing in safely + { + strncpy(tempname, filename, sizeof(tempname)-1); + } + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, + va(M_GetText("Downloading \"%s\""), tempname)); + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + { + if (snake) + Snake_Draw(snake); + + CL_DrawConnectionStatusBox(); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, + M_GetText("Waiting to download files...")); + } + } +} + +static boolean CL_AskFileList(INT32 firstfile) +{ + netbuffer->packettype = PT_TELLFILESNEEDED; + netbuffer->u.filesneedednum = firstfile; + + return HSendPacket(servernode, false, 0, sizeof (INT32)); +} + +/** Sends a special packet to declare how many players in local + * Used only in arbitratrenetstart() + * Sends a PT_CLIENTJOIN packet to the server + * + * \return True if the packet was successfully sent + * \todo Improve the description... + * + */ +boolean CL_SendJoin(void) +{ + UINT8 localplayers = 1; + if (netgame) + CONS_Printf(M_GetText("Sending join request...\n")); + netbuffer->packettype = PT_CLIENTJOIN; + + netbuffer->u.clientcfg.modversion = MODVERSION; + strncpy(netbuffer->u.clientcfg.application, + SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); + + if (splitscreen || botingame) + localplayers++; + netbuffer->u.clientcfg.localplayers = localplayers; + + CleanupPlayerName(consoleplayer, cv_playername.zstring); + if (splitscreen) + CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ + + strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); + + return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); +} + +static void SendAskInfo(INT32 node) +{ + const tic_t asktime = I_GetTime(); + netbuffer->packettype = PT_ASKINFO; + netbuffer->u.askinfo.version = VERSION; + netbuffer->u.askinfo.time = (tic_t)LONG(asktime); + + // Even if this never arrives due to the host being firewalled, we've + // now allowed traffic from the host to us in, so once the MS relays + // our address to the host, it'll be able to speak to us. + HSendPacket(node, false, 0, sizeof (askinfo_pak)); +} + +serverelem_t serverlist[MAXSERVERLIST]; +UINT32 serverlistcount = 0; + +#define FORCECLOSE 0x8000 + +static void SL_ClearServerList(INT32 connectedserver) +{ + UINT32 i; + + for (i = 0; i < serverlistcount; i++) + if (connectedserver != serverlist[i].node) + { + Net_CloseConnection(serverlist[i].node|FORCECLOSE); + serverlist[i].node = 0; + } + serverlistcount = 0; +} + +static UINT32 SL_SearchServer(INT32 node) +{ + UINT32 i; + for (i = 0; i < serverlistcount; i++) + if (serverlist[i].node == node) + return i; + + return UINT32_MAX; +} + +static void SL_InsertServer(serverinfo_pak* info, SINT8 node) +{ + UINT32 i; + + // search if not already on it + i = SL_SearchServer(node); + if (i == UINT32_MAX) + { + // not found add it + if (serverlistcount >= MAXSERVERLIST) + return; // list full + + /* check it later if connecting to this one */ + if (node != servernode) + { + if (info->_255 != 255) + return;/* old packet format */ + + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ + + if (info->version != VERSION) + return; // Not same version. + + if (info->subversion != SUBVERSION) + return; // Close, but no cigar. + + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + } + + i = serverlistcount++; + } + + serverlist[i].info = *info; + serverlist[i].node = node; + + // resort server list + M_SortServerList(); +} + +#if defined (MASTERSERVER) && defined (HAVE_THREADS) +struct Fetch_servers_ctx +{ + int room; + int id; +}; + +static void +Fetch_servers_thread (struct Fetch_servers_ctx *ctx) +{ + msg_server_t *server_list; + + server_list = GetShortServersList(ctx->room, ctx->id); + + if (server_list) + { + I_lock_mutex(&ms_QueryId_mutex); + { + if (ctx->id != ms_QueryId) + { + free(server_list); + server_list = NULL; + } + } + I_unlock_mutex(ms_QueryId_mutex); + + if (server_list) + { + I_lock_mutex(&m_menu_mutex); + { + if (m_waiting_mode == M_WAITING_SERVERS) + m_waiting_mode = M_NOT_WAITING; + } + I_unlock_mutex(m_menu_mutex); + + I_lock_mutex(&ms_ServerList_mutex); + { + ms_ServerList = server_list; + } + I_unlock_mutex(ms_ServerList_mutex); + } + } + + free(ctx); +} +#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ + +void CL_QueryServerList (msg_server_t *server_list) +{ + INT32 i; + + for (i = 0; server_list[i].header.buffer[0]; i++) + { + // Make sure MS version matches our own, to + // thwart nefarious servers who lie to the MS. + + /* lol bruh, that version COMES from the servers */ + //if (strcmp(version, server_list[i].version) == 0) + { + INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); + if (node == -1) + break; // no more node free + SendAskInfo(node); + // Force close the connection so that servers can't eat + // up nodes forever if we never get a reply back from them + // (usually when they've not forwarded their ports). + // + // Don't worry, we'll get in contact with the working + // servers again when they send SERVERINFO to us later! + // + // (Note: as a side effect this probably means every + // server in the list will probably be using the same node (e.g. node 1), + // not that it matters which nodes they use when + // the connections are closed afterwards anyway) + // -- Monster Iestyn 12/11/18 + Net_CloseConnection(node|FORCECLOSE); + } + } +} + +void CL_UpdateServerList(boolean internetsearch, INT32 room) +{ + (void)internetsearch; + (void)room; + + SL_ClearServerList(0); + + if (!netgame && I_NetOpenSocket) + { + if (I_NetOpenSocket()) + { + netgame = true; + multiplayer = true; + } + } + + // search for local servers + 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 */ + m_waiting_mode = M_WAITING_SERVERS; + + I_lock_mutex(&ms_QueryId_mutex); + { + ctx->id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + ctx->room = room; + + I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); +#else + msg_server_t *server_list; + + server_list = GetShortServersList(room, 0); + + if (server_list) + { + CL_QueryServerList(server_list); + free(server_list); + } +#endif + } +#endif/*MASTERSERVER*/ +} + +static void M_ConfirmConnect(event_t *ev) +{ + if (ev->type == ev_keydown || ev->type == ev_gamepad_down) + { + if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A)) + { + if (totalfilesrequestednum > 0) + { + if (CL_SendFileRequest()) + { + cl_mode = CL_DOWNLOADFILES; + Snake_Allocate(&snake); + } + } + else + cl_mode = CL_LOADFILES; + + M_ClearMenus(true); + } + else if ((ev->type == ev_keydown && (ev->key == 'n' || ev->key == KEY_ESCAPE)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_B)) + { + cl_mode = CL_ABORTED; + M_ClearMenus(true); + } + } +} + +static boolean CL_FinishedFileList(void) +{ + INT32 i; + char *downloadsize = NULL; + + //CONS_Printf(M_GetText("Checking files...\n")); + i = CL_CheckFiles(); + if (i == 4) // still checking ... + { + return true; + } + else if (i == 3) // too many files + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have too many WAD files loaded\n" + "to add ones the server is using.\n" + "Please restart SRB2 before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 2) // cannot join for some reason + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have the wrong addons loaded.\n\n" + "To play on this server, restart\n" + "the game and don't load any addons.\n" + "SRB2 will automatically add\n" + "everything you need when you join.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 1) + { + 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 ENTER to continue\nor ESC to cancel.\n\n" + ), M_ConfirmConnect, MM_EVENTHANDLER); + cl_mode = CL_CONFIRMCONNECT; + curfadevalue = 0; + } + else + cl_mode = CL_LOADFILES; + } + else + { + // must download something + // can we, though? + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "An error occured when trying to\n" + "download missing addons.\n" + "(This is almost always a problem\n" + "with the server, not your game.)\n\n" + "See the console or log file\n" + "for additional details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + + downloadcompletednum = 0; + downloadcompletedsize = 0; + totalfilesrequestednum = 0; + totalfilesrequestedsize = 0; + + if (fileneeded == NULL) + I_Error("CL_FinishedFileList: fileneeded == NULL"); + + 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\nis required to join.\n" + "\n" + "You may download, load server addons,\nand wait for a slot.\n" + "\n" + "Press ENTER to continue\nor ESC to cancel.\n" + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); + else + M_StartMessage(va(M_GetText( + "Download of %s additional content\nis required to join.\n" + "\n" + "Press ENTER to continue\nor ESC to cancel.\n" + ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); + + Z_Free(downloadsize); + cl_mode = CL_CONFIRMCONNECT; + curfadevalue = 0; + } + return true; +} + +static const char * InvalidServerReason (serverinfo_pak *info) +{ +#define EOT "\nPress ESC\n" + + /* magic number for new packet format */ + if (info->_255 != 255) + { + return + "Outdated server (version unknown).\n" EOT; + } + + if (strncmp(info->application, SRB2APPLICATION, sizeof + info->application)) + { + return va( + "%s cannot connect\n" + "to %s servers.\n" EOT, + SRB2APPLICATION, + info->application); + } + + if ( + info->packetversion != PACKETVERSION || + info->version != VERSION || + info->subversion != SUBVERSION + ){ + return va( + "Incompatible %s versions.\n" + "(server version %d.%d.%d)\n" EOT, + SRB2APPLICATION, + info->version / 100, + info->version % 100, + info->subversion); + } + + switch (info->refusereason) + { + case REFUSE_BANNED: + return + "You have been banned\n" + "from the server.\n" EOT; + case REFUSE_JOINS_DISABLED: + return + "The server is not accepting\n" + "joins for the moment.\n" EOT; + case REFUSE_SLOTS_FULL: + return va( + "Maximum players reached: %d\n" EOT, + info->maxplayer); + default: + if (info->refusereason) + { + return + "You can't join.\n" + "I don't know why,\n" + "but you can't join.\n" EOT; + } + } + + return NULL; + +#undef EOT +} + +/** Called by CL_ServerConnectionTicker + * + * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. + * \return False if the connection was aborted + * \sa CL_ServerConnectionTicker + * \sa CL_ConnectToServer + * + */ +static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) +{ + INT32 i; + + // serverlist is updated by GetPacket function + if (serverlistcount > 0) + { + // this can be a responce to our broadcast request + if (servernode == -1 || servernode >= MAXNETNODES) + { + i = 0; + servernode = serverlist[i].node; + CONS_Printf(M_GetText("Found, ")); + } + else + { + i = SL_SearchServer(servernode); + if (i < 0) + return true; + } + + if (client) + { + serverinfo_pak *info = &serverlist[i].info; + + if (info->refusereason == REFUSE_SLOTS_FULL) + serverisfull = true; + else + { + const char *reason = InvalidServerReason(info); + + // Quit here rather than downloading files + // and being refused later. + if (reason) + { + char *message = Z_StrDup(reason); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(message, NULL, MM_NOTHING); + Z_Free(message); + return false; + } + } + + D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0); + + if (info->flags & 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. + *asksent = 0; + } + + return true; + } + + // Ask the info to the server (askinfo packet) + if (*asksent + NEWTICRATE < I_GetTime()) + { + SendAskInfo(servernode); + *asksent = I_GetTime(); + } + + return true; +} + +/** Called by CL_ConnectToServer + * + * \param tmpsave The name of the gamestate file??? + * \param oldtic Used for knowing when to poll events and redraw + * \param asksent ??? + * \return False if the connection was aborted + * \sa CL_ServerConnectionSearchTicker + * \sa CL_ConnectToServer + * + */ +static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic_t *asksent) +{ + boolean waitmore; + INT32 i; + + switch (cl_mode) + { + case CL_SEARCHING: + if (!CL_ServerConnectionSearchTicker(asksent)) + return false; + break; + + case CL_ASKFULLFILELIST: + if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved + cl_mode = CL_CHECKFILES; + else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent) + { + if (CL_AskFileList(fileneedednum)) + { + cl_lastcheckedfilecount = fileneedednum; + *asksent = I_GetTime() + NEWTICRATE; + } + } + break; + case CL_CHECKFILES: + if (!CL_FinishedFileList()) + return false; + break; + case CL_DOWNLOADFILES: + waitmore = false; + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_DOWNLOADING + || fileneeded[i].status == FS_REQUESTED) + { + waitmore = true; + break; + } + if (waitmore) + break; // exit the case + + Snake_Free(&snake); + + cl_mode = CL_LOADFILES; + break; + case CL_LOADFILES: + if (CL_LoadServerFiles()) + { + FreeFileNeeded(); + *asksent = 0; //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() && !server) + { + 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); + return false; + } + + // 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); + + if (I_GetTime() >= *asksent && CL_SendJoin()) + { + *asksent = I_GetTime() + NEWTICRATE*3; + cl_mode = CL_WAITJOINRESPONSE; + } + break; + case CL_WAITJOINRESPONSE: + if (I_GetTime() >= *asksent) + { + cl_mode = CL_ASKJOIN; + } + break; + case CL_DOWNLOADSAVEGAME: + // At this state, the first (and only) needed file is the gamestate + if (fileneeded[0].status == FS_FOUND) + { + // Gamestate is now handled within CL_LoadReceivedSavegame() + CL_LoadReceivedSavegame(false); + cl_mode = CL_CONNECTED; + } // don't break case continue to CL_CONNECTED + else + break; + + case CL_CONNECTED: + case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect + default: + break; + + // Connection closed by cancel, timeout or refusal. + case CL_ABORTED: + cl_mode = CL_SEARCHING; + return false; + } + + GetPackets(); + Net_AckTicker(); + + // Call it only once by tic + if (*oldtic != I_GetTime()) + { + I_OsPolling(); + + if (cl_mode == CL_CONFIRMCONNECT) + D_ProcessEvents(); //needed for menu system to receive inputs + else + { + // my hand has been forced and I am dearly sorry for this awful hack :vomit: + for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) + { + G_MapEventsToControls(&events[eventtail]); + } + } + + if (gamekeydown[KEY_ESCAPE] || gamepads[0].buttons[GAMEPAD_BUTTON_B] || cl_mode == CL_ABORTED) + { + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); + M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); + + Snake_Free(&snake); + + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + memset(gamekeydown, 0, NUMKEYS); + return false; + } + else if (cl_mode == CL_DOWNLOADFILES && snake) + Snake_Update(snake); + + if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) + FileReceiveTicker(); + + // why are these here? this is for servers, we're a client + //if (key == 's' && server) + // doomcom->numnodes = (INT16)pnumnodes; + //FileSendTicker(); + *oldtic = I_GetTime(); + + if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) + { + if (!snake) + { + F_MenuPresTicker(true); // title sky + 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(); + S_UpdateSounds(); + S_UpdateClosedCaptions(); + } + } + else + { + I_Sleep(cv_sleep.value); + I_UpdateTime(cv_timescale.value); + } + + return true; +} + +#define TMPSAVENAME "$$$.sav" + +/** Use adaptive send using net_bandwidth and stat.sendbytes + * + * \todo Better description... + * + */ +void CL_ConnectToServer(void) +{ + INT32 pnumnodes, nodewaited = doomcom->numnodes, i; + tic_t oldtic; + tic_t asksent; + char tmpsave[256]; + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + lastfilenum = -1; + + cl_mode = CL_SEARCHING; + + // Don't get a corrupt savegame error because tmpsave already exists + if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) + I_Error("Can't delete %s\n", tmpsave); + + if (netgame) + { + if (servernode < 0 || servernode >= MAXNETNODES) + CONS_Printf(M_GetText("Searching for a server...\n")); + else + CONS_Printf(M_GetText("Contacting the server...\n")); + } + + if (gamestate == GS_INTERMISSION) + Y_EndIntermission(); // clean up intermission graphics etc + + DEBFILE(va("waiting %d nodes\n", doomcom->numnodes)); + G_SetGamestate(GS_WAITINGPLAYERS); + wipegamestate = GS_WAITINGPLAYERS; + + ClearAdminPlayers(); + pnumnodes = 1; + oldtic = I_GetTime() - 1; + + asksent = (tic_t) - TICRATE; + firstconnectattempttime = I_GetTime(); + + i = SL_SearchServer(servernode); + + if (i != -1) + { + char *gametypestr = serverlist[i].info.gametypename; + CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); + gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; + CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); + CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, + serverlist[i].info.version%100, serverlist[i].info.subversion); + } + SL_ClearServerList(servernode); + + do + { + // If the connection was aborted for some reason, leave + if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) + return; + + if (server) + { + pnumnodes = 0; + for (i = 0; i < MAXNETNODES; i++) + if (netnodes[i].ingame) + pnumnodes++; + } + } + while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); + + DEBFILE(va("Synchronisation Finished\n")); + + displayplayer = consoleplayer; +} + +/** Called when a PT_SERVERINFO packet is received + * + * \param node The packet sender + * \note What happens if the packet comes from a client or something like that? + * + */ +void HandleServerInfo(SINT8 node) +{ + // compute ping in ms + const tic_t ticnow = I_GetTime(); + const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time); + const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; + netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); + netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; + netbuffer->u.serverinfo.application + [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; + netbuffer->u.serverinfo.gametypename + [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; + + SL_InsertServer(&netbuffer->u.serverinfo, node); +} + +// Helper function for packets that should only be sent by the server +// If it is NOT from the server, bail out and close the connection! +static boolean ServerOnly(SINT8 node) +{ + if (node == servernode) + return false; + + Net_CloseConnection(node); + return true; +} + +void PT_MoreFilesNeeded(SINT8 node) +{ + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) + { + D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); + if (!netbuffer->u.filesneededcfg.more) + cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list + } +} + +// Negative response of client join request +void PT_ServerRefuse(SINT8 node) +{ + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + if (cl_mode == CL_WAITJOINRESPONSE) + { + // Save the reason so it can be displayed after quitting the netgame + char *reason = strdup(netbuffer->u.serverrefuse.reason); + if (!reason) + I_Error("Out of memory!\n"); + + 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); + return; + } + + 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. + cl_mode = CL_ABORTED; + } +} + +// Positive response of client join request +void PT_ServerCFG(SINT8 node) +{ + if (server && serverrunning && node != servernode) + { // but wait I thought I'm the server? + Net_CloseConnection(node); + return; + } + if (ServerOnly(node)) + return; + /// \note how would this happen? and is it doing the right thing if it does? + if (cl_mode != CL_WAITJOINRESPONSE) + return; + + if (client) + { + maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); + G_SetGametype(netbuffer->u.servercfg.gametype); + modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + } + + netnodes[(UINT8)servernode].ingame = true; + serverplayer = netbuffer->u.servercfg.serverplayer; + doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); + mynode = netbuffer->u.servercfg.clientnode; + if (serverplayer >= 0) + playernode[(UINT8)serverplayer] = servernode; + + if (netgame) + CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); + DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); + + /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? + /// Shouldn't them be downloaded even at intermission time? + /// Also, according to HandleConnect, the server will send the savegame even during intermission... + if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || + netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) + cl_mode = CL_DOWNLOADSAVEGAME; + else + cl_mode = CL_CONNECTED; +} diff --git a/src/netcode/client_connection.h b/src/netcode/client_connection.h new file mode 100644 index 000000000..a76411ba6 --- /dev/null +++ b/src/netcode/client_connection.h @@ -0,0 +1,61 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file client_connection.h +/// \brief Client connection handling + +#ifndef __D_CLIENT_CONNECTION__ +#define __D_CLIENT_CONNECTION__ + +#include "../doomtype.h" +#include "d_clisrv.h" + +#define MAXSERVERLIST (MAXNETNODES-1) + +typedef struct +{ + SINT8 node; + serverinfo_pak info; +} serverelem_t; + +typedef enum +{ + CL_SEARCHING, + CL_CHECKFILES, + CL_DOWNLOADFILES, + CL_ASKJOIN, + CL_LOADFILES, + CL_WAITJOINRESPONSE, + CL_DOWNLOADSAVEGAME, + CL_CONNECTED, + CL_ABORTED, + CL_ASKFULLFILELIST, + CL_CONFIRMCONNECT +} cl_mode_t; + +extern serverelem_t serverlist[MAXSERVERLIST]; +extern UINT32 serverlistcount; + +extern cl_mode_t cl_mode; +extern boolean serverisfull; //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 +extern tic_t firstconnectattempttime; +extern UINT8 mynode; // my address pointofview server + +void CL_QueryServerList(msg_server_t *list); +void CL_UpdateServerList(boolean internetsearch, INT32 room); + +void CL_ConnectToServer(void); +boolean CL_SendJoin(void); + +void HandleServerInfo(SINT8 node); +void PT_MoreFilesNeeded(SINT8 node); +void PT_ServerRefuse(SINT8 node); +void PT_ServerCFG(SINT8 node); + +#endif diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 9b11e23ff..f7a9260e1 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -49,14 +49,7 @@ #include "../lua_libs.h" #include "../md5.h" #include "../m_perfstats.h" - -// aaaaaa -#include "../i_gamepad.h" - -// cl loading screen -#include "../v_video.h" -#include "../f_finale.h" -#include "../snake.h" +#include "client_connection.h" // // NETWORKING @@ -103,7 +96,7 @@ tic_t servermaxping = 800; // server's max ping. Defaults to 800 static tic_t firstticstosend; // min of the nettics static tic_t tictoclear = 0; // optimize d_clearticcmd -static tic_t maketic; +tic_t maketic; static INT16 consistancy[BACKUPTICS]; @@ -121,21 +114,17 @@ static ticcmd_t localcmds; static ticcmd_t localcmds2; static boolean cl_packetmissed; // here it is for the secondary local player (splitscreen) -static UINT8 mynode; // my address pointofview server static boolean cl_redownloadinggamestate = false; static UINT8 localtextcmd[MAXTEXTCMD]; static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen -static tic_t neededtic; +tic_t neededtic; SINT8 servernode = 0; // the number of the server node /// \brief do we accept new players? /// \todo WORK! boolean acceptnewnode = true; -static 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 -static tic_t firstconnectattempttime = 0; - // engine // Must be a power of two @@ -512,250 +501,6 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) static INT16 Consistancy(void); -typedef enum -{ - CL_SEARCHING, - CL_CHECKFILES, - CL_DOWNLOADFILES, - CL_ASKJOIN, - CL_LOADFILES, - CL_WAITJOINRESPONSE, - CL_DOWNLOADSAVEGAME, - CL_CONNECTED, - CL_ABORTED, - CL_ASKFULLFILELIST, - CL_CONFIRMCONNECT -} cl_mode_t; - -static void GetPackets(void); - -static cl_mode_t cl_mode = CL_SEARCHING; - -static UINT16 cl_lastcheckedfilecount = 0; // used for full file list - -static void *snake = NULL; - -static void CL_DrawConnectionStatusBox(void) -{ - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); - if (cl_mode != CL_CONFIRMCONNECT) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); -} - -// -// CL_DrawConnectionStatus -// -// Keep the local client informed of our status. -// -static inline void CL_DrawConnectionStatus(void) -{ - INT32 ccstime = I_GetTime(); - - // Draw background fade - V_DrawFadeScreen(0xFF00, 16); // force default - - if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES) - { - INT32 i, animtime = ((ccstime / 4) & 15) + 16; - UINT8 palstart; - const char *cltext; - - // Draw the bottom box. - CL_DrawConnectionStatusBox(); - - if (cl_mode == CL_SEARCHING) - palstart = 32; // Red - else if (cl_mode == CL_CONFIRMCONNECT) - palstart = 48; // Orange - else - palstart = 96; // Green - - if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) - for (i = 0; i < 16; ++i) // 15 pal entries total. - V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); - - switch (cl_mode) - { - case CL_DOWNLOADSAVEGAME: - if (fileneeded && lastfilenum != -1) - { - UINT32 currentsize = fileneeded[lastfilenum].currentsize; - UINT32 totalsize = fileneeded[lastfilenum].totalsize; - INT32 dldlength; - - cltext = M_GetText("Downloading game state..."); - Net_GetNetStat(); - - dldlength = (INT32)((currentsize/(double)totalsize) * 256); - if (dldlength > 256) - dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); - - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",currentsize>>10,totalsize>>10)); - - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); - } - else - cltext = M_GetText("Waiting to download game state..."); - break; - 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: - if (serverisfull) - cltext = M_GetText("Server full, waiting for a slot..."); - else - cltext = M_GetText("Requesting to join..."); - break; - default: - cltext = M_GetText("Connecting to server..."); - break; - } - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, cltext); - } - else - { - if (cl_mode == CL_LOADFILES) - { - INT32 totalfileslength; - INT32 loadcompletednum = 0; - INT32 i; - - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); - - //ima just count files here - if (fileneeded) - { - for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status == FS_OPEN) - loadcompletednum++; - } - - // Loading progress - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, "Loading server addons..."); - totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256); - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va(" %2u/%2u Files",loadcompletednum,fileneedednum)); - } - else if (lastfilenum != -1) - { - INT32 dldlength; - static char tempname[28]; - fileneeded_t *file; - char *filename; - - if (snake) - Snake_Draw(snake); - - // Draw the bottom box. - CL_DrawConnectionStatusBox(); - - if (fileneeded) - { - file = &fileneeded[lastfilenum]; - filename = file->filename; - } - else - return; - - Net_GetNetStat(); - dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); - if (dldlength > 256) - dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); - - memset(tempname, 0, sizeof(tempname)); - // offset filename to just the name only part - filename += strlen(filename) - nameonlylength(filename); - - if (strlen(filename) > sizeof(tempname)-1) // too long to display fully - { - size_t endhalfpos = strlen(filename)-10; - // display as first 14 chars + ... + last 10 chars - // which should add up to 27 if our math(s) is correct - snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos); - } - else // we can copy the whole thing in safely - { - strncpy(tempname, filename, sizeof(tempname)-1); - } - - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, - va(M_GetText("Downloading \"%s\""), tempname)); - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); - } - else - { - if (snake) - Snake_Draw(snake); - - CL_DrawConnectionStatusBox(); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, - M_GetText("Waiting to download files...")); - } - } -} - -static boolean CL_AskFileList(INT32 firstfile) -{ - netbuffer->packettype = PT_TELLFILESNEEDED; - netbuffer->u.filesneedednum = firstfile; - - return HSendPacket(servernode, false, 0, sizeof (INT32)); -} - -/** Sends a special packet to declare how many players in local - * Used only in arbitratrenetstart() - * Sends a PT_CLIENTJOIN packet to the server - * - * \return True if the packet was successfully sent - * \todo Improve the description... - * - */ -static boolean CL_SendJoin(void) -{ - UINT8 localplayers = 1; - if (netgame) - CONS_Printf(M_GetText("Sending join request...\n")); - netbuffer->packettype = PT_CLIENTJOIN; - - netbuffer->u.clientcfg.modversion = MODVERSION; - strncpy(netbuffer->u.clientcfg.application, - SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application); - - if (splitscreen || botingame) - localplayers++; - netbuffer->u.clientcfg.localplayers = localplayers; - - CleanupPlayerName(consoleplayer, cv_playername.zstring); - if (splitscreen) - CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ - - strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); - strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); - - return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); -} - static INT32 FindRejoinerNum(SINT8 node) { char strippednodeaddress[64]; @@ -1105,7 +850,7 @@ static void SV_SavedGame(void) #define TMPSAVENAME "$$$.sav" -static void CL_LoadReceivedSavegame(boolean reloading) +void CL_LoadReceivedSavegame(boolean reloading) { UINT8 *savebuffer = NULL; size_t length, decompressedlen; @@ -1206,790 +951,6 @@ static void CL_ReloadReceivedSavegame(void) CONS_Printf(M_GetText("Game state reloaded\n")); } -static void SendAskInfo(INT32 node) -{ - const tic_t asktime = I_GetTime(); - netbuffer->packettype = PT_ASKINFO; - netbuffer->u.askinfo.version = VERSION; - netbuffer->u.askinfo.time = (tic_t)LONG(asktime); - - // Even if this never arrives due to the host being firewalled, we've - // now allowed traffic from the host to us in, so once the MS relays - // our address to the host, it'll be able to speak to us. - HSendPacket(node, false, 0, sizeof (askinfo_pak)); -} - -serverelem_t serverlist[MAXSERVERLIST]; -UINT32 serverlistcount = 0; - -#define FORCECLOSE 0x8000 - -static void SL_ClearServerList(INT32 connectedserver) -{ - UINT32 i; - - for (i = 0; i < serverlistcount; i++) - if (connectedserver != serverlist[i].node) - { - Net_CloseConnection(serverlist[i].node|FORCECLOSE); - serverlist[i].node = 0; - } - serverlistcount = 0; -} - -static UINT32 SL_SearchServer(INT32 node) -{ - UINT32 i; - for (i = 0; i < serverlistcount; i++) - if (serverlist[i].node == node) - return i; - - return UINT32_MAX; -} - -static void SL_InsertServer(serverinfo_pak* info, SINT8 node) -{ - UINT32 i; - - // search if not already on it - i = SL_SearchServer(node); - if (i == UINT32_MAX) - { - // not found add it - if (serverlistcount >= MAXSERVERLIST) - return; // list full - - /* check it later if connecting to this one */ - if (node != servernode) - { - if (info->_255 != 255) - return;/* old packet format */ - - if (info->packetversion != PACKETVERSION) - return;/* old new packet format */ - - if (info->version != VERSION) - return; // Not same version. - - if (info->subversion != SUBVERSION) - return; // Close, but no cigar. - - if (strcmp(info->application, SRB2APPLICATION)) - return;/* that's a different mod */ - } - - i = serverlistcount++; - } - - serverlist[i].info = *info; - serverlist[i].node = node; - - // resort server list - M_SortServerList(); -} - -#if defined (MASTERSERVER) && defined (HAVE_THREADS) -struct Fetch_servers_ctx -{ - int room; - int id; -}; - -static void -Fetch_servers_thread (struct Fetch_servers_ctx *ctx) -{ - msg_server_t *server_list; - - server_list = GetShortServersList(ctx->room, ctx->id); - - if (server_list) - { - I_lock_mutex(&ms_QueryId_mutex); - { - if (ctx->id != ms_QueryId) - { - free(server_list); - server_list = NULL; - } - } - I_unlock_mutex(ms_QueryId_mutex); - - if (server_list) - { - I_lock_mutex(&m_menu_mutex); - { - if (m_waiting_mode == M_WAITING_SERVERS) - m_waiting_mode = M_NOT_WAITING; - } - I_unlock_mutex(m_menu_mutex); - - I_lock_mutex(&ms_ServerList_mutex); - { - ms_ServerList = server_list; - } - I_unlock_mutex(ms_ServerList_mutex); - } - } - - free(ctx); -} -#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ - -void CL_QueryServerList (msg_server_t *server_list) -{ - INT32 i; - - for (i = 0; server_list[i].header.buffer[0]; i++) - { - // Make sure MS version matches our own, to - // thwart nefarious servers who lie to the MS. - - /* lol bruh, that version COMES from the servers */ - //if (strcmp(version, server_list[i].version) == 0) - { - INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); - if (node == -1) - break; // no more node free - SendAskInfo(node); - // Force close the connection so that servers can't eat - // up nodes forever if we never get a reply back from them - // (usually when they've not forwarded their ports). - // - // Don't worry, we'll get in contact with the working - // servers again when they send SERVERINFO to us later! - // - // (Note: as a side effect this probably means every - // server in the list will probably be using the same node (e.g. node 1), - // not that it matters which nodes they use when - // the connections are closed afterwards anyway) - // -- Monster Iestyn 12/11/18 - Net_CloseConnection(node|FORCECLOSE); - } - } -} - -void CL_UpdateServerList(boolean internetsearch, INT32 room) -{ - (void)internetsearch; - (void)room; - - SL_ClearServerList(0); - - if (!netgame && I_NetOpenSocket) - { - if (I_NetOpenSocket()) - { - netgame = true; - multiplayer = true; - } - } - - // search for local servers - 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 */ - m_waiting_mode = M_WAITING_SERVERS; - - I_lock_mutex(&ms_QueryId_mutex); - { - ctx->id = ms_QueryId; - } - I_unlock_mutex(ms_QueryId_mutex); - - ctx->room = room; - - I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); -#else - msg_server_t *server_list; - - server_list = GetShortServersList(room, 0); - - if (server_list) - { - CL_QueryServerList(server_list); - free(server_list); - } -#endif - } -#endif/*MASTERSERVER*/ -} - -static void M_ConfirmConnect(event_t *ev) -{ - if (ev->type == ev_keydown || ev->type == ev_gamepad_down) - { - if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A)) - { - if (totalfilesrequestednum > 0) - { - if (CL_SendFileRequest()) - { - cl_mode = CL_DOWNLOADFILES; - Snake_Allocate(&snake); - } - } - else - cl_mode = CL_LOADFILES; - - M_ClearMenus(true); - } - else if ((ev->type == ev_keydown && (ev->key == 'n' || ev->key == KEY_ESCAPE)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_B)) - { - cl_mode = CL_ABORTED; - M_ClearMenus(true); - } - } -} - -static boolean CL_FinishedFileList(void) -{ - INT32 i; - char *downloadsize = NULL; - - //CONS_Printf(M_GetText("Checking files...\n")); - i = CL_CheckFiles(); - if (i == 4) // still checking ... - { - return true; - } - else if (i == 3) // too many files - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have too many WAD files loaded\n" - "to add ones the server is using.\n" - "Please restart SRB2 before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 2) // cannot join for some reason - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have the wrong addons loaded.\n\n" - "To play on this server, restart\n" - "the game and don't load any addons.\n" - "SRB2 will automatically add\n" - "everything you need when you join.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 1) - { - 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 ENTER to continue\nor ESC to cancel.\n\n" - ), M_ConfirmConnect, MM_EVENTHANDLER); - cl_mode = CL_CONFIRMCONNECT; - curfadevalue = 0; - } - else - cl_mode = CL_LOADFILES; - } - else - { - // must download something - // can we, though? - if (!CL_CheckDownloadable()) // nope! - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "An error occured when trying to\n" - "download missing addons.\n" - "(This is almost always a problem\n" - "with the server, not your game.)\n\n" - "See the console or log file\n" - "for additional details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - - downloadcompletednum = 0; - downloadcompletedsize = 0; - totalfilesrequestednum = 0; - totalfilesrequestedsize = 0; - - if (fileneeded == NULL) - I_Error("CL_FinishedFileList: fileneeded == NULL"); - - 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\nis required to join.\n" - "\n" - "You may download, load server addons,\nand wait for a slot.\n" - "\n" - "Press ENTER to continue\nor ESC to cancel.\n" - ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); - else - M_StartMessage(va(M_GetText( - "Download of %s additional content\nis required to join.\n" - "\n" - "Press ENTER to continue\nor ESC to cancel.\n" - ), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER); - - Z_Free(downloadsize); - cl_mode = CL_CONFIRMCONNECT; - curfadevalue = 0; - } - return true; -} - -static const char * InvalidServerReason (serverinfo_pak *info) -{ -#define EOT "\nPress ESC\n" - - /* magic number for new packet format */ - if (info->_255 != 255) - { - return - "Outdated server (version unknown).\n" EOT; - } - - if (strncmp(info->application, SRB2APPLICATION, sizeof - info->application)) - { - return va( - "%s cannot connect\n" - "to %s servers.\n" EOT, - SRB2APPLICATION, - info->application); - } - - if ( - info->packetversion != PACKETVERSION || - info->version != VERSION || - info->subversion != SUBVERSION - ){ - return va( - "Incompatible %s versions.\n" - "(server version %d.%d.%d)\n" EOT, - SRB2APPLICATION, - info->version / 100, - info->version % 100, - info->subversion); - } - - switch (info->refusereason) - { - case REFUSE_BANNED: - return - "You have been banned\n" - "from the server.\n" EOT; - case REFUSE_JOINS_DISABLED: - return - "The server is not accepting\n" - "joins for the moment.\n" EOT; - case REFUSE_SLOTS_FULL: - return va( - "Maximum players reached: %d\n" EOT, - info->maxplayer); - default: - if (info->refusereason) - { - return - "You can't join.\n" - "I don't know why,\n" - "but you can't join.\n" EOT; - } - } - - return NULL; - -#undef EOT -} - -/** Called by CL_ServerConnectionTicker - * - * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. - * \return False if the connection was aborted - * \sa CL_ServerConnectionTicker - * \sa CL_ConnectToServer - * - */ -static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) -{ - INT32 i; - - // serverlist is updated by GetPacket function - if (serverlistcount > 0) - { - // this can be a responce to our broadcast request - if (servernode == -1 || servernode >= MAXNETNODES) - { - i = 0; - servernode = serverlist[i].node; - CONS_Printf(M_GetText("Found, ")); - } - else - { - i = SL_SearchServer(servernode); - if (i < 0) - return true; - } - - if (client) - { - serverinfo_pak *info = &serverlist[i].info; - - if (info->refusereason == REFUSE_SLOTS_FULL) - serverisfull = true; - else - { - const char *reason = InvalidServerReason(info); - - // Quit here rather than downloading files - // and being refused later. - if (reason) - { - char *message = Z_StrDup(reason); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(message, NULL, MM_NOTHING); - Z_Free(message); - return false; - } - } - - D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0); - - if (info->flags & 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. - *asksent = 0; - } - - return true; - } - - // Ask the info to the server (askinfo packet) - if (*asksent + NEWTICRATE < I_GetTime()) - { - SendAskInfo(servernode); - *asksent = I_GetTime(); - } - - return true; -} - -/** Called by CL_ConnectToServer - * - * \param tmpsave The name of the gamestate file??? - * \param oldtic Used for knowing when to poll events and redraw - * \param asksent ??? - * \return False if the connection was aborted - * \sa CL_ServerConnectionSearchTicker - * \sa CL_ConnectToServer - * - */ -static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic_t *asksent) -{ - boolean waitmore; - INT32 i; - - switch (cl_mode) - { - case CL_SEARCHING: - if (!CL_ServerConnectionSearchTicker(asksent)) - return false; - break; - - case CL_ASKFULLFILELIST: - if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved - cl_mode = CL_CHECKFILES; - else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent) - { - if (CL_AskFileList(fileneedednum)) - { - cl_lastcheckedfilecount = fileneedednum; - *asksent = I_GetTime() + NEWTICRATE; - } - } - break; - case CL_CHECKFILES: - if (!CL_FinishedFileList()) - return false; - break; - case CL_DOWNLOADFILES: - waitmore = false; - for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status == FS_DOWNLOADING - || fileneeded[i].status == FS_REQUESTED) - { - waitmore = true; - break; - } - if (waitmore) - break; // exit the case - - Snake_Free(&snake); - - cl_mode = CL_LOADFILES; - break; - case CL_LOADFILES: - if (CL_LoadServerFiles()) - { - FreeFileNeeded(); - *asksent = 0; //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() && !server) - { - 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); - return false; - } - - // 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); - - if (I_GetTime() >= *asksent && CL_SendJoin()) - { - *asksent = I_GetTime() + NEWTICRATE*3; - cl_mode = CL_WAITJOINRESPONSE; - } - break; - case CL_WAITJOINRESPONSE: - if (I_GetTime() >= *asksent) - { - cl_mode = CL_ASKJOIN; - } - break; - case CL_DOWNLOADSAVEGAME: - // At this state, the first (and only) needed file is the gamestate - if (fileneeded[0].status == FS_FOUND) - { - // Gamestate is now handled within CL_LoadReceivedSavegame() - CL_LoadReceivedSavegame(false); - cl_mode = CL_CONNECTED; - } // don't break case continue to CL_CONNECTED - else - break; - - case CL_CONNECTED: - case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect - default: - break; - - // Connection closed by cancel, timeout or refusal. - case CL_ABORTED: - cl_mode = CL_SEARCHING; - return false; - } - - GetPackets(); - Net_AckTicker(); - - // Call it only once by tic - if (*oldtic != I_GetTime()) - { - I_OsPolling(); - - if (cl_mode == CL_CONFIRMCONNECT) - D_ProcessEvents(); //needed for menu system to receive inputs - else - { - // my hand has been forced and I am dearly sorry for this awful hack :vomit: - for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) - { - G_MapEventsToControls(&events[eventtail]); - } - } - - if (gamekeydown[KEY_ESCAPE] || gamepads[0].buttons[GAMEPAD_BUTTON_B] || cl_mode == CL_ABORTED) - { - CONS_Printf(M_GetText("Network game synchronization aborted.\n")); - M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); - - Snake_Free(&snake); - - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - memset(gamekeydown, 0, NUMKEYS); - return false; - } - else if (cl_mode == CL_DOWNLOADFILES && snake) - Snake_Update(snake); - - if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) - FileReceiveTicker(); - - // why are these here? this is for servers, we're a client - //if (key == 's' && server) - // doomcom->numnodes = (INT16)pnumnodes; - //FileSendTicker(); - *oldtic = I_GetTime(); - - if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) - { - if (!snake) - { - F_MenuPresTicker(true); // title sky - 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(); - S_UpdateSounds(); - S_UpdateClosedCaptions(); - } - } - else - { - I_Sleep(cv_sleep.value); - I_UpdateTime(cv_timescale.value); - } - - return true; -} - -/** Use adaptive send using net_bandwidth and stat.sendbytes - * - * \todo Better description... - * - */ -static void CL_ConnectToServer(void) -{ - INT32 pnumnodes, nodewaited = doomcom->numnodes, i; - tic_t oldtic; - tic_t asksent; - char tmpsave[256]; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - lastfilenum = -1; - - cl_mode = CL_SEARCHING; - - // Don't get a corrupt savegame error because tmpsave already exists - if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) - I_Error("Can't delete %s\n", tmpsave); - - if (netgame) - { - if (servernode < 0 || servernode >= MAXNETNODES) - CONS_Printf(M_GetText("Searching for a server...\n")); - else - CONS_Printf(M_GetText("Contacting the server...\n")); - } - - if (gamestate == GS_INTERMISSION) - Y_EndIntermission(); // clean up intermission graphics etc - - DEBFILE(va("waiting %d nodes\n", doomcom->numnodes)); - G_SetGamestate(GS_WAITINGPLAYERS); - wipegamestate = GS_WAITINGPLAYERS; - - ClearAdminPlayers(); - pnumnodes = 1; - oldtic = I_GetTime() - 1; - - asksent = (tic_t) - TICRATE; - firstconnectattempttime = I_GetTime(); - - i = SL_SearchServer(servernode); - - if (i != -1) - { - char *gametypestr = serverlist[i].info.gametypename; - CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; - CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); - CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, - serverlist[i].info.version%100, serverlist[i].info.subversion); - } - SL_ClearServerList(servernode); - - do - { - // If the connection was aborted for some reason, leave - if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) - return; - - if (server) - { - pnumnodes = 0; - for (i = 0; i < MAXNETNODES; i++) - if (netnodes[i].ingame) - pnumnodes++; - } - } - while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); - - DEBFILE(va("Synchronisation Finished\n")); - - displayplayer = consoleplayer; -} - typedef struct banreason_s { char *reason; @@ -3525,39 +2486,6 @@ static void HandleTimeout(SINT8 node) M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); } -/** Called when a PT_SERVERINFO packet is received - * - * \param node The packet sender - * \note What happens if the packet comes from a client or something like that? - * - */ -static void HandleServerInfo(SINT8 node) -{ - // compute ping in ms - const tic_t ticnow = I_GetTime(); - const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time); - const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; - netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); - netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; - netbuffer->u.serverinfo.application - [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; - netbuffer->u.serverinfo.gametypename - [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; - - SL_InsertServer(&netbuffer->u.serverinfo, node); -} - -// Helper function for packets that should only be sent by the server -// If it is NOT from the server, bail out and close the connection! -static boolean ServerOnly(SINT8 node) -{ - if (node == servernode) - return false; - - Net_CloseConnection(node); - return true; -} - static void PT_AskInfoViaMS(SINT8 node) { Net_CloseConnection(node); @@ -3582,23 +2510,6 @@ static void PT_TellFilesNeeded(SINT8 node) Net_CloseConnection(node); } -static void PT_MoreFilesNeeded(SINT8 node) -{ - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - return; - } - if (ServerOnly(node)) - return; - if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) - { - D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); - if (!netbuffer->u.filesneededcfg.more) - cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list - } -} - static void PT_AskInfo(SINT8 node) { if (server && serverrunning) @@ -3609,91 +2520,6 @@ static void PT_AskInfo(SINT8 node) Net_CloseConnection(node); } -// Negative response of client join request -static void PT_ServerRefuse(SINT8 node) -{ - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - return; - } - if (ServerOnly(node)) - return; - if (cl_mode == CL_WAITJOINRESPONSE) - { - // Save the reason so it can be displayed after quitting the netgame - char *reason = strdup(netbuffer->u.serverrefuse.reason); - if (!reason) - I_Error("Out of memory!\n"); - - 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); - return; - } - - 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. - cl_mode = CL_ABORTED; - } -} - -// Positive response of client join request -static void PT_ServerCFG(SINT8 node) -{ - if (server && serverrunning && node != servernode) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - return; - } - if (ServerOnly(node)) - return; - /// \note how would this happen? and is it doing the right thing if it does? - if (cl_mode != CL_WAITJOINRESPONSE) - return; - - if (client) - { - maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - G_SetGametype(netbuffer->u.servercfg.gametype); - modifiedgame = netbuffer->u.servercfg.modifiedgame; - memcpy(server_context, netbuffer->u.servercfg.server_context, 8); - } - - netnodes[(UINT8)servernode].ingame = true; - serverplayer = netbuffer->u.servercfg.serverplayer; - doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); - mynode = netbuffer->u.servercfg.clientnode; - if (serverplayer >= 0) - playernode[(UINT8)serverplayer] = servernode; - - if (netgame) - CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); - DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); - - /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? - /// Shouldn't them be downloaded even at intermission time? - /// Also, according to HandleConnect, the server will send the savegame even during intermission... - if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || - netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) - cl_mode = CL_DOWNLOADSAVEGAME; - else - cl_mode = CL_CONNECTED; -} - static void PT_ClientCmd(SINT8 node, INT32 netconsole) { tic_t realend, realstart; @@ -4190,7 +3016,7 @@ static void HandlePacketFromPlayer(SINT8 node) * \todo Add details to this description (lol) * */ -static void GetPackets(void) +void GetPackets(void) { SINT8 node; // The packet sender diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 50b86e9f0..3b0690a79 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -332,15 +332,6 @@ typedef struct #pragma pack() #endif -#define MAXSERVERLIST (MAXNETNODES-1) -typedef struct -{ - SINT8 node; - serverinfo_pak info; -} serverelem_t; - -extern serverelem_t serverlist[MAXSERVERLIST]; -extern UINT32 serverlistcount; extern INT32 mapchangepending; // Points inside doomcom @@ -385,6 +376,8 @@ extern boolean dedicated; // For dedicated server extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; +extern tic_t maketic; +extern tic_t neededtic; void Command_Ping_f(void); extern tic_t connectiontimeout; @@ -411,6 +404,8 @@ void SendKick(UINT8 playernum, UINT8 msg); // Create any new ticcmds and broadcast to other players. void NetUpdate(void); +void GetPackets(void); + void SV_StartSinglePlayerServer(void); void SV_SpawnServer(void); void SV_StopServer(void); @@ -419,9 +414,8 @@ void CL_AddSplitscreenPlayer(void); void CL_RemoveSplitscreenPlayer(void); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); -void CL_QueryServerList(msg_server_t *list); -void CL_UpdateServerList(boolean internetsearch, INT32 room); void CL_RemovePlayer(INT32 playernum, kickreason_t reason); +void CL_LoadReceivedSavegame(boolean reloading); // Is there a game running boolean Playing(void); diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index 72dc1cafb..68e46b52a 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -20,6 +20,7 @@ Documentation available here. #include "../doomdef.h" #include "d_clisrv.h" +#include "client_connection.h" #include "../command.h" #include "../m_argv.h" #include "../m_menu.h" diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index 78301f4d9..f603d78e5 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -20,6 +20,7 @@ #include "../command.h" #include "../i_threads.h" #include "mserv.h" +#include "client_connection.h" #include "../m_menu.h" #include "../z_zone.h" From fc41dd78f46f5683612a5e33f922d94881d2b13e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 1 Jan 2023 11:45:09 +0100 Subject: [PATCH 38/93] Move server-side connection handling to a new file --- src/netcode/Sourcefile | 1 + src/netcode/d_clisrv.c | 475 +----------------------------- src/netcode/d_clisrv.h | 3 +- src/netcode/d_netcmd.c | 1 + src/netcode/server_connection.c | 497 ++++++++++++++++++++++++++++++++ src/netcode/server_connection.h | 29 ++ 6 files changed, 533 insertions(+), 473 deletions(-) create mode 100644 src/netcode/server_connection.c create mode 100644 src/netcode/server_connection.h diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile index c11b3d6c1..4177166a4 100644 --- a/src/netcode/Sourcefile +++ b/src/netcode/Sourcefile @@ -1,4 +1,5 @@ d_clisrv.c +server_connection.c client_connection.c d_net.c d_netcmd.c diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index f7a9260e1..c1264768e 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -49,6 +49,7 @@ #include "../lua_libs.h" #include "../md5.h" #include "../m_perfstats.h" +#include "server_connection.h" #include "client_connection.h" // @@ -79,15 +80,6 @@ netnode_t netnodes[MAXNETNODES]; // Server specific vars UINT8 playernode[MAXPLAYERS]; -char playeraddress[MAXPLAYERS][64]; - -// Minimum timeout for sending the savegame -// The actual timeout will be longer depending on the savegame length -tic_t jointimeout = (10*TICRATE); - -// Incremented by cv_joindelay when a client joins, decremented each tic. -// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. -static tic_t joindelay = 0; UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. @@ -100,7 +92,6 @@ tic_t maketic; static INT16 consistancy[BACKUPTICS]; -static UINT8 player_joining = false; UINT8 hu_redownloadinggamestate = 0; // true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks @@ -501,229 +492,6 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) static INT16 Consistancy(void); -static INT32 FindRejoinerNum(SINT8 node) -{ - char strippednodeaddress[64]; - const char *nodeaddress; - char *port; - INT32 i; - - // Make sure there is no dead dress before proceeding to the stripping - if (!I_GetNodeAddress) - return -1; - nodeaddress = I_GetNodeAddress(node); - if (!nodeaddress) - return -1; - - // Strip the address of its port - strcpy(strippednodeaddress, nodeaddress); - port = strchr(strippednodeaddress, ':'); - if (port) - *port = '\0'; - - // Check if any player matches the stripped address - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX - && !strcmp(playeraddress[i], strippednodeaddress)) - return i; - } - - return -1; -} - -static UINT8 -GetRefuseReason (INT32 node) -{ - if (!node || FindRejoinerNum(node) != -1) - return 0; - else if (bannednode && bannednode[node]) - return REFUSE_BANNED; - else if (!cv_allownewplayer.value) - return REFUSE_JOINS_DISABLED; - else if (D_NumPlayers() >= cv_maxplayers.value) - return REFUSE_SLOTS_FULL; - else - return 0; -} - -static void SV_SendServerInfo(INT32 node, tic_t servertime) -{ - UINT8 *p; - - netbuffer->packettype = PT_SERVERINFO; - netbuffer->u.serverinfo._255 = 255; - netbuffer->u.serverinfo.packetversion = PACKETVERSION; - netbuffer->u.serverinfo.version = VERSION; - netbuffer->u.serverinfo.subversion = SUBVERSION; - strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, - sizeof netbuffer->u.serverinfo.application); - // return back the time value so client can compute their ping - netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); - netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); - - netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); - netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; - - netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); - - strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], - sizeof netbuffer->u.serverinfo.gametypename); - netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; - netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); - netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0); - strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, - MAXSERVERNAME); - strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); - - M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); - - memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle); - - if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl) - { - char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; - while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0') - { - if (!(*read & 0x80)) - { - *writ = toupper(*read); - writ++; - } - read++; - } - *writ = '\0'; - //strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33); - } - else - strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32); - - if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - netbuffer->u.serverinfo.iszone = 1; - else - netbuffer->u.serverinfo.iszone = 0; - - if (mapheaderinfo[gamemap-1]) - netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; - - p = PutFileNeeded(0); - - HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); -} - -static void SV_SendPlayerInfo(INT32 node) -{ - UINT8 i; - netbuffer->packettype = PT_PLAYERINFO; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - { - netbuffer->u.playerinfo[i].num = 255; // This slot is empty. - continue; - } - - netbuffer->u.playerinfo[i].num = i; - strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); - netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; - - //fetch IP address - //No, don't do that, you fuckface. - memset(netbuffer->u.playerinfo[i].address, 0, 4); - - if (G_GametypeHasTeams()) - { - if (!players[i].ctfteam) - netbuffer->u.playerinfo[i].team = 255; - else - netbuffer->u.playerinfo[i].team = (UINT8)players[i].ctfteam; - } - else - { - if (players[i].spectator) - netbuffer->u.playerinfo[i].team = 255; - else - netbuffer->u.playerinfo[i].team = 0; - } - - netbuffer->u.playerinfo[i].score = LONG(players[i].score); - netbuffer->u.playerinfo[i].timeinserver = SHORT((UINT16)(players[i].jointime / TICRATE)); - netbuffer->u.playerinfo[i].skin = (UINT8)(players[i].skin -#ifdef DEVELOP // it's safe to do this only because PLAYERINFO isn't read by the game itself - % 3 -#endif - ); - - // Extra data - netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor; - - if (players[i].pflags & PF_TAGIT) - netbuffer->u.playerinfo[i].data |= 0x20; - - if (players[i].gotflag) - netbuffer->u.playerinfo[i].data |= 0x40; - - if (players[i].powers[pw_super]) - netbuffer->u.playerinfo[i].data |= 0x80; - } - - HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); -} - -/** Sends a PT_SERVERCFG packet - * - * \param node The destination - * \return True if the packet was successfully sent - * - */ -static boolean SV_SendServerConfig(INT32 node) -{ - boolean waspacketsent; - - netbuffer->packettype = PT_SERVERCFG; - - netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; - netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); - netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); - netbuffer->u.servercfg.clientnode = (UINT8)node; - netbuffer->u.servercfg.gamestate = (UINT8)gamestate; - netbuffer->u.servercfg.gametype = (UINT8)gametype; - netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; - - memcpy(netbuffer->u.servercfg.server_context, server_context, 8); - - { - const size_t len = sizeof (serverconfig_pak); - -#ifdef DEBUGFILE - if (debugfile) - { - fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n", - sizeu1(len), node); - } -#endif - - waspacketsent = HSendPacket(node, true, 0, len); - } - -#ifdef DEBUGFILE - if (debugfile) - { - if (waspacketsent) - { - fprintf(debugfile, "ServerConfig Packet was sent\n"); - } - else - { - fprintf(debugfile, "ServerConfig Packet could not be sent right now\n"); - } - } -#endif - - return waspacketsent; -} - #define SAVEGAMESIZE (768*1024) static boolean SV_ResendingSavegameToAnyone(void) @@ -736,7 +504,7 @@ static boolean SV_ResendingSavegameToAnyone(void) return false; } -static void SV_SendSaveGame(INT32 node, boolean resending) +void SV_SendSaveGame(INT32 node, boolean resending) { size_t length, compressedlen; UINT8 *savebuffer; @@ -1190,7 +958,7 @@ static void Command_connect(void) CL_ConnectToServer(); } -static void ResetNode(INT32 node) +void ResetNode(INT32 node) { memset(&netnodes[node], 0, sizeof(*netnodes)); netnodes[node].player = -1; @@ -2020,17 +1788,6 @@ void D_QuitNetGame(void) #endif } -// Adds a node to the game (player will follow at map change or at savegame....) -static inline void SV_AddNode(INT32 node) -{ - netnodes[node].tic = gametic; - netnodes[node].supposedtic = gametic; - // little hack because the server connects to itself and puts - // nodeingame when connected not here - if (node) - netnodes[node].ingame = true; -} - // Xcmd XD_ADDPLAYER static void Got_AddPlayer(UINT8 **p, INT32 playernum) { @@ -2163,56 +1920,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) LUA_HookInt(newplayernum, HOOK(PlayerJoin)); } -static void SV_AddPlayer(SINT8 node, const char *name) -{ - INT32 n; - UINT8 buf[2 + MAXPLAYERNAME]; - UINT8 *p; - INT32 newplayernum; - - newplayernum = FindRejoinerNum(node); - if (newplayernum == -1) - { - // search for a free playernum - // we can't use playeringame since it is not updated here - for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) - { - if (playeringame[newplayernum]) - continue; - for (n = 0; n < MAXNETNODES; n++) - if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) - break; - if (n == MAXNETNODES) - break; - } - } - - // should never happen since we check the playernum - // before accepting the join - I_Assert(newplayernum < MAXPLAYERS); - - playernode[newplayernum] = (UINT8)node; - - p = buf + 2; - buf[0] = (UINT8)node; - buf[1] = newplayernum; - if (netnodes[node].numplayers < 1) - { - netnodes[node].player = newplayernum; - } - else - { - netnodes[node].player2 = newplayernum; - buf[1] |= 0x80; - } - WRITESTRINGN(p, name, MAXPLAYERNAME); - netnodes[node].numplayers++; - - SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); - - DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); -} - void CL_AddSplitscreenPlayer(void) { if (cl_mode == CL_CONNECTED) @@ -2298,15 +2005,6 @@ void SV_StartSinglePlayerServer(void) multiplayer = true; } -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); - Net_CloseConnection(node); -} - // used at txtcmds received to check packetsize bound static size_t TotalTextCmdPerTic(tic_t tic) { @@ -2323,139 +2021,6 @@ static size_t TotalTextCmdPerTic(tic_t tic) return total; } -static const char * -GetRefuseMessage (SINT8 node, INT32 rejoinernum) -{ - clientconfig_pak *cc = &netbuffer->u.clientcfg; - - boolean rejoining = (rejoinernum != -1); - - if (!node)/* server connecting to itself */ - return NULL; - - if ( - cc->modversion != MODVERSION || - strncmp(cc->application, SRB2APPLICATION, - sizeof cc->application) - ){ - return/* this is probably client's fault */ - "Incompatible."; - } - else if (bannednode && bannednode[node]) - { - return - "You have been banned\n" - "from the server."; - } - else if (cc->localplayers != 1) - { - return - "Wrong player count."; - } - - if (!rejoining) - { - if (!cv_allownewplayer.value) - { - return - "The server is not accepting\n" - "joins for the moment."; - } - else if (D_NumPlayers() >= cv_maxplayers.value) - { - return va( - "Maximum players reached: %d", - cv_maxplayers.value); - } - } - - if (luafiletransfers) - { - return - "The serveris broadcasting a file\n" - "requested by a Lua script.\n" - "Please wait a bit and then\n" - "try rejoining."; - } - - if (netgame) - { - const tic_t th = 2 * cv_joindelay.value * TICRATE; - - if (joindelay > th) - { - return va( - "Too many people are connecting.\n" - "Please wait %d seconds and then\n" - "try rejoining.", - (joindelay - th) / TICRATE); - } - } - - return NULL; -} - -/** Called when a PT_CLIENTJOIN packet is received - * - * \param node The packet sender - * - */ -static void HandleConnect(SINT8 node) -{ - char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; - INT32 numplayers = netbuffer->u.clientcfg.localplayers; - INT32 rejoinernum; - INT32 i; - - // Ignore duplicate packets - if (netnodes[node].ingame) - return; - - rejoinernum = FindRejoinerNum(node); - - const char *refuse = GetRefuseMessage(node, rejoinernum); - if (refuse) - { - SV_SendRefuse(node, refuse); - return; - } - - for (i = 0; i < numplayers; i++) - { - strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); - if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) - { - SV_SendRefuse(node, "Bad player name"); - return; - } - } - - SV_AddNode(node); - - if (!SV_SendServerConfig(node)) - { - /// \note Shouldn't SV_SendRefuse be called before ResetNode? - ResetNode(node); - SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); - /// \todo fix this !!! - return; // restart the while - } - DEBFILE("new node joined\n"); - - if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) - { - SV_SendSaveGame(node, false); // send a complete game state - DEBFILE("send savegame\n"); - } - - // Splitscreen can allow 2 players in one node - for (i = 0; i < numplayers; i++) - SV_AddPlayer(node, names[i]); - - joindelay += cv_joindelay.value * TICRATE; - player_joining = true; -} - /** Called when a PT_SERVERSHUTDOWN packet is received * * \param node The packet sender (should be the server) @@ -2486,40 +2051,6 @@ static void HandleTimeout(SINT8 node) M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); } -static void PT_AskInfoViaMS(SINT8 node) -{ - Net_CloseConnection(node); -} - -static void PT_TellFilesNeeded(SINT8 node) -{ - if (server && serverrunning) - { - UINT8 *p; - INT32 firstfile = netbuffer->u.filesneedednum; - - netbuffer->packettype = PT_MOREFILESNEEDED; - netbuffer->u.filesneededcfg.first = firstfile; - netbuffer->u.filesneededcfg.more = 0; - - p = PutFileNeeded(firstfile); - - HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); - } - else // Shouldn't get this if you aren't the server...? - Net_CloseConnection(node); -} - -static void PT_AskInfo(SINT8 node) -{ - if (server && serverrunning) - { - SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); - SV_SendPlayerInfo(node); // Send extra info - } - Net_CloseConnection(node); -} - static void PT_ClientCmd(SINT8 node, INT32 netconsole) { tic_t realend, realstart; diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 3b0690a79..b8da645ba 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -381,7 +381,6 @@ extern tic_t neededtic; void Command_Ping_f(void); extern tic_t connectiontimeout; -extern tic_t jointimeout; extern UINT16 pingmeasurecount; extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; @@ -405,11 +404,13 @@ void SendKick(UINT8 playernum, UINT8 msg); void NetUpdate(void); void GetPackets(void); +void ResetNode(INT32 node); void SV_StartSinglePlayerServer(void); void SV_SpawnServer(void); void SV_StopServer(void); void SV_ResetServer(void); +void SV_SendSaveGame(INT32 node, boolean resending); void CL_AddSplitscreenPlayer(void); void CL_RemoveSplitscreenPlayer(void); void CL_Reset(void); diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index ed310805d..fe4cf22bd 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -36,6 +36,7 @@ #include "../p_spec.h" #include "../m_cheat.h" #include "d_clisrv.h" +#include "server_connection.h" #include "d_net.h" #include "../v_video.h" #include "../d_main.h" diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c new file mode 100644 index 000000000..9e397b0f3 --- /dev/null +++ b/src/netcode/server_connection.c @@ -0,0 +1,497 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file server_connection.c +/// \brief Server-side part of connection handling + +#include "server_connection.h" +#include "i_net.h" +#include "d_clisrv.h" +#include "d_netfil.h" +#include "mserv.h" +#include "../byteptr.h" +#include "../g_game.h" +#include "../g_state.h" +#include "../p_setup.h" +#include "../p_tick.h" +#include "../doomstat.h" + +// Minimum timeout for sending the savegame +// The actual timeout will be longer depending on the savegame length +tic_t jointimeout = (10*TICRATE); + +// Incremented by cv_joindelay when a client joins, decremented each tic. +// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. +tic_t joindelay = 0; + +// Minimum timeout for sending the savegame +// The actual timeout will be longer depending on the savegame length +char playeraddress[MAXPLAYERS][64]; + +UINT8 player_joining = false; + +static INT32 FindRejoinerNum(SINT8 node) +{ + char strippednodeaddress[64]; + const char *nodeaddress; + char *port; + INT32 i; + + // Make sure there is no dead dress before proceeding to the stripping + if (!I_GetNodeAddress) + return -1; + nodeaddress = I_GetNodeAddress(node); + if (!nodeaddress) + return -1; + + // Strip the address of its port + strcpy(strippednodeaddress, nodeaddress); + port = strchr(strippednodeaddress, ':'); + if (port) + *port = '\0'; + + // Check if any player matches the stripped address + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX + && !strcmp(playeraddress[i], strippednodeaddress)) + return i; + } + + return -1; +} + +static UINT8 +GetRefuseReason (INT32 node) +{ + if (!node || FindRejoinerNum(node) != -1) + return 0; + else if (bannednode && bannednode[node]) + return REFUSE_BANNED; + else if (!cv_allownewplayer.value) + return REFUSE_JOINS_DISABLED; + else if (D_NumPlayers() >= cv_maxplayers.value) + return REFUSE_SLOTS_FULL; + else + return 0; +} + +static void SV_SendServerInfo(INT32 node, tic_t servertime) +{ + UINT8 *p; + + netbuffer->packettype = PT_SERVERINFO; + netbuffer->u.serverinfo._255 = 255; + netbuffer->u.serverinfo.packetversion = PACKETVERSION; + netbuffer->u.serverinfo.version = VERSION; + netbuffer->u.serverinfo.subversion = SUBVERSION; + strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, + sizeof netbuffer->u.serverinfo.application); + // return back the time value so client can compute their ping + netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); + netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); + + netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); + netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; + + netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); + + strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], + sizeof netbuffer->u.serverinfo.gametypename); + netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; + netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); + netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0); + strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, + MAXSERVERNAME); + strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); + + M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); + + memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle); + + if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl) + { + char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; + while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0') + { + if (!(*read & 0x80)) + { + *writ = toupper(*read); + writ++; + } + read++; + } + *writ = '\0'; + //strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33); + } + else + strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32); + + if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + netbuffer->u.serverinfo.iszone = 1; + else + netbuffer->u.serverinfo.iszone = 0; + + if (mapheaderinfo[gamemap-1]) + netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; + + p = PutFileNeeded(0); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); +} + +static void SV_SendPlayerInfo(INT32 node) +{ + UINT8 i; + netbuffer->packettype = PT_PLAYERINFO; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + netbuffer->u.playerinfo[i].num = 255; // This slot is empty. + continue; + } + + netbuffer->u.playerinfo[i].num = i; + strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); + netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; + + //fetch IP address + //No, don't do that, you fuckface. + memset(netbuffer->u.playerinfo[i].address, 0, 4); + + if (G_GametypeHasTeams()) + { + if (!players[i].ctfteam) + netbuffer->u.playerinfo[i].team = 255; + else + netbuffer->u.playerinfo[i].team = (UINT8)players[i].ctfteam; + } + else + { + if (players[i].spectator) + netbuffer->u.playerinfo[i].team = 255; + else + netbuffer->u.playerinfo[i].team = 0; + } + + netbuffer->u.playerinfo[i].score = LONG(players[i].score); + netbuffer->u.playerinfo[i].timeinserver = SHORT((UINT16)(players[i].jointime / TICRATE)); + netbuffer->u.playerinfo[i].skin = (UINT8)(players[i].skin +#ifdef DEVELOP // it's safe to do this only because PLAYERINFO isn't read by the game itself + % 3 +#endif + ); + + // Extra data + netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor; + + if (players[i].pflags & PF_TAGIT) + netbuffer->u.playerinfo[i].data |= 0x20; + + if (players[i].gotflag) + netbuffer->u.playerinfo[i].data |= 0x40; + + if (players[i].powers[pw_super]) + netbuffer->u.playerinfo[i].data |= 0x80; + } + + HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); +} + +/** Sends a PT_SERVERCFG packet + * + * \param node The destination + * \return True if the packet was successfully sent + * + */ +static boolean SV_SendServerConfig(INT32 node) +{ + boolean waspacketsent; + + netbuffer->packettype = PT_SERVERCFG; + + netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; + netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); + netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); + netbuffer->u.servercfg.clientnode = (UINT8)node; + netbuffer->u.servercfg.gamestate = (UINT8)gamestate; + netbuffer->u.servercfg.gametype = (UINT8)gametype; + netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; + + memcpy(netbuffer->u.servercfg.server_context, server_context, 8); + + { + const size_t len = sizeof (serverconfig_pak); + +#ifdef DEBUGFILE + if (debugfile) + { + fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n", + sizeu1(len), node); + } +#endif + + waspacketsent = HSendPacket(node, true, 0, len); + } + +#ifdef DEBUGFILE + if (debugfile) + { + if (waspacketsent) + { + fprintf(debugfile, "ServerConfig Packet was sent\n"); + } + else + { + fprintf(debugfile, "ServerConfig Packet could not be sent right now\n"); + } + } +#endif + + return waspacketsent; +} + +// Adds a node to the game (player will follow at map change or at savegame....) +static inline void SV_AddNode(INT32 node) +{ + netnodes[node].tic = gametic; + netnodes[node].supposedtic = gametic; + // little hack because the server connects to itself and puts + // nodeingame when connected not here + if (node) + netnodes[node].ingame = true; +} + +static void SV_AddPlayer(SINT8 node, const char *name) +{ + INT32 n; + UINT8 buf[2 + MAXPLAYERNAME]; + UINT8 *p; + INT32 newplayernum; + + newplayernum = FindRejoinerNum(node); + if (newplayernum == -1) + { + // search for a free playernum + // we can't use playeringame since it is not updated here + for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) + { + if (playeringame[newplayernum]) + continue; + for (n = 0; n < MAXNETNODES; n++) + if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) + break; + if (n == MAXNETNODES) + break; + } + } + + // should never happen since we check the playernum + // before accepting the join + I_Assert(newplayernum < MAXPLAYERS); + + playernode[newplayernum] = (UINT8)node; + + p = buf + 2; + buf[0] = (UINT8)node; + buf[1] = newplayernum; + if (netnodes[node].numplayers < 1) + { + netnodes[node].player = newplayernum; + } + else + { + netnodes[node].player2 = newplayernum; + buf[1] |= 0x80; + } + WRITESTRINGN(p, name, MAXPLAYERNAME); + netnodes[node].numplayers++; + + SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); + + DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); +} + +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); + Net_CloseConnection(node); +} + +static const char * +GetRefuseMessage (SINT8 node, INT32 rejoinernum) +{ + clientconfig_pak *cc = &netbuffer->u.clientcfg; + + boolean rejoining = (rejoinernum != -1); + + if (!node)/* server connecting to itself */ + return NULL; + + if ( + cc->modversion != MODVERSION || + strncmp(cc->application, SRB2APPLICATION, + sizeof cc->application) + ){ + return/* this is probably client's fault */ + "Incompatible."; + } + else if (bannednode && bannednode[node]) + { + return + "You have been banned\n" + "from the server."; + } + else if (cc->localplayers != 1) + { + return + "Wrong player count."; + } + + if (!rejoining) + { + if (!cv_allownewplayer.value) + { + return + "The server is not accepting\n" + "joins for the moment."; + } + else if (D_NumPlayers() >= cv_maxplayers.value) + { + return va( + "Maximum players reached: %d", + cv_maxplayers.value); + } + } + + if (luafiletransfers) + { + return + "The serveris broadcasting a file\n" + "requested by a Lua script.\n" + "Please wait a bit and then\n" + "try rejoining."; + } + + if (netgame) + { + const tic_t th = 2 * cv_joindelay.value * TICRATE; + + if (joindelay > th) + { + return va( + "Too many people are connecting.\n" + "Please wait %d seconds and then\n" + "try rejoining.", + (joindelay - th) / TICRATE); + } + } + + return NULL; +} + +/** Called when a PT_CLIENTJOIN packet is received + * + * \param node The packet sender + * + */ +void HandleConnect(SINT8 node) +{ + char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; + INT32 numplayers = netbuffer->u.clientcfg.localplayers; + INT32 rejoinernum; + INT32 i; + + // Ignore duplicate packets + if (netnodes[node].ingame) + return; + + rejoinernum = FindRejoinerNum(node); + + const char *refuse = GetRefuseMessage(node, rejoinernum); + if (refuse) + { + SV_SendRefuse(node, refuse); + return; + } + + for (i = 0; i < numplayers; i++) + { + strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); + if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) + { + SV_SendRefuse(node, "Bad player name"); + return; + } + } + + SV_AddNode(node); + + if (!SV_SendServerConfig(node)) + { + /// \note Shouldn't SV_SendRefuse be called before ResetNode? + ResetNode(node); + SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); + /// \todo fix this !!! + return; // restart the while + } + DEBFILE("new node joined\n"); + + if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) + { + SV_SendSaveGame(node, false); // send a complete game state + DEBFILE("send savegame\n"); + } + + // Splitscreen can allow 2 players in one node + for (i = 0; i < numplayers; i++) + SV_AddPlayer(node, names[i]); + + joindelay += cv_joindelay.value * TICRATE; + player_joining = true; +} + +void PT_AskInfoViaMS(SINT8 node) +{ + Net_CloseConnection(node); +} + +void PT_TellFilesNeeded(SINT8 node) +{ + if (server && serverrunning) + { + UINT8 *p; + INT32 firstfile = netbuffer->u.filesneedednum; + + netbuffer->packettype = PT_MOREFILESNEEDED; + netbuffer->u.filesneededcfg.first = firstfile; + netbuffer->u.filesneededcfg.more = 0; + + p = PutFileNeeded(firstfile); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); + } + else // Shouldn't get this if you aren't the server...? + Net_CloseConnection(node); +} + +void PT_AskInfo(SINT8 node) +{ + if (server && serverrunning) + { + SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); + SV_SendPlayerInfo(node); // Send extra info + } + Net_CloseConnection(node); +} diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h new file mode 100644 index 000000000..4204db2e6 --- /dev/null +++ b/src/netcode/server_connection.h @@ -0,0 +1,29 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file server_connection.h +/// \brief Server-side part of connection handling + +#ifndef __D_SERVER_CONNECTION__ +#define __D_SERVER_CONNECTION__ + +#include "../doomdef.h" +#include "../doomtype.h" + +void HandleConnect(SINT8 node); +void PT_AskInfoViaMS(SINT8 node); +void PT_TellFilesNeeded(SINT8 node); +void PT_AskInfo(SINT8 node); + +extern tic_t jointimeout; +extern tic_t joindelay; +extern char playeraddress[MAXPLAYERS][64]; +extern UINT8 player_joining; + +#endif From 0ade3ae0bc020e3ca932f98e977c78301dcbaa0d Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 5 Jan 2023 22:51:17 +0100 Subject: [PATCH 39/93] Move tic and net command handling to new files --- src/blua/liolib.c | 1 + src/command.c | 1 + src/g_game.c | 1 + src/hu_stuff.c | 1 + src/lua_consolelib.c | 1 + src/netcode/Sourcefile | 2 + src/netcode/d_clisrv.c | 878 +------------------------------- src/netcode/d_clisrv.h | 12 +- src/netcode/d_net.c | 1 + src/netcode/d_netcmd.c | 1 + src/netcode/d_netfil.c | 1 + src/netcode/net_command.c | 315 ++++++++++++ src/netcode/net_command.h | 62 +++ src/netcode/server_connection.c | 1 + src/netcode/tic_command.c | 504 ++++++++++++++++++ src/netcode/tic_command.h | 44 ++ src/p_inter.c | 1 + src/p_mobj.c | 1 + src/p_setup.c | 2 + src/p_tick.c | 1 + src/p_user.c | 1 + 21 files changed, 955 insertions(+), 877 deletions(-) create mode 100644 src/netcode/net_command.c create mode 100644 src/netcode/net_command.h create mode 100644 src/netcode/tic_command.c create mode 100644 src/netcode/tic_command.h diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 00e31e965..6b44e2eb8 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -20,6 +20,7 @@ #include "../i_system.h" #include "../g_game.h" #include "../netcode/d_netfil.h" +#include "../netcode/net_command.h" #include "../lua_libs.h" #include "../byteptr.h" #include "../lua_script.h" diff --git a/src/command.c b/src/command.c index 0256365f3..e0deff8e1 100644 --- a/src/command.c +++ b/src/command.c @@ -29,6 +29,7 @@ #include "p_saveg.h" #include "g_game.h" // for player_names #include "netcode/d_netcmd.h" +#include "netcode/net_command.h" #include "hu_stuff.h" #include "p_setup.h" #include "lua_script.h" diff --git a/src/g_game.c b/src/g_game.c index f47aa2183..70d249a2f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -16,6 +16,7 @@ #include "d_main.h" #include "d_player.h" #include "netcode/d_clisrv.h" +#include "netcode/net_command.h" #include "f_finale.h" #include "p_setup.h" #include "p_saveg.h" diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 33ef8a404..1e5e47df6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -20,6 +20,7 @@ #include "m_misc.h" // word jumping #include "netcode/d_clisrv.h" +#include "netcode/net_command.h" #include "g_game.h" #include "g_input.h" diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 9e5d1e2ee..831dceba5 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -16,6 +16,7 @@ #include "g_game.h" #include "byteptr.h" #include "z_zone.h" +#include "netcode/net_command.h" #include "lua_script.h" #include "lua_libs.h" diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile index 4177166a4..1039b218a 100644 --- a/src/netcode/Sourcefile +++ b/src/netcode/Sourcefile @@ -1,6 +1,8 @@ d_clisrv.c server_connection.c client_connection.c +tic_command.c +net_command.c d_net.c d_netcmd.c d_netfil.c diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index c1264768e..06e6da751 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -51,6 +51,8 @@ #include "../m_perfstats.h" #include "server_connection.h" #include "client_connection.h" +#include "tic_command.h" +#include "net_command.h" // // NETWORKING @@ -86,11 +88,9 @@ UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. tic_t servermaxping = 800; // server's max ping. Defaults to 800 -static tic_t firstticstosend; // min of the nettics -static tic_t tictoclear = 0; // optimize d_clearticcmd tic_t maketic; -static INT16 consistancy[BACKUPTICS]; +INT16 consistancy[BACKUPTICS]; UINT8 hu_redownloadinggamestate = 0; @@ -101,14 +101,9 @@ UINT8 adminpassmd5[16]; boolean adminpasswordset = false; // Client specific -static ticcmd_t localcmds; -static ticcmd_t localcmds2; -static boolean cl_packetmissed; // here it is for the secondary local player (splitscreen) static boolean cl_redownloadinggamestate = false; -static UINT8 localtextcmd[MAXTEXTCMD]; -static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen tic_t neededtic; SINT8 servernode = 0; // the number of the server node @@ -116,385 +111,19 @@ SINT8 servernode = 0; // the number of the server node /// \todo WORK! boolean acceptnewnode = true; -// engine - -// Must be a power of two -#define TEXTCMD_HASH_SIZE 4 - -typedef struct textcmdplayer_s -{ - INT32 playernum; - UINT8 cmd[MAXTEXTCMD]; - struct textcmdplayer_s *next; -} textcmdplayer_t; - -typedef struct textcmdtic_s -{ - tic_t tic; - textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; - struct textcmdtic_s *next; -} textcmdtic_t; - -ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; -static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; - - consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); -static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) -{ - const size_t d = n / sizeof(ticcmd_t); - const size_t r = n % sizeof(ticcmd_t); - UINT8 *ret = dest; - - if (r) - M_Memcpy(dest, src, n); - else if (d) - G_MoveTiccmd(dest, src, d); - return ret+n; -} - -static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n) -{ - const size_t d = n / sizeof(ticcmd_t); - const size_t r = n % sizeof(ticcmd_t); - UINT8 *ret = src; - - if (r) - M_Memcpy(dest, src, n); - else if (d) - G_MoveTiccmd(dest, src, d); - return ret+n; -} - - - // Some software don't support largest packet // (original sersetup, not exactely, but the probability of sending a packet // of 512 bytes is like 0.1) UINT16 software_MAXPACKETLENGTH; -/** Guesses the full value of a tic from its lowest byte, for a specific node - * - * \param low The lowest byte of the tic value - * \param node The node to deduce the tic for - * \return The full tic value - * - */ -tic_t ExpandTics(INT32 low, INT32 node) -{ - INT32 delta; - - delta = low - (netnodes[node].tic & UINT8_MAX); - - if (delta >= -64 && delta <= 64) - return (netnodes[node].tic & ~UINT8_MAX) + low; - else if (delta > 64) - return (netnodes[node].tic & ~UINT8_MAX) - 256 + low; - else //if (delta < -64) - return (netnodes[node].tic & ~UINT8_MAX) + 256 + low; -} - -// ----------------------------------------------------------------- -// Some extra data function for handle textcmd buffer -// ----------------------------------------------------------------- - -static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); - -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) -{ -#ifdef PARANOIA - if (id >= MAXNETXCMD) - I_Error("Command id %d too big", id); - if (listnetxcmd[id] != 0) - I_Error("Command id %d already used", id); -#endif - listnetxcmd[id] = cmd_f; -} - -void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) -{ - if (localtextcmd[0]+2+nparam > MAXTEXTCMD) - { - // for future reference: if (cv_debug) != debug disabled. - CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam)); - return; - } - localtextcmd[0]++; - localtextcmd[localtextcmd[0]] = (UINT8)id; - if (param && nparam) - { - M_Memcpy(&localtextcmd[localtextcmd[0]+1], param, nparam); - localtextcmd[0] = (UINT8)(localtextcmd[0] + (UINT8)nparam); - } -} - -// splitscreen player -void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) -{ - if (localtextcmd2[0]+2+nparam > MAXTEXTCMD) - { - I_Error("No more place in the buffer for netcmd %d\n",id); - return; - } - localtextcmd2[0]++; - localtextcmd2[localtextcmd2[0]] = (UINT8)id; - if (param && nparam) - { - M_Memcpy(&localtextcmd2[localtextcmd2[0]+1], param, nparam); - localtextcmd2[0] = (UINT8)(localtextcmd2[0] + (UINT8)nparam); - } -} - -UINT8 GetFreeXCmdSize(void) -{ - // -1 for the size and another -1 for the ID. - return (UINT8)(localtextcmd[0] - 2); -} - -// Frees all textcmd memory for the specified tic -static void D_FreeTextcmd(tic_t tic) -{ - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t *textcmdtic = *tctprev; - - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } - - if (textcmdtic) - { - INT32 i; - - // Remove this tic from the list. - *tctprev = textcmdtic->next; - - // Free all players. - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) - { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; - - while (textcmdplayer) - { - textcmdplayer_t *tcpnext = textcmdplayer->next; - Z_Free(textcmdplayer); - textcmdplayer = tcpnext; - } - } - - // Free this tic's own memory. - Z_Free(textcmdtic); - } -} - -// Gets the buffer for the specified ticcmd, or NULL if there isn't one -static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) -{ - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdtic && textcmdtic->tic != tic) textcmdtic = textcmdtic->next; - - // Do we have an entry for the tic? If so, look for player. - if (textcmdtic) - { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; - - if (textcmdplayer) return textcmdplayer->cmd; - } - - return NULL; -} - -// Gets the buffer for the specified ticcmd, creating one if necessary -static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) -{ - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer_t *textcmdplayer, **tcpprev; - - // Look for the tic. - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } - - // If we don't have an entry for the tic, make it. - if (!textcmdtic) - { - textcmdtic = *tctprev = Z_Calloc(sizeof (textcmdtic_t), PU_STATIC, NULL); - textcmdtic->tic = tic; - } - - tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer = *tcpprev; - - // Look for the player. - while (textcmdplayer && textcmdplayer->playernum != playernum) - { - tcpprev = &textcmdplayer->next; - textcmdplayer = textcmdplayer->next; - } - - // If we don't have an entry for the player, make it. - if (!textcmdplayer) - { - textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL); - textcmdplayer->playernum = playernum; - } - - return textcmdplayer->cmd; -} - -static void ExtraDataTicker(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] || i == 0) - { - UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); - - if (bufferstart) - { - UINT8 *curpos = bufferstart; - UINT8 *bufferend = &curpos[curpos[0]+1]; - - curpos++; - while (curpos < bufferend) - { - if (*curpos < MAXNETXCMD && listnetxcmd[*curpos]) - { - const UINT8 id = *curpos; - curpos++; - DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i)); - (listnetxcmd[id])(&curpos, i); - DEBFILE("done\n"); - } - else - { - if (server) - { - SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); - } - CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); - break; - } - } - } - } - - // If you are a client, you can safely forget the net commands for this tic - // If you are the server, you need to remember them until every client has been acknowledged, - // because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it - if (client) - D_FreeTextcmd(gametic); -} - -static void D_Clearticcmd(tic_t tic) -{ - INT32 i; - - D_FreeTextcmd(tic); - - for (i = 0; i < MAXPLAYERS; i++) - netcmds[tic%BACKUPTICS][i].angleturn = 0; - - DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); -} - -void D_ResetTiccmds(void) -{ - INT32 i; - - memset(&localcmds, 0, sizeof(ticcmd_t)); - memset(&localcmds2, 0, sizeof(ticcmd_t)); - - // Reset the net command list - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) - while (textcmds[i]) - D_Clearticcmd(textcmds[i]->tic); -} - -void SendKick(UINT8 playernum, UINT8 msg) -{ - UINT8 buf[2]; - - if (!(server && cv_rejointimeout.value)) - msg &= ~KICK_MSG_KEEP_BODY; - - buf[0] = playernum; - buf[1] = msg; - SendNetXCmd(XD_KICK, &buf, 2); -} - -// ----------------------------------------------------------------- -// end of extra data function -// ----------------------------------------------------------------- - -// ----------------------------------------------------------------- -// extra data function for lmps -// ----------------------------------------------------------------- - -// if extradatabit is set, after the ziped tic you find this: -// -// type | description -// ---------+-------------- -// byte | size of the extradata -// byte | the extradata (xd) bits: see XD_... -// with this byte you know what parameter folow -// if (xd & XDNAMEANDCOLOR) -// byte | color -// char[MAXPLAYERNAME] | name of the player -// endif -// if (xd & XD_WEAPON_PREF) -// byte | original weapon switch: boolean, true if use the old -// | weapon switch methode -// char[NUMWEAPONS] | the weapon switch priority -// byte | autoaim: true if use the old autoaim system -// endif -/*boolean AddLmpExtradata(UINT8 **demo_point, INT32 playernum) -{ - UINT8 *textcmd = D_GetExistingTextcmd(gametic, playernum); - - if (!textcmd) - return false; - - M_Memcpy(*demo_point, textcmd, textcmd[0]+1); - *demo_point += textcmd[0]+1; - return true; -} - -void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) -{ - UINT8 nextra; - UINT8 *textcmd; - - if (!demo_pointer) - return; - - textcmd = D_GetTextcmd(gametic, playernum); - nextra = **demo_pointer; - M_Memcpy(textcmd, *demo_pointer, nextra + 1); - // increment demo pointer - *demo_pointer += nextra + 1; -}*/ - -// ----------------------------------------------------------------- -// end extra data function for lmps -// ----------------------------------------------------------------- - -static INT16 Consistancy(void); - #define SAVEGAMESIZE (768*1024) -static boolean SV_ResendingSavegameToAnyone(void) +boolean SV_ResendingSavegameToAnyone(void) { INT32 i; @@ -2005,22 +1634,6 @@ void SV_StartSinglePlayerServer(void) multiplayer = true; } -// used at txtcmds received to check packetsize bound -static size_t TotalTextCmdPerTic(tic_t tic) -{ - INT32 i; - size_t total = 1; // num of textcmds in the tic (ntextcmd byte) - - for (i = 0; i < MAXPLAYERS; i++) - { - UINT8 *textcmd = D_GetExistingTextcmd(tic, i); - if ((!i || playeringame[i]) && textcmd) - total += 2 + textcmd[0]; // "+2" for size and playernum - } - - return total; -} - /** Called when a PT_SERVERSHUTDOWN packet is received * * \param node The packet sender (should be the server) @@ -2051,168 +1664,6 @@ static void HandleTimeout(SINT8 node) M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); } -static void PT_ClientCmd(SINT8 node, INT32 netconsole) -{ - tic_t realend, realstart; - - if (client) - return; - - // To save bytes, only the low byte of tic numbers are sent - // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); - - if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS - || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || netnodes[node].supposedtic < realend) - { - netnodes[node].supposedtic = realend; - } - // Discard out of order packet - if (netnodes[node].tic > realend) - { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", netnodes[node].tic)); - return; - } - - // Update the nettics - netnodes[node].tic = realend; - - // Don't do anything for packets of type NODEKEEPALIVE? - if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) - return; - - // As long as clients send valid ticcmds, the server can keep running, so reset the timeout - /// \todo Use a separate cvar for that kind of timeout? - netnodes[node].freezetimeout = I_GetTime() + connectiontimeout; - - // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); - - // Check ticcmd for "speed hacks" - if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) - { - CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); - //D_Clearticcmd(k); - - SendKick(netconsole, KICK_MSG_CON_FAIL); - return; - } - - // Splitscreen cmd - if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) - && netnodes[node].player2 >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)netnodes[node].player2], - &netbuffer->u.client2pak.cmd2, 1); - - // Check player consistancy during the level - if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) - && !SV_ResendingSavegameToAnyone() - && !netnodes[node].resendingsavegame && netnodes[node].savegameresendcooldown <= I_GetTime()) - { - if (cv_resynchattempts.value) - { - // Tell the client we are about to resend them the gamestate - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - HSendPacket(node, true, 0, 0); - - netnodes[node].resendingsavegame = true; - - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), - netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy)); - DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - return; - } - else - { - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - return; - } - } -} - -static void PT_TextCmd(SINT8 node, INT32 netconsole) -{ - if (client) - return; - - // splitscreen special - if (netbuffer->packettype == PT_TEXTCMD2) - netconsole = netnodes[node].player2; - - if (netconsole < 0 || netconsole >= MAXPLAYERS) - Net_UnAcknowledgePacket(node); - else - { - size_t j; - tic_t tic = maketic; - UINT8 *textcmd; - - // ignore if the textcmd has a reported size of zero - // this shouldn't be sent at all - if (!netbuffer->u.textcmd[0]) - { - DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", - node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // ignore if the textcmd size var is actually larger than it should be - // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength - if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) - { - DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", - netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), - node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // check if tic that we are making isn't too large else we cannot send it :( - // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time - j = software_MAXPACKETLENGTH - - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE - + (doomcom->numslots+1)*sizeof(ticcmd_t)); - - // search a tic that have enougth space in the ticcmd - while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), - (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) - tic++; - - if (tic >= firstticstosend + BACKUPTICS) - { - DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " - "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), - maketic, firstticstosend, node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // Make sure we have a buffer - if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); - - DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", - tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); - - M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); - textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; - } -} - static void PT_Login(SINT8 node, INT32 netconsole) { (void)node; @@ -2314,81 +1765,6 @@ static void PT_ReceivedGamestate(SINT8 node) netnodes[node].savegameresendcooldown = I_GetTime() + 5 * TICRATE; } -static void PT_ServerTics(SINT8 node, INT32 netconsole) -{ - UINT8 *pak, *txtpak, numtxtpak; - tic_t realend, realstart; - - if (!netnodes[node].ingame) - { - // Do not remove my own server (we have just get a out of order packet) - if (node != servernode) - { - DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); - Net_CloseConnection(node); - } - return; - } - - // Only accept PT_SERVERTICS from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - return; - } - - realstart = netbuffer->u.serverpak.starttic; - realend = realstart + netbuffer->u.serverpak.numtics; - - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; - - if (realend > gametic + CLIENTBACKUPTICS) - realend = gametic + CLIENTBACKUPTICS; - cl_packetmissed = realstart > neededtic; - - if (realstart <= neededtic && realend > neededtic) - { - tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realstart; i < realend; i++) - { - // clear first - D_Clearticcmd(i); - - // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - - // copy the textcmds - numtxtpak = *txtpak++; - for (j = 0; j < numtxtpak; j++) - { - INT32 k = *txtpak++; // playernum - const size_t txtsize = txtpak[0]+1; - - if (i >= gametic) // Don't copy old net commands - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); - txtpak += txtsize; - } - } - - neededtic = realend; - } - else - { - DEBFILE(va("frame not in bound: %u\n", neededtic)); - /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) - I_Error("Received an out of order PT_SERVERTICS packet!\n" - "Got tics %d-%d, needed tic %d\n\n" - "Please report this crash on the Master Board,\n" - "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ - } -} - static void PT_Ping(SINT8 node, INT32 netconsole) { // Only accept PT_PING from the server. @@ -2602,7 +1978,7 @@ void GetPackets(void) // no more use random generator, because at very first tic isn't yet synchronized // Note: It is called consistAncy on purpose. // -static INT16 Consistancy(void) +INT16 Consistancy(void) { INT32 i; UINT32 ret = 0; @@ -2708,239 +2084,11 @@ static INT16 Consistancy(void) return (INT16)(ret & 0xFFFF); } -// send the client packet to the server -static void CL_SendClientCmd(void) -{ - size_t packetsize = 0; - - netbuffer->packettype = PT_CLIENTCMD; - - if (cl_packetmissed) - netbuffer->packettype++; - netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX); - netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX); - - if (gamestate == GS_WAITINGPLAYERS) - { - // Send PT_NODEKEEPALIVE packet - netbuffer->packettype += 4; - packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); - HSendPacket(servernode, false, 0, packetsize); - } - else if (gamestate != GS_NULL && (addedtogame || dedicated)) - { - G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); - netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); - - // Send a special packet with 2 cmd for splitscreen - if (splitscreen || botingame) - { - netbuffer->packettype += 2; - G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); - packetsize = sizeof (client2cmd_pak); - } - else - packetsize = sizeof (clientcmd_pak); - - HSendPacket(servernode, false, 0, packetsize); - } - - if (cl_mode == CL_CONNECTED || dedicated) - { - // Send extra data if needed - if (localtextcmd[0]) - { - netbuffer->packettype = PT_TEXTCMD; - M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); - // All extra data have been sent - if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... - localtextcmd[0] = 0; - } - - // Send extra data if needed for player 2 (splitscreen) - if (localtextcmd2[0]) - { - netbuffer->packettype = PT_TEXTCMD2; - M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); - // All extra data have been sent - if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... - localtextcmd2[0] = 0; - } - } -} - -// send the server packet -// send tic from firstticstosend to maketic-1 -static void SV_SendTics(void) -{ - tic_t realfirsttic, lasttictosend, i; - UINT32 n; - INT32 j; - size_t packsize; - UINT8 *bufpos; - UINT8 *ntextcmd; - - // send to all client but not to me - // for each node create a packet with x tics and send it - // x is computed using netnodes[n].supposedtic, max packet size and maketic - for (n = 1; n < MAXNETNODES; n++) - if (netnodes[n].ingame) - { - // assert netnodes[n].supposedtic>=netnodes[n].tic - realfirsttic = netnodes[n].supposedtic; - lasttictosend = min(maketic, netnodes[n].tic + CLIENTBACKUPTICS); - - if (realfirsttic >= lasttictosend) - { - // well we have sent all tics we will so use extrabandwidth - // to resent packet that are supposed lost (this is necessary since lost - // packet detection work when we have received packet with firsttic > neededtic - // (getpacket servertics case) - DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, netnodes[n].supposedtic, netnodes[n].tic)); - realfirsttic = netnodes[n].tic; - if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) - // all tic are ok - continue; - DEBFILE(va("Sent %d anyway\n", realfirsttic)); - } - if (realfirsttic < firstticstosend) - realfirsttic = firstticstosend; - - // compute the length of the packet and cut it if too large - packsize = BASESERVERTICSSIZE; - for (i = realfirsttic; i < lasttictosend; i++) - { - packsize += sizeof (ticcmd_t) * doomcom->numslots; - packsize += TotalTextCmdPerTic(i); - - if (packsize > software_MAXPACKETLENGTH) - { - DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", - sizeu1(packsize), i, realfirsttic, lasttictosend)); - lasttictosend = i; - - // too bad: too much player have send extradata and there is too - // much data in one tic. - // To avoid it put the data on the next tic. (see getpacket - // textcmd case) but when numplayer changes the computation can be different - if (lasttictosend == realfirsttic) - { - if (packsize > MAXPACKETLENGTH) - I_Error("Too many players: can't send %s data for %d players to node %d\n" - "Well sorry nobody is perfect....\n", - sizeu1(packsize), doomcom->numslots, n); - else - { - lasttictosend++; // send it anyway! - DEBFILE("sending it anyway\n"); - } - } - break; - } - } - - // Send the tics - netbuffer->packettype = PT_SERVERTICS; - netbuffer->u.serverpak.starttic = realfirsttic; - netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); - netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); - bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realfirsttic; i < lasttictosend; i++) - { - bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); - } - - // add textcmds - for (i = realfirsttic; i < lasttictosend; i++) - { - ntextcmd = bufpos++; - *ntextcmd = 0; - for (j = 0; j < MAXPLAYERS; j++) - { - UINT8 *textcmd = D_GetExistingTextcmd(i, j); - INT32 size = textcmd ? textcmd[0] : 0; - - if ((!j || playeringame[j]) && size) - { - (*ntextcmd)++; - WRITEUINT8(bufpos, j); - M_Memcpy(bufpos, textcmd, size + 1); - bufpos += size + 1; - } - } - } - packsize = bufpos - (UINT8 *)&(netbuffer->u); - - HSendPacket(n, false, 0, packsize); - // when tic are too large, only one tic is sent so don't go backward! - if (lasttictosend-doomcom->extratics > realfirsttic) - netnodes[n].supposedtic = lasttictosend-doomcom->extratics; - else - netnodes[n].supposedtic = lasttictosend; - if (netnodes[n].supposedtic < netnodes[n].tic) netnodes[n].supposedtic = netnodes[n].tic; - } - // node 0 is me! - netnodes[0].supposedtic = maketic; -} - -// -// TryRunTics -// -static void Local_Maketic(INT32 realtics) -{ - I_OsPolling(); // I_Getevent - D_ProcessEvents(); // menu responder, cons responder, - // game responder calls HU_Responder, AM_Responder, - // and G_MapEventsToControls - if (!dedicated) rendergametic = gametic; - // translate inputs (keyboard/mouse/gamepad) into game controls - G_BuildTiccmd(&localcmds, realtics, 1); - if (splitscreen || botingame) - G_BuildTiccmd(&localcmds2, realtics, 2); - - localcmds.angleturn |= TICCMD_RECEIVED; - localcmds2.angleturn |= TICCMD_RECEIVED; -} - -// create missed tic -static void SV_Maketic(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - // We didn't receive this tic - if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) - { - ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; - ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; - - if (players[i].quittime) - { - // Copy the angle/aiming from the previous tic - // and empty the other inputs - memset(ticcmd, 0, sizeof(netcmds[0][0])); - ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED; - ticcmd->aiming = prevticcmd->aiming; - } - else - { - DEBFILE(va("MISS tic%4d for player %d\n", maketic, i)); - // Copy the input from the previous tic - *ticcmd = *prevticcmd; - ticcmd->angleturn &= ~TICCMD_RECEIVED; - } - } - } - - // all tic are now proceed make the next - maketic++; -} +/* +Ping Update except better: +We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. +If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. +*/ boolean TryRunTics(tic_t realtics) { @@ -3049,12 +2197,6 @@ boolean TryRunTics(tic_t realtics) return ticking; } -/* -Ping Update except better: -We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. -If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. -*/ - static INT32 pingtimeout[MAXPLAYERS]; static inline void PingUpdate(void) diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index b8da645ba..8b73170da 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -378,6 +378,7 @@ extern boolean acceptnewnode; extern SINT8 servernode; extern tic_t maketic; extern tic_t neededtic; +extern INT16 consistancy[BACKUPTICS]; void Command_Ping_f(void); extern tic_t connectiontimeout; @@ -391,20 +392,15 @@ extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; // Used in d_net, the only dependence -tic_t ExpandTics(INT32 low, INT32 node); void D_ClientServerInit(void); -// Initialise the other field -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); -void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); -void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player -void SendKick(UINT8 playernum, UINT8 msg); - // Create any new ticcmds and broadcast to other players. void NetUpdate(void); void GetPackets(void); void ResetNode(INT32 node); +INT16 Consistancy(void); +boolean SV_ResendingSavegameToAnyone(void); void SV_StartSinglePlayerServer(void); void SV_SpawnServer(void); @@ -440,10 +436,8 @@ extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); -void D_ResetTiccmds(void); tic_t GetLag(INT32 node); -UINT8 GetFreeXCmdSize(void); void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index ae0605001..972342282 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -26,6 +26,7 @@ #include "../w_wad.h" #include "d_netfil.h" #include "d_clisrv.h" +#include "tic_command.h" #include "../z_zone.h" #include "i_tcp.h" #include "../d_main.h" // srb2home diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index fe4cf22bd..0d1785510 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -37,6 +37,7 @@ #include "../m_cheat.h" #include "d_clisrv.h" #include "server_connection.h" +#include "net_command.h" #include "d_net.h" #include "../v_video.h" #include "../d_main.h" diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 80fa06852..e581be2ac 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -42,6 +42,7 @@ #include "d_net.h" #include "../w_wad.h" #include "d_netfil.h" +#include "net_command.h" #include "../z_zone.h" #include "../byteptr.h" #include "../p_setup.h" diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c new file mode 100644 index 000000000..eeb479d21 --- /dev/null +++ b/src/netcode/net_command.c @@ -0,0 +1,315 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file net_command.c +/// \brief Net command handling + +#include "net_command.h" +#include "tic_command.h" +#include "d_clisrv.h" +#include "i_net.h" +#include "../g_game.h" +#include "../z_zone.h" +#include "../doomtype.h" + +textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; +UINT8 localtextcmd[MAXTEXTCMD]; +UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen +static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); + +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) +{ +#ifdef PARANOIA + if (id >= MAXNETXCMD) + I_Error("Command id %d too big", id); + if (listnetxcmd[id] != 0) + I_Error("Command id %d already used", id); +#endif + listnetxcmd[id] = cmd_f; +} + +void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) +{ + if (localtextcmd[0]+2+nparam > MAXTEXTCMD) + { + // for future reference: if (cv_debug) != debug disabled. + CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam)); + return; + } + localtextcmd[0]++; + localtextcmd[localtextcmd[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd[localtextcmd[0]+1], param, nparam); + localtextcmd[0] = (UINT8)(localtextcmd[0] + (UINT8)nparam); + } +} + +// splitscreen player +void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) +{ + if (localtextcmd2[0]+2+nparam > MAXTEXTCMD) + { + I_Error("No more place in the buffer for netcmd %d\n",id); + return; + } + localtextcmd2[0]++; + localtextcmd2[localtextcmd2[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd2[localtextcmd2[0]+1], param, nparam); + localtextcmd2[0] = (UINT8)(localtextcmd2[0] + (UINT8)nparam); + } +} + +UINT8 GetFreeXCmdSize(void) +{ + // -1 for the size and another -1 for the ID. + return (UINT8)(localtextcmd[0] - 2); +} + +// Frees all textcmd memory for the specified tic +void D_FreeTextcmd(tic_t tic) +{ + textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdtic_t *textcmdtic = *tctprev; + + while (textcmdtic && textcmdtic->tic != tic) + { + tctprev = &textcmdtic->next; + textcmdtic = textcmdtic->next; + } + + if (textcmdtic) + { + INT32 i; + + // Remove this tic from the list. + *tctprev = textcmdtic->next; + + // Free all players. + for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + { + textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; + + while (textcmdplayer) + { + textcmdplayer_t *tcpnext = textcmdplayer->next; + Z_Free(textcmdplayer); + textcmdplayer = tcpnext; + } + } + + // Free this tic's own memory. + Z_Free(textcmdtic); + } +} + +// Gets the buffer for the specified ticcmd, or NULL if there isn't one +UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) +{ + textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + while (textcmdtic && textcmdtic->tic != tic) textcmdtic = textcmdtic->next; + + // Do we have an entry for the tic? If so, look for player. + if (textcmdtic) + { + textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; + while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; + + if (textcmdplayer) return textcmdplayer->cmd; + } + + return NULL; +} + +// Gets the buffer for the specified ticcmd, creating one if necessary +UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) +{ + textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdplayer_t *textcmdplayer, **tcpprev; + + // Look for the tic. + while (textcmdtic && textcmdtic->tic != tic) + { + tctprev = &textcmdtic->next; + textcmdtic = textcmdtic->next; + } + + // If we don't have an entry for the tic, make it. + if (!textcmdtic) + { + textcmdtic = *tctprev = Z_Calloc(sizeof (textcmdtic_t), PU_STATIC, NULL); + textcmdtic->tic = tic; + } + + tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; + textcmdplayer = *tcpprev; + + // Look for the player. + while (textcmdplayer && textcmdplayer->playernum != playernum) + { + tcpprev = &textcmdplayer->next; + textcmdplayer = textcmdplayer->next; + } + + // If we don't have an entry for the player, make it. + if (!textcmdplayer) + { + textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL); + textcmdplayer->playernum = playernum; + } + + return textcmdplayer->cmd; +} + +void ExtraDataTicker(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] || i == 0) + { + UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); + + if (bufferstart) + { + UINT8 *curpos = bufferstart; + UINT8 *bufferend = &curpos[curpos[0]+1]; + + curpos++; + while (curpos < bufferend) + { + if (*curpos < MAXNETXCMD && listnetxcmd[*curpos]) + { + const UINT8 id = *curpos; + curpos++; + DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i)); + (listnetxcmd[id])(&curpos, i); + DEBFILE("done\n"); + } + else + { + if (server) + { + SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); + } + CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); + break; + } + } + } + } + + // If you are a client, you can safely forget the net commands for this tic + // If you are the server, you need to remember them until every client has been acknowledged, + // because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it + if (client) + D_FreeTextcmd(gametic); +} + +// used at txtcmds received to check packetsize bound +size_t TotalTextCmdPerTic(tic_t tic) +{ + INT32 i; + size_t total = 1; // num of textcmds in the tic (ntextcmd byte) + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT8 *textcmd = D_GetExistingTextcmd(tic, i); + if ((!i || playeringame[i]) && textcmd) + total += 2 + textcmd[0]; // "+2" for size and playernum + } + + return total; +} + +void PT_TextCmd(SINT8 node, INT32 netconsole) +{ + if (client) + return; + + // splitscreen special + if (netbuffer->packettype == PT_TEXTCMD2) + netconsole = netnodes[node].player2; + + if (netconsole < 0 || netconsole >= MAXPLAYERS) + Net_UnAcknowledgePacket(node); + else + { + size_t j; + tic_t tic = maketic; + UINT8 *textcmd; + + // ignore if the textcmd has a reported size of zero + // this shouldn't be sent at all + if (!netbuffer->u.textcmd[0]) + { + DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // ignore if the textcmd size var is actually larger than it should be + // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) + { + DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // check if tic that we are making isn't too large else we cannot send it :( + // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time + j = software_MAXPACKETLENGTH + - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + + (doomcom->numslots+1)*sizeof(ticcmd_t)); + + // search a tic that have enougth space in the ticcmd + while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), + (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) + && tic < firstticstosend + BACKUPTICS) + tic++; + + if (tic >= firstticstosend + BACKUPTICS) + { + DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " + "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), + maketic, firstticstosend, node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // Make sure we have a buffer + if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); + + DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", + tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); + + M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; + } +} + +void SendKick(UINT8 playernum, UINT8 msg) +{ + UINT8 buf[2]; + + if (!(server && cv_rejointimeout.value)) + msg &= ~KICK_MSG_KEEP_BODY; + + buf[0] = playernum; + buf[1] = msg; + SendNetXCmd(XD_KICK, &buf, 2); +} diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h new file mode 100644 index 000000000..1fc5035c8 --- /dev/null +++ b/src/netcode/net_command.h @@ -0,0 +1,62 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file net_command.h +/// \brief Net command handling + +#ifndef __D_NET_COMMAND__ +#define __D_NET_COMMAND__ + +#include "d_clisrv.h" +#include "../doomtype.h" + +// Must be a power of two +#define TEXTCMD_HASH_SIZE 4 + +typedef struct textcmdplayer_s +{ + INT32 playernum; + UINT8 cmd[MAXTEXTCMD]; + struct textcmdplayer_s *next; +} textcmdplayer_t; + +typedef struct textcmdtic_s +{ + tic_t tic; + textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; + struct textcmdtic_s *next; +} textcmdtic_t; + +extern textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE]; + +extern UINT8 localtextcmd[MAXTEXTCMD]; +extern UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen + +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); +void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); +void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player + +UINT8 GetFreeXCmdSize(void); +void D_FreeTextcmd(tic_t tic); + +// Gets the buffer for the specified ticcmd, or NULL if there isn't one +UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum); + +// Gets the buffer for the specified ticcmd, creating one if necessary +UINT8* D_GetTextcmd(tic_t tic, INT32 playernum); + +void ExtraDataTicker(void); + +// used at txtcmds received to check packetsize bound +size_t TotalTextCmdPerTic(tic_t tic); + +void PT_TextCmd(SINT8 node, INT32 netconsole); +void SendKick(UINT8 playernum, UINT8 msg); + +#endif diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index 9e397b0f3..b776db422 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -15,6 +15,7 @@ #include "d_clisrv.h" #include "d_netfil.h" #include "mserv.h" +#include "net_command.h" #include "../byteptr.h" #include "../g_game.h" #include "../g_state.h" diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c new file mode 100644 index 000000000..e7df895ff --- /dev/null +++ b/src/netcode/tic_command.c @@ -0,0 +1,504 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file tic_command.c +/// \brief Tic command handling + +#include "tic_command.h" +#include "d_clisrv.h" +#include "net_command.h" +#include "client_connection.h" +#include "i_net.h" +#include "../d_main.h" +#include "../g_game.h" +#include "../i_system.h" +#include "../i_time.h" +#include "../byteptr.h" +#include "../doomstat.h" +#include "../doomtype.h" + +tic_t firstticstosend; // min of the nettics +tic_t tictoclear = 0; // optimize d_clearticcmd +ticcmd_t localcmds; +ticcmd_t localcmds2; +boolean cl_packetmissed; +ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; + +static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) +{ + const size_t d = n / sizeof(ticcmd_t); + const size_t r = n % sizeof(ticcmd_t); + UINT8 *ret = dest; + + if (r) + M_Memcpy(dest, src, n); + else if (d) + G_MoveTiccmd(dest, src, d); + return ret+n; +} + +static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n) +{ + const size_t d = n / sizeof(ticcmd_t); + const size_t r = n % sizeof(ticcmd_t); + UINT8 *ret = src; + + if (r) + M_Memcpy(dest, src, n); + else if (d) + G_MoveTiccmd(dest, src, d); + return ret+n; +} + +/** Guesses the full value of a tic from its lowest byte, for a specific node + * + * \param low The lowest byte of the tic value + * \param node The node to deduce the tic for + * \return The full tic value + * + */ +tic_t ExpandTics(INT32 low, INT32 node) +{ + INT32 delta; + + delta = low - (netnodes[node].tic & UINT8_MAX); + + if (delta >= -64 && delta <= 64) + return (netnodes[node].tic & ~UINT8_MAX) + low; + else if (delta > 64) + return (netnodes[node].tic & ~UINT8_MAX) - 256 + low; + else //if (delta < -64) + return (netnodes[node].tic & ~UINT8_MAX) + 256 + low; +} + +void D_Clearticcmd(tic_t tic) +{ + INT32 i; + + D_FreeTextcmd(tic); + + for (i = 0; i < MAXPLAYERS; i++) + netcmds[tic%BACKUPTICS][i].angleturn = 0; + + DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); +} + +void D_ResetTiccmds(void) +{ + INT32 i; + + memset(&localcmds, 0, sizeof(ticcmd_t)); + memset(&localcmds2, 0, sizeof(ticcmd_t)); + + // Reset the net command list + for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + while (textcmds[i]) + D_Clearticcmd(textcmds[i]->tic); +} + +void PT_ClientCmd(SINT8 node, INT32 netconsole) +{ + tic_t realend, realstart; + + if (client) + return; + + // To save bytes, only the low byte of tic numbers are sent + // Use ExpandTics to figure out what the rest of the bytes are + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); + + if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS + || netbuffer->packettype == PT_NODEKEEPALIVEMIS + || netnodes[node].supposedtic < realend) + { + netnodes[node].supposedtic = realend; + } + // Discard out of order packet + if (netnodes[node].tic > realend) + { + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", netnodes[node].tic)); + return; + } + + // Update the nettics + netnodes[node].tic = realend; + + // Don't do anything for packets of type NODEKEEPALIVE? + if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + return; + + // As long as clients send valid ticcmds, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + netnodes[node].freezetimeout = I_GetTime() + connectiontimeout; + + // Copy ticcmd + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + + // Check ticcmd for "speed hacks" + if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE + || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); + //D_Clearticcmd(k); + + SendKick(netconsole, KICK_MSG_CON_FAIL); + return; + } + + // Splitscreen cmd + if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) + && netnodes[node].player2 >= 0) + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)netnodes[node].player2], + &netbuffer->u.client2pak.cmd2, 1); + + // Check player consistancy during the level + if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL + && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) + && !SV_ResendingSavegameToAnyone() + && !netnodes[node].resendingsavegame && netnodes[node].savegameresendcooldown <= I_GetTime()) + { + if (cv_resynchattempts.value) + { + // Tell the client we are about to resend them the gamestate + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + HSendPacket(node, true, 0, 0); + + netnodes[node].resendingsavegame = true; + + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + return; + } + else + { + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + return; + } + } +} + +void PT_ServerTics(SINT8 node, INT32 netconsole) +{ + UINT8 *pak, *txtpak, numtxtpak; + tic_t realend, realstart; + + if (!netnodes[node].ingame) + { + // Do not remove my own server (we have just get a out of order packet) + if (node != servernode) + { + DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); + Net_CloseConnection(node); + } + return; + } + + // Only accept PT_SERVERTICS from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + realstart = netbuffer->u.serverpak.starttic; + realend = realstart + netbuffer->u.serverpak.numtics; + + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; + + if (realend > gametic + CLIENTBACKUPTICS) + realend = gametic + CLIENTBACKUPTICS; + cl_packetmissed = realstart > neededtic; + + if (realstart <= neededtic && realend > neededtic) + { + tic_t i, j; + pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realstart; i < realend; i++) + { + // clear first + D_Clearticcmd(i); + + // copy the tics + pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + + // copy the textcmds + numtxtpak = *txtpak++; + for (j = 0; j < numtxtpak; j++) + { + INT32 k = *txtpak++; // playernum + const size_t txtsize = txtpak[0]+1; + + if (i >= gametic) // Don't copy old net commands + M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); + txtpak += txtsize; + } + } + + neededtic = realend; + } + else + { + DEBFILE(va("frame not in bound: %u\n", neededtic)); + /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) + I_Error("Received an out of order PT_SERVERTICS packet!\n" + "Got tics %d-%d, needed tic %d\n\n" + "Please report this crash on the Master Board,\n" + "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ + } +} + +// send the client packet to the server +void CL_SendClientCmd(void) +{ + size_t packetsize = 0; + + netbuffer->packettype = PT_CLIENTCMD; + + if (cl_packetmissed) + netbuffer->packettype++; + netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX); + netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX); + + if (gamestate == GS_WAITINGPLAYERS) + { + // Send PT_NODEKEEPALIVE packet + netbuffer->packettype += 4; + packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); + HSendPacket(servernode, false, 0, packetsize); + } + else if (gamestate != GS_NULL && (addedtogame || dedicated)) + { + G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); + netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); + + // Send a special packet with 2 cmd for splitscreen + if (splitscreen || botingame) + { + netbuffer->packettype += 2; + G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + packetsize = sizeof (client2cmd_pak); + } + else + packetsize = sizeof (clientcmd_pak); + + HSendPacket(servernode, false, 0, packetsize); + } + + if (cl_mode == CL_CONNECTED || dedicated) + { + // Send extra data if needed + if (localtextcmd[0]) + { + netbuffer->packettype = PT_TEXTCMD; + M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... + localtextcmd[0] = 0; + } + + // Send extra data if needed for player 2 (splitscreen) + if (localtextcmd2[0]) + { + netbuffer->packettype = PT_TEXTCMD2; + M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... + localtextcmd2[0] = 0; + } + } +} + +// send the server packet +// send tic from firstticstosend to maketic-1 +void SV_SendTics(void) +{ + tic_t realfirsttic, lasttictosend, i; + UINT32 n; + INT32 j; + size_t packsize; + UINT8 *bufpos; + UINT8 *ntextcmd; + + // send to all client but not to me + // for each node create a packet with x tics and send it + // x is computed using netnodes[n].supposedtic, max packet size and maketic + for (n = 1; n < MAXNETNODES; n++) + if (netnodes[n].ingame) + { + // assert netnodes[n].supposedtic>=netnodes[n].tic + realfirsttic = netnodes[n].supposedtic; + lasttictosend = min(maketic, netnodes[n].tic + CLIENTBACKUPTICS); + + if (realfirsttic >= lasttictosend) + { + // well we have sent all tics we will so use extrabandwidth + // to resent packet that are supposed lost (this is necessary since lost + // packet detection work when we have received packet with firsttic > neededtic + // (getpacket servertics case) + DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", + n, maketic, netnodes[n].supposedtic, netnodes[n].tic)); + realfirsttic = netnodes[n].tic; + if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) + // all tic are ok + continue; + DEBFILE(va("Sent %d anyway\n", realfirsttic)); + } + if (realfirsttic < firstticstosend) + realfirsttic = firstticstosend; + + // compute the length of the packet and cut it if too large + packsize = BASESERVERTICSSIZE; + for (i = realfirsttic; i < lasttictosend; i++) + { + packsize += sizeof (ticcmd_t) * doomcom->numslots; + packsize += TotalTextCmdPerTic(i); + + if (packsize > software_MAXPACKETLENGTH) + { + DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", + sizeu1(packsize), i, realfirsttic, lasttictosend)); + lasttictosend = i; + + // too bad: too much player have send extradata and there is too + // much data in one tic. + // To avoid it put the data on the next tic. (see getpacket + // textcmd case) but when numplayer changes the computation can be different + if (lasttictosend == realfirsttic) + { + if (packsize > MAXPACKETLENGTH) + I_Error("Too many players: can't send %s data for %d players to node %d\n" + "Well sorry nobody is perfect....\n", + sizeu1(packsize), doomcom->numslots, n); + else + { + lasttictosend++; // send it anyway! + DEBFILE("sending it anyway\n"); + } + } + break; + } + } + + // Send the tics + netbuffer->packettype = PT_SERVERTICS; + netbuffer->u.serverpak.starttic = realfirsttic; + netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); + netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); + bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realfirsttic; i < lasttictosend; i++) + { + bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); + } + + // add textcmds + for (i = realfirsttic; i < lasttictosend; i++) + { + ntextcmd = bufpos++; + *ntextcmd = 0; + for (j = 0; j < MAXPLAYERS; j++) + { + UINT8 *textcmd = D_GetExistingTextcmd(i, j); + INT32 size = textcmd ? textcmd[0] : 0; + + if ((!j || playeringame[j]) && size) + { + (*ntextcmd)++; + WRITEUINT8(bufpos, j); + M_Memcpy(bufpos, textcmd, size + 1); + bufpos += size + 1; + } + } + } + packsize = bufpos - (UINT8 *)&(netbuffer->u); + + HSendPacket(n, false, 0, packsize); + // when tic are too large, only one tic is sent so don't go backward! + if (lasttictosend-doomcom->extratics > realfirsttic) + netnodes[n].supposedtic = lasttictosend-doomcom->extratics; + else + netnodes[n].supposedtic = lasttictosend; + if (netnodes[n].supposedtic < netnodes[n].tic) netnodes[n].supposedtic = netnodes[n].tic; + } + // node 0 is me! + netnodes[0].supposedtic = maketic; +} + +// +// TryRunTics +// +void Local_Maketic(INT32 realtics) +{ + I_OsPolling(); // I_Getevent + D_ProcessEvents(); // menu responder, cons responder, + // game responder calls HU_Responder, AM_Responder, + // and G_MapEventsToControls + if (!dedicated) rendergametic = gametic; + // translate inputs (keyboard/mouse/gamepad) into game controls + G_BuildTiccmd(&localcmds, realtics, 1); + if (splitscreen || botingame) + G_BuildTiccmd(&localcmds2, realtics, 2); + + localcmds.angleturn |= TICCMD_RECEIVED; + localcmds2.angleturn |= TICCMD_RECEIVED; +} + +// create missed tic +void SV_Maketic(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + // We didn't receive this tic + if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) + { + ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; + ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; + + if (players[i].quittime) + { + // Copy the angle/aiming from the previous tic + // and empty the other inputs + memset(ticcmd, 0, sizeof(netcmds[0][0])); + ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED; + ticcmd->aiming = prevticcmd->aiming; + } + else + { + DEBFILE(va("MISS tic%4d for player %d\n", maketic, i)); + // Copy the input from the previous tic + *ticcmd = *prevticcmd; + ticcmd->angleturn &= ~TICCMD_RECEIVED; + } + } + } + + // all tic are now proceed make the next + maketic++; +} diff --git a/src/netcode/tic_command.h b/src/netcode/tic_command.h new file mode 100644 index 000000000..d19f4c1aa --- /dev/null +++ b/src/netcode/tic_command.h @@ -0,0 +1,44 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file tic_command.h +/// \brief Tic command handling + +#ifndef __D_TIC_COMMAND__ +#define __D_TIC_COMMAND__ + +#include "d_clisrv.h" +#include "../d_ticcmd.h" +#include "../doomdef.h" +#include "../doomtype.h" + +extern tic_t firstticstosend; // min of the nettics +extern tic_t tictoclear; // optimize d_clearticcmd + +extern ticcmd_t localcmds; +extern ticcmd_t localcmds2; +extern boolean cl_packetmissed; + +extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; + +tic_t ExpandTics(INT32 low, INT32 node); +void D_Clearticcmd(tic_t tic); +void D_ResetTiccmds(void); + +void PT_ClientCmd(SINT8 node, INT32 netconsole); +void PT_ServerTics(SINT8 node, INT32 netconsole); + +// send the client packet to the server +void CL_SendClientCmd(void); + +void SV_SendTics(void); +void Local_Maketic(INT32 realtics); +void SV_Maketic(void); + +#endif diff --git a/src/p_inter.c b/src/p_inter.c index 4d22ba343..490065a1f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -28,6 +28,7 @@ #include "m_misc.h" #include "v_video.h" // video flags for CEchos #include "f_finale.h" +#include "netcode/net_command.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" diff --git a/src/p_mobj.c b/src/p_mobj.c index 4ca59285f..807368890 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -36,6 +36,7 @@ #include "p_slopes.h" #include "f_finale.h" #include "m_cond.h" +#include "netcode/net_command.h" static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); diff --git a/src/p_setup.c b/src/p_setup.c index 175ab3328..4dc37d667 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -87,6 +87,8 @@ #include "taglist.h" +#include "netcode/net_command.h" + // // Map MD5, calculated on level load. // Sent to clients in PT_SERVERINFO. diff --git a/src/p_tick.c b/src/p_tick.c index b1fd367ed..4b724e333 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -26,6 +26,7 @@ #include "r_main.h" #include "r_fps.h" #include "i_video.h" // rendermode +#include "netcode/net_command.h" // Object place #include "m_cheat.h" diff --git a/src/p_user.c b/src/p_user.c index 6bbefcb19..c8657f8c5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -18,6 +18,7 @@ #include "i_system.h" #include "d_event.h" #include "netcode/d_net.h" +#include "netcode/net_command.h" #include "g_game.h" #include "p_local.h" #include "r_fps.h" From 1a7f42d172e3ec4c68003988436b4c15ef23e765 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 5 Jan 2023 23:48:44 +0100 Subject: [PATCH 40/93] Declare data exchanged through the network to a new file --- src/netcode/d_clisrv.c | 1 + src/netcode/d_clisrv.h | 313 +------------------------------------- src/netcode/d_net.h | 2 + src/netcode/protocol.h | 335 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+), 312 deletions(-) create mode 100644 src/netcode/protocol.h diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 06e6da751..b834c92f5 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -53,6 +53,7 @@ #include "client_connection.h" #include "tic_command.h" #include "net_command.h" +#include "protocol.h" // // NETWORKING diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 8b73170da..691a2787f 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -13,6 +13,7 @@ #ifndef __D_CLISRV__ #define __D_CLISRV__ +#include "protocol.h" #include "../d_ticcmd.h" #include "d_net.h" #include "d_netcmd.h" @@ -21,85 +22,7 @@ #include "../d_player.h" #include "mserv.h" -/* -The 'packet version' is used to distinguish packet -formats. This version is independent of VERSION and -SUBVERSION. Different applications may follow different -packet versions. - -If you change the struct or the meaning of a field -therein, increment this number. -*/ -#define PACKETVERSION 4 - -// Network play related stuff. -// There is a data struct that stores network -// communication related stuff, and another -// one that defines the actual packets to -// be transmitted. - -// Networking and tick handling related. -#define BACKUPTICS 1024 #define CLIENTBACKUPTICS 32 -#define MAXTEXTCMD 256 -// -// Packet structure -// -typedef enum -{ - PT_NOTHING, // To send a nop through the network. ^_~ - PT_SERVERCFG, // Server config used in start game - // (must stay 1 for backwards compatibility). - // This is a positive response to a CLIENTJOIN request. - PT_CLIENTCMD, // Ticcmd of the client. - PT_CLIENTMIS, // Same as above with but saying resend from. - PT_CLIENT2CMD, // 2 cmds in the packet for splitscreen. - PT_CLIENT2MIS, // Same as above with but saying resend from - PT_NODEKEEPALIVE, // Same but without ticcmd and consistancy - PT_NODEKEEPALIVEMIS, - PT_SERVERTICS, // All cmds for the tic. - PT_SERVERREFUSE, // Server refuses joiner (reason inside). - PT_SERVERSHUTDOWN, - PT_CLIENTQUIT, // Client closes the connection. - - PT_ASKINFO, // Anyone can ask info of the server. - PT_SERVERINFO, // Send game & server info (gamespy). - PT_PLAYERINFO, // Send information for players in game (gamespy). - PT_REQUESTFILE, // Client requests a file transfer - PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. - // If this ID changes, update masterserver definition. - - PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate! - PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead. - PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again! - - PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file - PT_ASKLUAFILE, // Client telling the server they don't have the file - PT_HASLUAFILE, // Client telling the server they have the file - - // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. - - PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL - // allows HSendPacket(*, true, *, *) to return false. - // In addition, this packet can't occupy all the available slots. - - PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file. - PT_FILEACK, - PT_FILERECEIVED, - - PT_TEXTCMD, // Extra text commands from the client. - PT_TEXTCMD2, // Splitscreen text commands. - PT_CLIENTJOIN, // Client wants to join; used in start game. - PT_NODETIMEOUT, // Packet sent to self if the connection times out. - - PT_LOGIN, // Login attempt from the client. - - PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" - PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" - - PT_PING, // Packet sent to tell clients the other client's latency to server. - NUMPACKETTYPE -} packettype_t; #ifdef PACKETDROP void Command_Drop(void); @@ -109,229 +32,6 @@ void Command_Droprate(void); void Command_Numnodes(void); #endif -#if defined(_MSC_VER) -#pragma pack(1) -#endif - -// Client to server packet -typedef struct -{ - UINT8 client_tic; - UINT8 resendfrom; - INT16 consistancy; - ticcmd_t cmd; -} ATTRPACK clientcmd_pak; - -// Splitscreen packet -// WARNING: must have the same format of clientcmd_pak, for more easy use -typedef struct -{ - UINT8 client_tic; - UINT8 resendfrom; - INT16 consistancy; - ticcmd_t cmd, cmd2; -} ATTRPACK client2cmd_pak; - -#ifdef _MSC_VER -#pragma warning(disable : 4200) -#endif - -// Server to client packet -// this packet is too large -typedef struct -{ - tic_t starttic; - UINT8 numtics; - UINT8 numslots; // "Slots filled": Highest player number in use plus one. - ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large -} ATTRPACK servertics_pak; - -typedef struct -{ - // Server launch stuffs - UINT8 serverplayer; - UINT8 totalslotnum; // "Slots": highest player number in use plus one. - - tic_t gametic; - UINT8 clientnode; - UINT8 gamestate; - - UINT8 gametype; - UINT8 modifiedgame; - - char server_context[8]; // Unique context id, generated at server startup. -} ATTRPACK serverconfig_pak; - -typedef struct -{ - UINT8 fileid; - UINT32 filesize; - UINT8 iteration; - UINT32 position; - UINT16 size; - UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH -} ATTRPACK filetx_pak; - -typedef struct -{ - UINT32 start; - UINT32 acks; -} ATTRPACK fileacksegment_t; - -typedef struct -{ - UINT8 fileid; - UINT8 iteration; - UINT8 numsegments; - fileacksegment_t segments[0]; -} ATTRPACK fileack_pak; - -#ifdef _MSC_VER -#pragma warning(default : 4200) -#endif - -#define MAXAPPLICATION 16 - -typedef struct -{ - UINT8 modversion; - char application[MAXAPPLICATION]; - UINT8 localplayers; - UINT8 mode; - char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; -} ATTRPACK clientconfig_pak; - -#define SV_DEDICATED 0x40 // server is dedicated -#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil - -enum { - REFUSE_JOINS_DISABLED = 1, - REFUSE_SLOTS_FULL, - REFUSE_BANNED, -}; - -#define MAXSERVERNAME 32 -#define MAXFILENEEDED 915 -// This packet is too large -typedef struct -{ - /* - In the old packet, 'version' is the first field. Now that field is set - to 255 always, so older versions won't be confused with the new - versions or vice-versa. - */ - UINT8 _255; - UINT8 packetversion; - char application[MAXAPPLICATION]; - UINT8 version; - UINT8 subversion; - UINT8 numberofplayer; - UINT8 maxplayer; - UINT8 refusereason; // 0: joinable, REFUSE enum - char gametypename[24]; - UINT8 modifiedgame; - UINT8 cheatsenabled; - UINT8 flags; - UINT8 fileneedednum; - tic_t time; - tic_t leveltime; - char servername[MAXSERVERNAME]; - char mapname[8]; - char maptitle[33]; - unsigned char mapmd5[16]; - UINT8 actnum; - UINT8 iszone; - UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) -} ATTRPACK serverinfo_pak; - -typedef struct -{ - char reason[255]; -} ATTRPACK serverrefuse_pak; - -typedef struct -{ - UINT8 version; - tic_t time; // used for ping evaluation -} ATTRPACK askinfo_pak; - -typedef struct -{ - char clientaddr[22]; - tic_t time; // used for ping evaluation -} ATTRPACK msaskinfo_pak; - -// Shorter player information for external use. -typedef struct -{ - UINT8 num; - char name[MAXPLAYERNAME+1]; - UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH - UINT8 team; - UINT8 skin; - UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused. - UINT32 score; - UINT16 timeinserver; // In seconds. -} ATTRPACK plrinfo; - -// Shortest player information for join during intermission. -typedef struct -{ - char name[MAXPLAYERNAME+1]; - UINT8 skin; - UINT16 color; - UINT32 pflags; - UINT32 score; - UINT8 ctfteam; -} ATTRPACK plrconfig; - -typedef struct -{ - INT32 first; - UINT8 num; - UINT8 more; - UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) -} ATTRPACK filesneededconfig_pak; - -// -// Network packet data -// -typedef struct -{ - UINT32 checksum; - UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack - UINT8 ackreturn; // The return of the ack number - - UINT8 packettype; - UINT8 reserved; // Padding - union - { - clientcmd_pak clientpak; // 144 bytes - client2cmd_pak client2pak; // 200 bytes - servertics_pak serverpak; // 132495 bytes (more around 360, no?) - serverconfig_pak servercfg; // 773 bytes - UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) - filetx_pak filetxpak; // 139 bytes - fileack_pak fileack; - UINT8 filereceived; - clientconfig_pak clientcfg; // 136 bytes - UINT8 md5sum[16]; - serverinfo_pak serverinfo; // 1024 bytes - serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) - askinfo_pak askinfo; // 61 bytes - msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) - plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) - INT32 filesneedednum; // 4 bytes - filesneededconfig_pak filesneededcfg; // ??? bytes - UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes - } u; // This is needed to pack diff packet types data together -} ATTRPACK doomdata_t; - -#if defined(_MSC_VER) -#pragma pack() -#endif - extern INT32 mapchangepending; // Points inside doomcom @@ -341,19 +41,8 @@ extern consvar_t cv_showjoinaddress; extern consvar_t cv_playbackspeed; #define BASEPACKETSIZE offsetof(doomdata_t, u) -#define FILETXHEADER offsetof(filetx_pak, data) #define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0]) -#define KICK_MSG_GO_AWAY 1 -#define KICK_MSG_CON_FAIL 2 -#define KICK_MSG_PLAYER_QUIT 3 -#define KICK_MSG_TIMEOUT 4 -#define KICK_MSG_BANNED 5 -#define KICK_MSG_PING_HIGH 6 -#define KICK_MSG_CUSTOM_KICK 7 -#define KICK_MSG_CUSTOM_BAN 8 -#define KICK_MSG_KEEP_BODY 0x80 - typedef enum { KR_KICK = 1, //Kicked by server diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h index 803b49d74..857c3463c 100644 --- a/src/netcode/d_net.h +++ b/src/netcode/d_net.h @@ -18,6 +18,8 @@ #ifndef __D_NET__ #define __D_NET__ +#include "../doomtype.h" + // Max computers in a game // 127 is probably as high as this can go, because // SINT8 is used for nodes sometimes >:( diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h new file mode 100644 index 000000000..566d10d8c --- /dev/null +++ b/src/netcode/protocol.h @@ -0,0 +1,335 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file protocol.h +/// \brief Data exchanged through the network + +#ifndef __PROTOCOL__ +#define __PROTOCOL__ + +#include "d_net.h" +#include "../d_ticcmd.h" +#include "../doomdef.h" + +/* +The 'packet version' is used to distinguish packet +formats. This version is independent of VERSION and +SUBVERSION. Different applications may follow different +packet versions. + +If you change the struct or the meaning of a field +therein, increment this number. +*/ +#define PACKETVERSION 4 + +// Network play related stuff. +// There is a data struct that stores network +// communication related stuff, and another +// one that defines the actual packets to +// be transmitted. + +#define BACKUPTICS 1024 +#define MAXTEXTCMD 256 + +// +// Packet structure +// +typedef enum +{ + PT_NOTHING, // To send a nop through the network. ^_~ + PT_SERVERCFG, // Server config used in start game + // (must stay 1 for backwards compatibility). + // This is a positive response to a CLIENTJOIN request. + PT_CLIENTCMD, // Ticcmd of the client. + PT_CLIENTMIS, // Same as above with but saying resend from. + PT_CLIENT2CMD, // 2 cmds in the packet for splitscreen. + PT_CLIENT2MIS, // Same as above with but saying resend from + PT_NODEKEEPALIVE, // Same but without ticcmd and consistancy + PT_NODEKEEPALIVEMIS, + PT_SERVERTICS, // All cmds for the tic. + PT_SERVERREFUSE, // Server refuses joiner (reason inside). + PT_SERVERSHUTDOWN, + PT_CLIENTQUIT, // Client closes the connection. + + PT_ASKINFO, // Anyone can ask info of the server. + PT_SERVERINFO, // Send game & server info (gamespy). + PT_PLAYERINFO, // Send information for players in game (gamespy). + PT_REQUESTFILE, // Client requests a file transfer + PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. + // If this ID changes, update masterserver definition. + + PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate! + PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead. + PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again! + + PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file + PT_ASKLUAFILE, // Client telling the server they don't have the file + PT_HASLUAFILE, // Client telling the server they have the file + + // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. + + PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL + // allows HSendPacket(*, true, *, *) to return false. + // In addition, this packet can't occupy all the available slots. + + PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file. + PT_FILEACK, + PT_FILERECEIVED, + + PT_TEXTCMD, // Extra text commands from the client. + PT_TEXTCMD2, // Splitscreen text commands. + PT_CLIENTJOIN, // Client wants to join; used in start game. + PT_NODETIMEOUT, // Packet sent to self if the connection times out. + + PT_LOGIN, // Login attempt from the client. + + PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" + PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" + + PT_PING, // Packet sent to tell clients the other client's latency to server. + NUMPACKETTYPE +} packettype_t; + +#if defined(_MSC_VER) +#pragma pack(1) +#endif + +// Client to server packet +typedef struct +{ + UINT8 client_tic; + UINT8 resendfrom; + INT16 consistancy; + ticcmd_t cmd; +} ATTRPACK clientcmd_pak; + +// Splitscreen packet +// WARNING: must have the same format of clientcmd_pak, for more easy use +typedef struct +{ + UINT8 client_tic; + UINT8 resendfrom; + INT16 consistancy; + ticcmd_t cmd, cmd2; +} ATTRPACK client2cmd_pak; + +#ifdef _MSC_VER +#pragma warning(disable : 4200) +#endif + +// Server to client packet +// this packet is too large +typedef struct +{ + tic_t starttic; + UINT8 numtics; + UINT8 numslots; // "Slots filled": Highest player number in use plus one. + ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large +} ATTRPACK servertics_pak; + +typedef struct +{ + // Server launch stuffs + UINT8 serverplayer; + UINT8 totalslotnum; // "Slots": highest player number in use plus one. + + tic_t gametic; + UINT8 clientnode; + UINT8 gamestate; + + UINT8 gametype; + UINT8 modifiedgame; + + char server_context[8]; // Unique context id, generated at server startup. +} ATTRPACK serverconfig_pak; + +typedef struct +{ + UINT8 fileid; + UINT32 filesize; + UINT8 iteration; + UINT32 position; + UINT16 size; + UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH +} ATTRPACK filetx_pak; + +typedef struct +{ + UINT32 start; + UINT32 acks; +} ATTRPACK fileacksegment_t; + +typedef struct +{ + UINT8 fileid; + UINT8 iteration; + UINT8 numsegments; + fileacksegment_t segments[0]; +} ATTRPACK fileack_pak; + +#ifdef _MSC_VER +#pragma warning(default : 4200) +#endif + +#define MAXAPPLICATION 16 + +typedef struct +{ + UINT8 modversion; + char application[MAXAPPLICATION]; + UINT8 localplayers; + UINT8 mode; + char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; +} ATTRPACK clientconfig_pak; + +#define SV_DEDICATED 0x40 // server is dedicated +#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil + +enum { + REFUSE_JOINS_DISABLED = 1, + REFUSE_SLOTS_FULL, + REFUSE_BANNED, +}; + +#define MAXSERVERNAME 32 +#define MAXFILENEEDED 915 + +// This packet is too large +typedef struct +{ + /* + In the old packet, 'version' is the first field. Now that field is set + to 255 always, so older versions won't be confused with the new + versions or vice-versa. + */ + UINT8 _255; + UINT8 packetversion; + char application[MAXAPPLICATION]; + UINT8 version; + UINT8 subversion; + UINT8 numberofplayer; + UINT8 maxplayer; + UINT8 refusereason; // 0: joinable, REFUSE enum + char gametypename[24]; + UINT8 modifiedgame; + UINT8 cheatsenabled; + UINT8 flags; + UINT8 fileneedednum; + tic_t time; + tic_t leveltime; + char servername[MAXSERVERNAME]; + char mapname[8]; + char maptitle[33]; + unsigned char mapmd5[16]; + UINT8 actnum; + UINT8 iszone; + UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) +} ATTRPACK serverinfo_pak; + +typedef struct +{ + char reason[255]; +} ATTRPACK serverrefuse_pak; + +typedef struct +{ + UINT8 version; + tic_t time; // used for ping evaluation +} ATTRPACK askinfo_pak; + +typedef struct +{ + char clientaddr[22]; + tic_t time; // used for ping evaluation +} ATTRPACK msaskinfo_pak; + +// Shorter player information for external use. +typedef struct +{ + UINT8 num; + char name[MAXPLAYERNAME+1]; + UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH + UINT8 team; + UINT8 skin; + UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused. + UINT32 score; + UINT16 timeinserver; // In seconds. +} ATTRPACK plrinfo; + +// Shortest player information for join during intermission. +typedef struct +{ + char name[MAXPLAYERNAME+1]; + UINT8 skin; + UINT16 color; + UINT32 pflags; + UINT32 score; + UINT8 ctfteam; +} ATTRPACK plrconfig; + +typedef struct +{ + INT32 first; + UINT8 num; + UINT8 more; + UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) +} ATTRPACK filesneededconfig_pak; + +// +// Network packet data +// +typedef struct +{ + UINT32 checksum; + UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack + UINT8 ackreturn; // The return of the ack number + + UINT8 packettype; + UINT8 reserved; // Padding + union + { + clientcmd_pak clientpak; // 144 bytes + client2cmd_pak client2pak; // 200 bytes + servertics_pak serverpak; // 132495 bytes (more around 360, no?) + serverconfig_pak servercfg; // 773 bytes + UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) + filetx_pak filetxpak; // 139 bytes + fileack_pak fileack; + UINT8 filereceived; + clientconfig_pak clientcfg; // 136 bytes + UINT8 md5sum[16]; + serverinfo_pak serverinfo; // 1024 bytes + serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) + askinfo_pak askinfo; // 61 bytes + msaskinfo_pak msaskinfo; // 22 bytes + plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + INT32 filesneedednum; // 4 bytes + filesneededconfig_pak filesneededcfg; // ??? bytes + UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes + } u; // This is needed to pack diff packet types data together +} ATTRPACK doomdata_t; + +#if defined(_MSC_VER) +#pragma pack() +#endif + +#define FILETXHEADER offsetof(filetx_pak, data) + +#define KICK_MSG_GO_AWAY 1 +#define KICK_MSG_CON_FAIL 2 +#define KICK_MSG_PLAYER_QUIT 3 +#define KICK_MSG_TIMEOUT 4 +#define KICK_MSG_BANNED 5 +#define KICK_MSG_PING_HIGH 6 +#define KICK_MSG_CUSTOM_KICK 7 +#define KICK_MSG_CUSTOM_BAN 8 +#define KICK_MSG_KEEP_BODY 0x80 + +#endif From de46eef068b5fa241c2340edf88a6ff24c74c24c Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 7 Jan 2023 13:01:48 +0100 Subject: [PATCH 41/93] Move gamestate handling to a new file --- src/hu_stuff.c | 1 + src/netcode/Sourcefile | 1 + src/netcode/d_clisrv.c | 308 +---------------------------- src/netcode/d_clisrv.h | 5 - src/netcode/gamestate.c | 341 ++++++++++++++++++++++++++++++++ src/netcode/gamestate.h | 31 +++ src/netcode/net_command.c | 1 + src/netcode/server_connection.c | 1 + src/netcode/tic_command.c | 1 + 9 files changed, 378 insertions(+), 312 deletions(-) create mode 100644 src/netcode/gamestate.c create mode 100644 src/netcode/gamestate.h diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 1e5e47df6..dc4dfe4b7 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -21,6 +21,7 @@ #include "netcode/d_clisrv.h" #include "netcode/net_command.h" +#include "netcode/gamestate.h" #include "g_game.h" #include "g_input.h" diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile index 1039b218a..c59050367 100644 --- a/src/netcode/Sourcefile +++ b/src/netcode/Sourcefile @@ -3,6 +3,7 @@ server_connection.c client_connection.c tic_command.c net_command.c +gamestate.c d_net.c d_netcmd.c d_netfil.c diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index b834c92f5..8ba10f6ea 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -53,6 +53,7 @@ #include "client_connection.h" #include "tic_command.h" #include "net_command.h" +#include "gamestate.h" #include "protocol.h" // @@ -93,18 +94,12 @@ tic_t maketic; INT16 consistancy[BACKUPTICS]; -UINT8 hu_redownloadinggamestate = 0; - // true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks boolean hu_stopped = false; UINT8 adminpassmd5[16]; boolean adminpasswordset = false; -// Client specific -// here it is for the secondary local player (splitscreen) -static boolean cl_redownloadinggamestate = false; - tic_t neededtic; SINT8 servernode = 0; // the number of the server node @@ -122,233 +117,6 @@ consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_c // of 512 bytes is like 0.1) UINT16 software_MAXPACKETLENGTH; -#define SAVEGAMESIZE (768*1024) - -boolean SV_ResendingSavegameToAnyone(void) -{ - INT32 i; - - for (i = 0; i < MAXNETNODES; i++) - if (netnodes[i].resendingsavegame) - return true; - return false; -} - -void SV_SendSaveGame(INT32 node, boolean resending) -{ - size_t length, compressedlen; - UINT8 *savebuffer; - UINT8 *compressedsave; - UINT8 *buffertosend; - - // first save it in a malloced buffer - savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!savebuffer) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - // Leave room for the uncompressed length. - save_p = savebuffer + sizeof(UINT32); - - P_SaveNetGame(resending); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } - - // Allocate space for compressed save: one byte fewer than for the - // uncompressed data to ensure that the compression is worthwhile. - compressedsave = malloc(length - 1); - if (!compressedsave) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - // Attempt to compress it. - if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) - { - // Compressing succeeded; send compressed data - - free(savebuffer); - - // State that we're compressed. - buffertosend = compressedsave; - WRITEUINT32(compressedsave, length - sizeof(UINT32)); - length = compressedlen + sizeof(UINT32); - } - else - { - // Compression failed to make it smaller; send original - - free(compressedsave); - - // State that we're not compressed - buffertosend = savebuffer; - WRITEUINT32(savebuffer, 0); - } - - AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); - save_p = NULL; - - // Remember when we started sending the savegame so we can handle timeouts - netnodes[node].sendingsavegame = true; - netnodes[node].freezetimeout = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte -} - -#ifdef DUMPCONSISTENCY -#define TMPSAVENAME "badmath.sav" -static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -static void SV_SavedGame(void) -{ - size_t length; - UINT8 *savebuffer; - char tmpsave[256]; - - if (!cv_dumpconsistency.value) - return; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - // first save it in a malloced buffer - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - P_SaveNetGame(false); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } - - // then save it! - if (!FIL_WriteFile(tmpsave, savebuffer, length)) - CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); - - free(savebuffer); - save_p = NULL; -} - -#undef TMPSAVENAME -#endif -#define TMPSAVENAME "$$$.sav" - - -void CL_LoadReceivedSavegame(boolean reloading) -{ - UINT8 *savebuffer = NULL; - size_t length, decompressedlen; - char tmpsave[256]; - - FreeFileNeeded(); - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - length = FIL_ReadFile(tmpsave, &savebuffer); - - CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); - if (!length) - { - I_Error("Can't read savegame sent"); - return; - } - - save_p = savebuffer; - - // Decompress saved game if necessary. - decompressedlen = READUINT32(save_p); - if(decompressedlen > 0) - { - UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); - lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); - Z_Free(savebuffer); - save_p = savebuffer = decompressedbuffer; - } - - paused = false; - demoplayback = false; - titlemapinaction = TITLEMAP_OFF; - titledemo = false; - automapactive = false; - - P_StopRumble(NULL); - - // load a base level - if (P_LoadNetGame(reloading)) - { - const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; - CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); - if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, "")) - { - CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - CONS_Printf(M_GetText(" Zone")); - if (actnum > 0) - CONS_Printf(" %2d", actnum); - } - CONS_Printf("\"\n"); - } - - // done - Z_Free(savebuffer); - save_p = NULL; - if (unlink(tmpsave) == -1) - CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - consistancy[gametic%BACKUPTICS] = Consistancy(); - CON_ToggleOff(); - - // Tell the server we have received and reloaded the gamestate - // so they know they can resume the game - netbuffer->packettype = PT_RECEIVEDGAMESTATE; - HSendPacket(servernode, true, 0, 0); -} - -static void CL_ReloadReceivedSavegame(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - { - LUA_InvalidatePlayer(&players[i]); - sprintf(player_names[i], "Player %d", i + 1); - } - - CL_LoadReceivedSavegame(true); - - if (neededtic < gametic) - neededtic = gametic; - maketic = neededtic; - - ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn; - P_ForceLocalAngle(&players[consoleplayer], (angle_t)(players[consoleplayer].angleturn << 16)); - if (splitscreen) - { - ticcmd_oldangleturn[1] = players[secondarydisplayplayer].oldrelangleturn; - P_ForceLocalAngle(&players[secondarydisplayplayer], (angle_t)(players[secondarydisplayplayer].angleturn << 16)); - } - - camera.subsector = R_PointInSubsector(camera.x, camera.y); - camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); - - cl_redownloadinggamestate = false; - - CONS_Printf(M_GetText("Game state reloaded\n")); -} - typedef struct banreason_s { char *reason; @@ -1006,34 +774,6 @@ static void Command_Kick(void) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } -static void Command_ResendGamestate(void) -{ - SINT8 playernum; - - if (COM_Argc() == 1) - { - CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); - return; - } - else if (client) - { - CONS_Printf(M_GetText("Only the server can use this.\n")); - return; - } - - playernum = nametonum(COM_Argv(1)); - if (playernum == -1 || playernum == 0) - return; - - // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - if (!HSendPacket(playernode[playernum], true, 0, 0)) - { - CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); - return; - } -} - static void Got_KickCmd(UINT8 **p, INT32 playernum) { INT32 pnum, msg; @@ -1736,17 +1476,6 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) netnodes[node].ingame = false; } -static void PT_CanReceiveGamestate(SINT8 node) -{ - if (client || netnodes[node].sendingsavegame) - return; - - CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[netnodes[node].player]); - - SV_SendSaveGame(node, true); // Resend a complete game state - netnodes[node].resendingsavegame = true; -} - static void PT_AskLuaFile(SINT8 node) { if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) @@ -1759,13 +1488,6 @@ static void PT_HasLuaFile(SINT8 node) SV_HandleLuaFileSent(node); } -static void PT_ReceivedGamestate(SINT8 node) -{ - netnodes[node].sendingsavegame = false; - netnodes[node].resendingsavegame = false; - netnodes[node].savegameresendcooldown = I_GetTime() + 5 * TICRATE; -} - static void PT_Ping(SINT8 node, INT32 netconsole) { // Only accept PT_PING from the server. @@ -1789,34 +1511,6 @@ static void PT_Ping(SINT8 node, INT32 netconsole) } } -static void PT_WillResendGamestate(SINT8 node) -{ - (void)node; - - char tmpsave[256]; - - if (server || cl_redownloadinggamestate) - return; - - // Send back a PT_CANRECEIVEGAMESTATE packet to the server - // so they know they can start sending the game state - netbuffer->packettype = PT_CANRECEIVEGAMESTATE; - if (!HSendPacket(servernode, true, 0, 0)) - return; - - CONS_Printf(M_GetText("Reloading game state...\n")); - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - // Don't get a corrupt savegame error because tmpsave already exists - if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) - I_Error("Can't delete %s\n", tmpsave); - - CL_PrepareDownloadSaveGame(tmpsave); - - cl_redownloadinggamestate = true; -} - static void PT_SendingLuaFile(SINT8 node) { (void)node; diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 691a2787f..d5bafe750 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -89,19 +89,16 @@ void NetUpdate(void); void GetPackets(void); void ResetNode(INT32 node); INT16 Consistancy(void); -boolean SV_ResendingSavegameToAnyone(void); void SV_StartSinglePlayerServer(void); void SV_SpawnServer(void); void SV_StopServer(void); void SV_ResetServer(void); -void SV_SendSaveGame(INT32 node, boolean resending); void CL_AddSplitscreenPlayer(void); void CL_RemoveSplitscreenPlayer(void); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, kickreason_t reason); -void CL_LoadReceivedSavegame(boolean reloading); // Is there a game running boolean Playing(void); @@ -130,8 +127,6 @@ tic_t GetLag(INT32 node); void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); -extern UINT8 hu_redownloadinggamestate; - extern UINT8 adminpassmd5[16]; extern boolean adminpasswordset; diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c new file mode 100644 index 000000000..4a3e9f3af --- /dev/null +++ b/src/netcode/gamestate.c @@ -0,0 +1,341 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file gamestate.c +/// \brief Gamestate (re)sending + +#include "d_clisrv.h" +#include "d_netfil.h" +#include "gamestate.h" +#include "i_net.h" +#include "protocol.h" +#include "server_connection.h" +#include "../am_map.h" +#include "../byteptr.h" +#include "../console.h" +#include "../d_main.h" +#include "../doomstat.h" +#include "../doomtype.h" +#include "../f_finale.h" +#include "../g_demo.h" +#include "../g_game.h" +#include "../i_time.h" +#include "../lua_script.h" +#include "../lzf.h" +#include "../m_misc.h" +#include "../p_haptic.h" +#include "../p_local.h" +#include "../p_saveg.h" +#include "../r_main.h" +#include "../tables.h" +#include "../z_zone.h" + +#define SAVEGAMESIZE (768*1024) + +UINT8 hu_redownloadinggamestate = 0; +boolean cl_redownloadinggamestate = false; + +boolean SV_ResendingSavegameToAnyone(void) +{ + INT32 i; + + for (i = 0; i < MAXNETNODES; i++) + if (netnodes[i].resendingsavegame) + return true; + return false; +} + +void SV_SendSaveGame(INT32 node, boolean resending) +{ + size_t length, compressedlen; + UINT8 *savebuffer; + UINT8 *compressedsave; + UINT8 *buffertosend; + + // first save it in a malloced buffer + savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); + if (!savebuffer) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + // Leave room for the uncompressed length. + save_p = savebuffer + sizeof(UINT32); + + P_SaveNetGame(resending); + + length = save_p - savebuffer; + if (length > SAVEGAMESIZE) + { + free(savebuffer); + save_p = NULL; + I_Error("Savegame buffer overrun"); + } + + // Allocate space for compressed save: one byte fewer than for the + // uncompressed data to ensure that the compression is worthwhile. + compressedsave = malloc(length - 1); + if (!compressedsave) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + // Attempt to compress it. + if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) + { + // Compressing succeeded; send compressed data + + free(savebuffer); + + // State that we're compressed. + buffertosend = compressedsave; + WRITEUINT32(compressedsave, length - sizeof(UINT32)); + length = compressedlen + sizeof(UINT32); + } + else + { + // Compression failed to make it smaller; send original + + free(compressedsave); + + // State that we're not compressed + buffertosend = savebuffer; + WRITEUINT32(savebuffer, 0); + } + + AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); + save_p = NULL; + + // Remember when we started sending the savegame so we can handle timeouts + netnodes[node].sendingsavegame = true; + netnodes[node].freezetimeout = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte +} + +#ifdef DUMPCONSISTENCY +#define TMPSAVENAME "badmath.sav" +static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +void SV_SavedGame(void) +{ + size_t length; + UINT8 *savebuffer; + char tmpsave[256]; + + if (!cv_dumpconsistency.value) + return; + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + // first save it in a malloced buffer + save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); + if (!save_p) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + P_SaveNetGame(false); + + length = save_p - savebuffer; + if (length > SAVEGAMESIZE) + { + free(savebuffer); + save_p = NULL; + I_Error("Savegame buffer overrun"); + } + + // then save it! + if (!FIL_WriteFile(tmpsave, savebuffer, length)) + CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); + + free(savebuffer); + save_p = NULL; +} + +#undef TMPSAVENAME +#endif +#define TMPSAVENAME "$$$.sav" + + +void CL_LoadReceivedSavegame(boolean reloading) +{ + UINT8 *savebuffer = NULL; + size_t length, decompressedlen; + char tmpsave[256]; + + FreeFileNeeded(); + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + length = FIL_ReadFile(tmpsave, &savebuffer); + + CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); + if (!length) + { + I_Error("Can't read savegame sent"); + return; + } + + save_p = savebuffer; + + // Decompress saved game if necessary. + decompressedlen = READUINT32(save_p); + if(decompressedlen > 0) + { + UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); + lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); + Z_Free(savebuffer); + save_p = savebuffer = decompressedbuffer; + } + + paused = false; + demoplayback = false; + titlemapinaction = TITLEMAP_OFF; + titledemo = false; + automapactive = false; + + P_StopRumble(NULL); + + // load a base level + if (P_LoadNetGame(reloading)) + { + const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; + CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); + if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, "")) + { + CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); + if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + CONS_Printf(M_GetText(" Zone")); + if (actnum > 0) + CONS_Printf(" %2d", actnum); + } + CONS_Printf("\"\n"); + } + + // done + Z_Free(savebuffer); + save_p = NULL; + if (unlink(tmpsave) == -1) + CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); + consistancy[gametic%BACKUPTICS] = Consistancy(); + CON_ToggleOff(); + + // Tell the server we have received and reloaded the gamestate + // so they know they can resume the game + netbuffer->packettype = PT_RECEIVEDGAMESTATE; + HSendPacket(servernode, true, 0, 0); +} + +void CL_ReloadReceivedSavegame(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + LUA_InvalidatePlayer(&players[i]); + sprintf(player_names[i], "Player %d", i + 1); + } + + CL_LoadReceivedSavegame(true); + + if (neededtic < gametic) + neededtic = gametic; + maketic = neededtic; + + ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn; + P_ForceLocalAngle(&players[consoleplayer], (angle_t)(players[consoleplayer].angleturn << 16)); + if (splitscreen) + { + ticcmd_oldangleturn[1] = players[secondarydisplayplayer].oldrelangleturn; + P_ForceLocalAngle(&players[secondarydisplayplayer], (angle_t)(players[secondarydisplayplayer].angleturn << 16)); + } + + camera.subsector = R_PointInSubsector(camera.x, camera.y); + camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); + + cl_redownloadinggamestate = false; + + CONS_Printf(M_GetText("Game state reloaded\n")); +} + +void Command_ResendGamestate(void) +{ + SINT8 playernum; + + if (COM_Argc() == 1) + { + CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); + return; + } + else if (client) + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + playernum = nametonum(COM_Argv(1)); + if (playernum == -1 || playernum == 0) + return; + + // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + if (!HSendPacket(playernode[playernum], true, 0, 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); + return; + } +} + +void PT_CanReceiveGamestate(SINT8 node) +{ + if (client || netnodes[node].sendingsavegame) + return; + + CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[netnodes[node].player]); + + SV_SendSaveGame(node, true); // Resend a complete game state + netnodes[node].resendingsavegame = true; +} + +void PT_ReceivedGamestate(SINT8 node) +{ + netnodes[node].sendingsavegame = false; + netnodes[node].resendingsavegame = false; + netnodes[node].savegameresendcooldown = I_GetTime() + 5 * TICRATE; +} + +void PT_WillResendGamestate(SINT8 node) +{ + (void)node; + + char tmpsave[256]; + + if (server || cl_redownloadinggamestate) + return; + + // Send back a PT_CANRECEIVEGAMESTATE packet to the server + // so they know they can start sending the game state + netbuffer->packettype = PT_CANRECEIVEGAMESTATE; + if (!HSendPacket(servernode, true, 0, 0)) + return; + + CONS_Printf(M_GetText("Reloading game state...\n")); + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + // Don't get a corrupt savegame error because tmpsave already exists + if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) + I_Error("Can't delete %s\n", tmpsave); + + CL_PrepareDownloadSaveGame(tmpsave); + + cl_redownloadinggamestate = true; +} diff --git a/src/netcode/gamestate.h b/src/netcode/gamestate.h new file mode 100644 index 000000000..9d2779772 --- /dev/null +++ b/src/netcode/gamestate.h @@ -0,0 +1,31 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file gamestate.h +/// \brief Gamestate (re)sending + +#ifndef __GAMESTATE__ +#define __GAMESTATE__ + +#include "../doomtype.h" + +extern UINT8 hu_redownloadinggamestate; +extern boolean cl_redownloadinggamestate; + +boolean SV_ResendingSavegameToAnyone(void); +void SV_SendSaveGame(INT32 node, boolean resending); +void SV_SavedGame(void); +void CL_LoadReceivedSavegame(boolean reloading); +void CL_ReloadReceivedSavegame(void); +void Command_ResendGamestate(void); +void PT_CanReceiveGamestate(SINT8 node); +void PT_ReceivedGamestate(SINT8 node); +void PT_WillResendGamestate(SINT8 node); + +#endif diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index eeb479d21..6f9f3f79a 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -12,6 +12,7 @@ #include "net_command.h" #include "tic_command.h" +#include "gamestate.h" #include "d_clisrv.h" #include "i_net.h" #include "../g_game.h" diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index b776db422..28d97c052 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -16,6 +16,7 @@ #include "d_netfil.h" #include "mserv.h" #include "net_command.h" +#include "gamestate.h" #include "../byteptr.h" #include "../g_game.h" #include "../g_state.h" diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index e7df895ff..180d54e69 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -14,6 +14,7 @@ #include "d_clisrv.h" #include "net_command.h" #include "client_connection.h" +#include "gamestate.h" #include "i_net.h" #include "../d_main.h" #include "../g_game.h" From 91f9f53cfc45503767e3fa7f2724c3151bab91eb Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 7 Jan 2023 13:37:33 +0100 Subject: [PATCH 42/93] Remove unused stuff --- src/netcode/d_clisrv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 8ba10f6ea..36116b931 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -69,13 +69,9 @@ // firstticstosend is used to optimize a condition // Normally maketic >= gametic > 0 -#define PREDICTIONQUEUE BACKUPTICS -#define PREDICTIONMASK (PREDICTIONQUEUE-1) #define MAX_REASONLENGTH 30 boolean server = true; // true or false but !server == client -#define client (!server) -boolean nodownload = false; boolean serverrunning = false; INT32 serverplayer = 0; char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) From d841bfb23647a2f5e97c863b5cb729fcde87fedd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 7 Jan 2023 15:57:04 +0100 Subject: [PATCH 43/93] Move netcode console variables to appropriate files --- src/m_menu.c | 1 + src/netcode/client_connection.c | 1 + src/netcode/d_clisrv.c | 40 +++++++++------------------------ src/netcode/d_clisrv.h | 7 +----- src/netcode/d_netfil.c | 9 ++++++++ src/netcode/d_netfil.h | 2 ++ src/netcode/net_command.c | 1 + src/netcode/server_connection.c | 14 ++++++++++++ src/netcode/server_connection.h | 2 ++ src/p_tick.c | 1 + 10 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f0691c17f..6a8d59f48 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -55,6 +55,7 @@ #include "netcode/d_net.h" #include "netcode/mserv.h" +#include "netcode/server_connection.h" #include "netcode/client_connection.h" #include "m_misc.h" #include "m_anigif.h" diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index bfaea2e81..a00157a50 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -11,6 +11,7 @@ /// \brief Client connection handling #include "client_connection.h" +#include "gamestate.h" #include "d_clisrv.h" #include "d_netfil.h" #include "../d_main.h" diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 36116b931..0b1c487d8 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -103,11 +103,6 @@ SINT8 servernode = 0; // the number of the server node /// \todo WORK! boolean acceptnewnode = true; -consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; -consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); - // Some software don't support largest packet // (original sersetup, not exactely, but the probability of sending a packet // of 512 bytes is like 0.1) @@ -123,6 +118,17 @@ typedef struct banreason_s static banreason_t *reasontail = NULL; //last entry, use prev static banreason_t *reasonhead = NULL; //1st entry, use next +static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; +consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); + +static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; +consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); + +consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; +consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); + static void Command_ShowBan(void) //Print out ban list { size_t i; @@ -961,30 +967,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; -consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); - -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); -static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); -static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "2", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); - -static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; -consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); -consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -// max file size to send to a player (in kilobytes) -static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {204800, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); -consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -// Speed of file downloading (in packets per tic) -static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); - static void Got_AddPlayer(UINT8 **p, INT32 playernum); // called one time at init diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index d5bafe750..9cb3ef3e8 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -37,9 +37,6 @@ extern INT32 mapchangepending; // Points inside doomcom extern doomdata_t *netbuffer; -extern consvar_t cv_showjoinaddress; -extern consvar_t cv_playbackspeed; - #define BASEPACKETSIZE offsetof(doomdata_t, u) #define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0]) @@ -76,9 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_joindelay, cv_rejointimeout; -extern consvar_t cv_resynchattempts, cv_blamecfail; -extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed; // Used in d_net, the only dependence void D_ClientServerInit(void); diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index e581be2ac..205abf713 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -116,6 +116,15 @@ boolean waitingforluafiletransfer = false; boolean waitingforluafilecommand = false; char luafiledir[256 + 16] = "luafiles"; +// max file size to send to a player (in kilobytes) +static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {204800, "MAX"}, {0, NULL}}; +consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); + +consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +// Speed of file downloading (in packets per tic) +static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; +consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); static UINT16 GetWadNumFromFileNeededId(UINT8 id) { diff --git a/src/netcode/d_netfil.h b/src/netcode/d_netfil.h index 732efcd5e..850e24d49 100644 --- a/src/netcode/d_netfil.h +++ b/src/netcode/d_netfil.h @@ -76,6 +76,8 @@ extern UINT32 downloadcompletedsize; extern INT32 totalfilesrequestednum; extern UINT32 totalfilesrequestedsize; +extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; + void AllocFileNeeded(INT32 size); void FreeFileNeeded(void); UINT8 *PutFileNeeded(UINT16 firstfile); diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 6f9f3f79a..95a49a959 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -13,6 +13,7 @@ #include "net_command.h" #include "tic_command.h" #include "gamestate.h" +#include "server_connection.h" #include "d_clisrv.h" #include "i_net.h" #include "../g_game.h" diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index 28d97c052..ce1192475 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -22,6 +22,7 @@ #include "../g_state.h" #include "../p_setup.h" #include "../p_tick.h" +#include "../command.h" #include "../doomstat.h" // Minimum timeout for sending the savegame @@ -38,6 +39,19 @@ char playeraddress[MAXPLAYERS][64]; UINT8 player_joining = false; +consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); + +static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); + +static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "2", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); + static INT32 FindRejoinerNum(SINT8 node) { char strippednodeaddress[64]; diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h index 4204db2e6..a40bd4603 100644 --- a/src/netcode/server_connection.h +++ b/src/netcode/server_connection.h @@ -13,6 +13,7 @@ #ifndef __D_SERVER_CONNECTION__ #define __D_SERVER_CONNECTION__ +#include "../command.h" #include "../doomdef.h" #include "../doomtype.h" @@ -25,5 +26,6 @@ extern tic_t jointimeout; extern tic_t joindelay; extern char playeraddress[MAXPLAYERS][64]; extern UINT8 player_joining; +extern consvar_t cv_showjoinaddress, cv_allownewplayer, cv_maxplayers, cv_joindelay, cv_rejointimeout; #endif diff --git a/src/p_tick.c b/src/p_tick.c index 4b724e333..2473d5fac 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -27,6 +27,7 @@ #include "r_fps.h" #include "i_video.h" // rendermode #include "netcode/net_command.h" +#include "netcode/server_connection.h" // Object place #include "m_cheat.h" From 332a0f6b9322c07a5ec36616b621e365a2569c29 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 7 Jan 2023 15:57:17 +0100 Subject: [PATCH 44/93] Add missing PT_ prefix to a few packet handlers --- src/netcode/client_connection.c | 4 ++-- src/netcode/client_connection.h | 2 +- src/netcode/d_clisrv.c | 12 ++++++------ src/netcode/server_connection.c | 2 +- src/netcode/server_connection.h | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index a00157a50..bed445a64 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -1052,7 +1052,7 @@ void CL_ConnectToServer(void) * \note What happens if the packet comes from a client or something like that? * */ -void HandleServerInfo(SINT8 node) +void PT_ServerInfo(SINT8 node) { // compute ping in ms const tic_t ticnow = I_GetTime(); @@ -1173,7 +1173,7 @@ void PT_ServerCFG(SINT8 node) /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? /// Shouldn't them be downloaded even at intermission time? - /// Also, according to HandleConnect, the server will send the savegame even during intermission... + /// Also, according to PT_Connect, the server will send the savegame even during intermission... if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) cl_mode = CL_DOWNLOADSAVEGAME; diff --git a/src/netcode/client_connection.h b/src/netcode/client_connection.h index a76411ba6..74cff61ff 100644 --- a/src/netcode/client_connection.h +++ b/src/netcode/client_connection.h @@ -53,7 +53,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room); void CL_ConnectToServer(void); boolean CL_SendJoin(void); -void HandleServerInfo(SINT8 node); +void PT_ServerInfo(SINT8 node); void PT_MoreFilesNeeded(SINT8 node); void PT_ServerRefuse(SINT8 node); void PT_ServerCFG(SINT8 node); diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 0b1c487d8..4589c83d3 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1358,7 +1358,7 @@ void SV_StartSinglePlayerServer(void) * \param node The packet sender (should be the server) * */ -static void HandleShutdown(SINT8 node) +static void PT_Shutdown(SINT8 node) { (void)node; LUA_HookBool(false, HOOK(GameQuit)); @@ -1373,7 +1373,7 @@ static void HandleShutdown(SINT8 node) * \param node The packet sender (should be the server) * */ -static void HandleTimeout(SINT8 node) +static void PT_Timeout(SINT8 node) { (void)node; LUA_HookBool(false, HOOK(GameQuit)); @@ -1608,26 +1608,26 @@ void GetPackets(void) if (netbuffer->packettype == PT_CLIENTJOIN && server) { - HandleConnect(node); + PT_Connect(node); continue; } if (node == servernode && client && cl_mode != CL_SEARCHING) { if (netbuffer->packettype == PT_SERVERSHUTDOWN) { - HandleShutdown(node); + PT_Shutdown(node); continue; } if (netbuffer->packettype == PT_NODETIMEOUT) { - HandleTimeout(node); + PT_Timeout(node); continue; } } if (netbuffer->packettype == PT_SERVERINFO) { - HandleServerInfo(node); + PT_ServerInfo(node); continue; } diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index ce1192475..e37c45951 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -422,7 +422,7 @@ GetRefuseMessage (SINT8 node, INT32 rejoinernum) * \param node The packet sender * */ -void HandleConnect(SINT8 node) +void PT_Connect(SINT8 node) { char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; INT32 numplayers = netbuffer->u.clientcfg.localplayers; diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h index a40bd4603..585c9e428 100644 --- a/src/netcode/server_connection.h +++ b/src/netcode/server_connection.h @@ -17,7 +17,7 @@ #include "../doomdef.h" #include "../doomtype.h" -void HandleConnect(SINT8 node); +void PT_Connect(SINT8 node); void PT_AskInfoViaMS(SINT8 node); void PT_TellFilesNeeded(SINT8 node); void PT_AskInfo(SINT8 node); From 39556e8af74d2d34976159b7654a9af684152d14 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 7 Jan 2023 16:14:41 +0100 Subject: [PATCH 45/93] Add missing _pak suffix to a few packet structures --- src/netcode/protocol.h | 8 ++++---- src/netcode/server_connection.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index 566d10d8c..1eba9286b 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -260,7 +260,7 @@ typedef struct UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused. UINT32 score; UINT16 timeinserver; // In seconds. -} ATTRPACK plrinfo; +} ATTRPACK plrinfo_pak; // Shortest player information for join during intermission. typedef struct @@ -271,7 +271,7 @@ typedef struct UINT32 pflags; UINT32 score; UINT8 ctfteam; -} ATTRPACK plrconfig; +} ATTRPACK plrconfig_pak; typedef struct { @@ -308,8 +308,8 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) - plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + plrinfo_pak playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrconfig_pak playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index e37c45951..924aa82d6 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -219,7 +219,7 @@ static void SV_SendPlayerInfo(INT32 node) netbuffer->u.playerinfo[i].data |= 0x80; } - HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); + HSendPacket(node, false, 0, sizeof(plrinfo_pak) * MAXPLAYERS); } /** Sends a PT_SERVERCFG packet From 94761d3a5505d79d6f7ebdf96e7fbf88991bff47 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 00:43:18 +0100 Subject: [PATCH 46/93] Remove outdated or misleading comments --- src/netcode/client_connection.c | 11 ++--------- src/netcode/d_clisrv.c | 14 ++------------ src/netcode/protocol.h | 32 ++++++++++++++++---------------- src/netcode/server_connection.c | 2 +- src/netcode/tic_command.c | 8 -------- 5 files changed, 21 insertions(+), 46 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index bed445a64..1adc3a65e 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -36,7 +36,7 @@ cl_mode_t cl_mode = CL_SEARCHING; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list 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; -UINT8 mynode; // my address pointofview server +UINT8 mynode; static void *snake = NULL; static void CL_DrawConnectionStatusBox(void) @@ -226,12 +226,9 @@ static boolean CL_AskFileList(INT32 firstfile) return HSendPacket(servernode, false, 0, sizeof (INT32)); } -/** Sends a special packet to declare how many players in local - * Used only in arbitratrenetstart() - * Sends a PT_CLIENTJOIN packet to the server +/** Sends a PT_CLIENTJOIN packet to the server * * \return True if the packet was successfully sent - * \todo Improve the description... * */ boolean CL_SendJoin(void) @@ -928,10 +925,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) FileReceiveTicker(); - // why are these here? this is for servers, we're a client - //if (key == 's' && server) - // doomcom->numnodes = (INT16)pnumnodes; - //FileSendTicker(); *oldtic = I_GetTime(); if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 4589c83d3..eef9bdfe5 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -99,13 +99,8 @@ boolean adminpasswordset = false; tic_t neededtic; SINT8 servernode = 0; // the number of the server node -/// \brief do we accept new players? -/// \todo WORK! boolean acceptnewnode = true; -// Some software don't support largest packet -// (original sersetup, not exactely, but the probability of sending a packet -// of 512 bytes is like 0.1) UINT16 software_MAXPACKETLENGTH; typedef struct banreason_s @@ -300,9 +295,6 @@ static void Command_connect(void) return; } - // modified game check: no longer handled - // we don't request a restart unless the filelist differs - server = false; /* if (!stricmp(COM_Argv(1), "self")) @@ -1768,7 +1760,7 @@ boolean TryRunTics(tic_t realtics) boolean ticking; // the machine has lagged but it is not so bad - if (realtics > TICRATE/7) // FIXME: consistency failure!! + if (realtics > TICRATE/7) { if (server) realtics = 1; @@ -1802,8 +1794,6 @@ boolean TryRunTics(tic_t realtics) #ifdef DEBUGFILE if (debugfile && (realtics || neededtic > gametic)) { - //SoM: 3/30/2000: Need long INT32 in the format string for args 4 & 5. - //Shut up stupid warning! fprintf(debugfile, "------------ Tryruntic: REAL:%d NEED:%d GAME:%d LOAD: %d\n", realtics, neededtic, gametic, debugload); debugload = 100000; @@ -1983,7 +1973,7 @@ void NetUpdate(void) if (client) maketic = neededtic; - Local_Maketic(realtics); // make local tic, and call menu? + Local_Maketic(realtics); if (server) CL_SendClientCmd(); // send it diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index 1eba9286b..cbeb37f36 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -294,25 +294,25 @@ typedef struct UINT8 reserved; // Padding union { - clientcmd_pak clientpak; // 144 bytes - client2cmd_pak client2pak; // 200 bytes - servertics_pak serverpak; // 132495 bytes (more around 360, no?) - serverconfig_pak servercfg; // 773 bytes - UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) - filetx_pak filetxpak; // 139 bytes + clientcmd_pak clientpak; + client2cmd_pak client2pak; + servertics_pak serverpak; + serverconfig_pak servercfg; + UINT8 textcmd[MAXTEXTCMD+1]; + filetx_pak filetxpak; fileack_pak fileack; UINT8 filereceived; - clientconfig_pak clientcfg; // 136 bytes + clientconfig_pak clientcfg; UINT8 md5sum[16]; - serverinfo_pak serverinfo; // 1024 bytes - serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) - askinfo_pak askinfo; // 61 bytes - msaskinfo_pak msaskinfo; // 22 bytes - plrinfo_pak playerinfo[MAXPLAYERS]; // 576 bytes(?) - plrconfig_pak playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) - INT32 filesneedednum; // 4 bytes - filesneededconfig_pak filesneededcfg; // ??? bytes - UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes + serverinfo_pak serverinfo; + serverrefuse_pak serverrefuse; + askinfo_pak askinfo; + msaskinfo_pak msaskinfo; + plrinfo_pak playerinfo[MAXPLAYERS]; + plrconfig_pak playerconfig[MAXPLAYERS]; + INT32 filesneedednum; + filesneededconfig_pak filesneededcfg; + UINT32 pingtable[MAXPLAYERS+1]; } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index 924aa82d6..f2b0306e6 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -460,7 +460,7 @@ void PT_Connect(SINT8 node) ResetNode(node); SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); /// \todo fix this !!! - return; // restart the while + return; } DEBFILE("new node joined\n"); diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 180d54e69..bab0fad0a 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -262,11 +262,6 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) else { DEBFILE(va("frame not in bound: %u\n", neededtic)); - /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) - I_Error("Received an out of order PT_SERVERTICS packet!\n" - "Got tics %d-%d, needed tic %d\n\n" - "Please report this crash on the Master Board,\n" - "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ } } @@ -447,9 +442,6 @@ void SV_SendTics(void) netnodes[0].supposedtic = maketic; } -// -// TryRunTics -// void Local_Maketic(INT32 realtics) { I_OsPolling(); // I_Getevent From cb634402a843e6542d00c851fda814d9f2df9a23 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 00:46:12 +0100 Subject: [PATCH 47/93] Rename packet handlers to match their associated PT_ constants --- src/netcode/client_connection.c | 2 +- src/netcode/d_clisrv.c | 4 ++-- src/netcode/server_connection.c | 2 +- src/netcode/server_connection.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 1adc3a65e..ff20a6fc7 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -1166,7 +1166,7 @@ void PT_ServerCFG(SINT8 node) /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? /// Shouldn't them be downloaded even at intermission time? - /// Also, according to PT_Connect, the server will send the savegame even during intermission... + /// Also, according to PT_ClientJoin, the server will send the savegame even during intermission... if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) cl_mode = CL_DOWNLOADSAVEGAME; diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index eef9bdfe5..7fc64b456 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1350,7 +1350,7 @@ void SV_StartSinglePlayerServer(void) * \param node The packet sender (should be the server) * */ -static void PT_Shutdown(SINT8 node) +static void PT_ServerShutdown(SINT8 node) { (void)node; LUA_HookBool(false, HOOK(GameQuit)); @@ -1365,7 +1365,7 @@ static void PT_Shutdown(SINT8 node) * \param node The packet sender (should be the server) * */ -static void PT_Timeout(SINT8 node) +static void PT_NodeTimeout(SINT8 node) { (void)node; LUA_HookBool(false, HOOK(GameQuit)); diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index f2b0306e6..3e7d46ef6 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -422,7 +422,7 @@ GetRefuseMessage (SINT8 node, INT32 rejoinernum) * \param node The packet sender * */ -void PT_Connect(SINT8 node) +void PT_ClientJoin(SINT8 node) { char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; INT32 numplayers = netbuffer->u.clientcfg.localplayers; diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h index 585c9e428..96f7566ba 100644 --- a/src/netcode/server_connection.h +++ b/src/netcode/server_connection.h @@ -17,7 +17,7 @@ #include "../doomdef.h" #include "../doomtype.h" -void PT_Connect(SINT8 node); +void PT_ClientJoin(SINT8 node); void PT_AskInfoViaMS(SINT8 node); void PT_TellFilesNeeded(SINT8 node); void PT_AskInfo(SINT8 node); From 5d5e2c78e4e116b40de4bfb81b2d409b4211c189 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 00:47:33 +0100 Subject: [PATCH 48/93] Call all packet handlers from the same place --- src/netcode/d_clisrv.c | 41 +++++++++++---------------------- src/netcode/server_connection.c | 2 +- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 7fc64b456..c004eeede 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1352,6 +1352,9 @@ void SV_StartSinglePlayerServer(void) */ static void PT_ServerShutdown(SINT8 node) { + if (node != servernode || server || cl_mode == CL_SEARCHING) + return; + (void)node; LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); @@ -1412,7 +1415,11 @@ static void PT_Login(SINT8 node, INT32 netconsole) static void PT_ClientQuit(SINT8 node, INT32 netconsole) { if (client) + { + if (node == servernode && cl_mode != CL_SEARCHING && netbuffer->packettype == PT_NODETIMEOUT) + PT_NodeTimeout(node); return; + } if (!netnodes[node].ingame) { @@ -1505,6 +1512,7 @@ static void HandlePacketFromAwayNode(SINT8 node) switch (netbuffer->packettype) { case PT_ASKINFOVIAMS : PT_AskInfoViaMS (node ); break; + case PT_SERVERINFO : PT_ServerInfo (node ); break; case PT_TELLFILESNEEDED: PT_TellFilesNeeded(node ); break; case PT_MOREFILESNEEDED: PT_MoreFilesNeeded(node ); break; case PT_ASKINFO : PT_AskInfo (node ); break; @@ -1517,6 +1525,8 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_NODETIMEOUT : PT_ClientQuit (node, -1); break; case PT_CLIENTQUIT : PT_ClientQuit (node, -1); break; case PT_SERVERTICS : PT_ServerTics (node, -1); break; + case PT_CLIENTJOIN : PT_ClientJoin (node ); break; + case PT_SERVERSHUTDOWN : PT_ServerShutdown (node ); break; case PT_CLIENTCMD : break; // This is not an "unknown packet" default: @@ -1566,6 +1576,7 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_ASKLUAFILE : PT_AskLuaFile (node ); break; case PT_HASLUAFILE : PT_HasLuaFile (node ); break; case PT_RECEIVEDGAMESTATE : PT_ReceivedGamestate (node ); break; + case PT_SERVERINFO : PT_ServerInfo (node ); break; // CLIENT RECEIVE case PT_SERVERTICS : PT_ServerTics (node, netconsole); break; @@ -1575,7 +1586,9 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_FILERECEIVED : PT_FileReceived (node ); break; case PT_WILLRESENDGAMESTATE: PT_WillResendGamestate(node ); break; case PT_SENDINGLUAFILE : PT_SendingLuaFile (node ); break; + case PT_SERVERSHUTDOWN : PT_ServerShutdown (node ); break; case PT_SERVERCFG : break; + case PT_CLIENTJOIN : break; default: DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", @@ -1598,34 +1611,6 @@ void GetPackets(void) { node = (SINT8)doomcom->remotenode; - if (netbuffer->packettype == PT_CLIENTJOIN && server) - { - PT_Connect(node); - continue; - } - if (node == servernode && client && cl_mode != CL_SEARCHING) - { - if (netbuffer->packettype == PT_SERVERSHUTDOWN) - { - PT_Shutdown(node); - continue; - } - if (netbuffer->packettype == PT_NODETIMEOUT) - { - PT_Timeout(node); - continue; - } - } - - if (netbuffer->packettype == PT_SERVERINFO) - { - PT_ServerInfo(node); - continue; - } - - if (netbuffer->packettype == PT_PLAYERINFO) - continue; // We do nothing with PLAYERINFO, that's for the MS browser. - // Packet received from someone already playing if (netnodes[node].ingame) HandlePacketFromPlayer(node); diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index 3e7d46ef6..9b41da920 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -430,7 +430,7 @@ void PT_ClientJoin(SINT8 node) INT32 i; // Ignore duplicate packets - if (netnodes[node].ingame) + if (client || netnodes[node].ingame) return; rejoinernum = FindRejoinerNum(node); From 2bd2b728bf530b65de3c12cbb9a7f75e79d94c5f Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 13:27:08 +0100 Subject: [PATCH 49/93] Remove useless variable --- src/netcode/d_clisrv.c | 9 --------- src/netcode/server_connection.c | 3 --- src/netcode/server_connection.h | 1 - 3 files changed, 13 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index c004eeede..ecd7c9bbe 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1605,8 +1605,6 @@ void GetPackets(void) { SINT8 node; // The packet sender - player_joining = false; - while (HGetPacket()) { node = (SINT8)doomcom->remotenode; @@ -1793,13 +1791,6 @@ boolean TryRunTics(tic_t realtics) hu_stopped = false; } - if (player_joining) - { - if (realtics) - hu_stopped = true; - return false; - } - if (ticking) { if (advancedemo) diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index 9b41da920..ed0e28309 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -37,8 +37,6 @@ tic_t joindelay = 0; // The actual timeout will be longer depending on the savegame length char playeraddress[MAXPLAYERS][64]; -UINT8 player_joining = false; - consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); @@ -475,7 +473,6 @@ void PT_ClientJoin(SINT8 node) SV_AddPlayer(node, names[i]); joindelay += cv_joindelay.value * TICRATE; - player_joining = true; } void PT_AskInfoViaMS(SINT8 node) diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h index 96f7566ba..7481d0eb5 100644 --- a/src/netcode/server_connection.h +++ b/src/netcode/server_connection.h @@ -25,7 +25,6 @@ void PT_AskInfo(SINT8 node); extern tic_t jointimeout; extern tic_t joindelay; extern char playeraddress[MAXPLAYERS][64]; -extern UINT8 player_joining; extern consvar_t cv_showjoinaddress, cv_allownewplayer, cv_maxplayers, cv_joindelay, cv_rejointimeout; #endif From b42336c23254e795e351aad18a4ef83989f987a1 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 16:28:41 +0100 Subject: [PATCH 50/93] Simplify convoluted code --- src/netcode/d_clisrv.c | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index ecd7c9bbe..5bb2c4600 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1421,15 +1421,9 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) return; } - if (!netnodes[node].ingame) - { - Net_CloseConnection(node); - return; - } - // nodeingame will be put false in the execution of kick command // this allow to send some packets to the quitting client to have their ack back - if (netconsole != -1 && playeringame[netconsole]) + if (netnodes[node].ingame && netconsole != -1 && playeringame[netconsole]) { UINT8 kickmsg; @@ -1440,17 +1434,18 @@ static void PT_ClientQuit(SINT8 node, INT32 netconsole) kickmsg |= KICK_MSG_KEEP_BODY; SendKick(netconsole, kickmsg); - netnodes[node].player = -1; if (netnodes[node].player2 != -1 && netnodes[node].player2 >= 0 && playeringame[(UINT8)netnodes[node].player2]) { SendKick(netnodes[node].player2, kickmsg); - netnodes[node].player2 = -1; } } + Net_CloseConnection(node); netnodes[node].ingame = false; + netnodes[node].player = -1; + netnodes[node].player2 = -1; } static void PT_AskLuaFile(SINT8 node) @@ -1603,11 +1598,9 @@ static void HandlePacketFromPlayer(SINT8 node) */ void GetPackets(void) { - SINT8 node; // The packet sender - while (HGetPacket()) { - node = (SINT8)doomcom->remotenode; + SINT8 node = doomcom->remotenode; // Packet received from someone already playing if (netnodes[node].ingame) @@ -1740,8 +1733,6 @@ If they're not lagging, decrement the timer by 1. Of course, reset all of this i boolean TryRunTics(tic_t realtics) { - boolean ticking; - // the machine has lagged but it is not so bad if (realtics > TICRATE/7) { @@ -1783,16 +1774,11 @@ boolean TryRunTics(tic_t realtics) } #endif - ticking = neededtic > gametic; - - if (ticking) + if (neededtic > gametic) { if (realtics) hu_stopped = false; - } - if (ticking) - { if (advancedemo) { if (timedemo_quit) @@ -1826,16 +1812,19 @@ boolean TryRunTics(tic_t realtics) if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) break; } + + return true; } else { if (realtics) hu_stopped = true; - } - return ticking; + return false; + } } + static INT32 pingtimeout[MAXPLAYERS]; static inline void PingUpdate(void) @@ -1976,8 +1965,6 @@ void NetUpdate(void) { if (!demoplayback) { - INT32 counts; - hu_redownloadinggamestate = false; firstticstosend = gametic; @@ -1991,8 +1978,7 @@ void NetUpdate(void) } // Don't erase tics not acknowledged - counts = realtics; - + INT32 counts = realtics; if (maketic + counts >= firstticstosend + BACKUPTICS) counts = firstticstosend+BACKUPTICS-maketic-1; From 2f9a2ebc86f6252526f5186793c81933d71f9293 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 8 Jan 2023 16:33:21 +0100 Subject: [PATCH 51/93] Move comment to an appropriate place --- src/netcode/d_clisrv.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 5bb2c4600..b0d534b84 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1725,12 +1725,6 @@ INT16 Consistancy(void) return (INT16)(ret & 0xFFFF); } -/* -Ping Update except better: -We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. -If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. -*/ - boolean TryRunTics(tic_t realtics) { // the machine has lagged but it is not so bad @@ -1824,6 +1818,11 @@ boolean TryRunTics(tic_t realtics) } } +/* +Ping Update except better: +We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. +If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. +*/ static INT32 pingtimeout[MAXPLAYERS]; From 35dac244ef1a0727ba54a3dbdb6dd797220fdbcd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Mon, 9 Jan 2023 21:39:33 +0100 Subject: [PATCH 52/93] Fix clients not being able to join servers --- src/netcode/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index b0d534b84..6680c7e42 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1523,6 +1523,7 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_CLIENTJOIN : PT_ClientJoin (node ); break; case PT_SERVERSHUTDOWN : PT_ServerShutdown (node ); break; case PT_CLIENTCMD : break; // This is not an "unknown packet" + case PT_PLAYERINFO : break; // This is not an "unknown packet" default: DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); From 456c6b1a0012c8b04881ba9f7042869e111c9471 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Mon, 9 Jan 2023 22:14:58 +0100 Subject: [PATCH 53/93] Remove reboundstore timeout hack --- src/netcode/d_clisrv.c | 50 ++++++++------------------------------- src/netcode/d_clisrv.h | 1 + src/netcode/d_net.c | 19 +++++---------- src/netcode/net_command.c | 10 ++++++++ src/netcode/net_command.h | 1 + src/netcode/protocol.h | 1 - 6 files changed, 28 insertions(+), 54 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 6680c7e42..81d7e5543 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -479,6 +479,15 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason) P_CheckRacers(); } +void CL_HandleTimeout(void) +{ + LUA_HookBool(false, HOOK(GameQuit)); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); +} + void CL_Reset(void) { if (metalrecording) @@ -1363,21 +1372,6 @@ static void PT_ServerShutdown(SINT8 node) M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING); } -/** Called when a PT_NODETIMEOUT packet is received - * - * \param node The packet sender (should be the server) - * - */ -static void PT_NodeTimeout(SINT8 node) -{ - (void)node; - LUA_HookBool(false, HOOK(GameQuit)); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); -} - static void PT_Login(SINT8 node, INT32 netconsole) { (void)node; @@ -1415,32 +1409,10 @@ static void PT_Login(SINT8 node, INT32 netconsole) static void PT_ClientQuit(SINT8 node, INT32 netconsole) { if (client) - { - if (node == servernode && cl_mode != CL_SEARCHING && netbuffer->packettype == PT_NODETIMEOUT) - PT_NodeTimeout(node); return; - } - // nodeingame will be put false in the execution of kick command - // this allow to send some packets to the quitting client to have their ack back if (netnodes[node].ingame && netconsole != -1 && playeringame[netconsole]) - { - UINT8 kickmsg; - - if (netbuffer->packettype == PT_NODETIMEOUT) - kickmsg = KICK_MSG_TIMEOUT; - else - kickmsg = KICK_MSG_PLAYER_QUIT; - kickmsg |= KICK_MSG_KEEP_BODY; - - SendKick(netconsole, kickmsg); - - if (netnodes[node].player2 != -1 && netnodes[node].player2 >= 0 - && playeringame[(UINT8)netnodes[node].player2]) - { - SendKick(netnodes[node].player2, kickmsg); - } - } + SendKicksForNode(node, KICK_MSG_PLAYER_QUIT | KICK_MSG_KEEP_BODY); Net_CloseConnection(node); netnodes[node].ingame = false; @@ -1517,7 +1489,6 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_FILEACK : PT_FileAck (node ); break; case PT_FILERECEIVED : PT_FileReceived (node ); break; case PT_REQUESTFILE : PT_RequestFile (node ); break; - case PT_NODETIMEOUT : PT_ClientQuit (node, -1); break; case PT_CLIENTQUIT : PT_ClientQuit (node, -1); break; case PT_SERVERTICS : PT_ServerTics (node, -1); break; case PT_CLIENTJOIN : PT_ClientJoin (node ); break; @@ -1566,7 +1537,6 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_TEXTCMD : PT_TextCmd (node, netconsole); break; case PT_TEXTCMD2 : PT_TextCmd (node, netconsole); break; case PT_LOGIN : PT_Login (node, netconsole); break; - case PT_NODETIMEOUT : PT_ClientQuit (node, netconsole); break; case PT_CLIENTQUIT : PT_ClientQuit (node, netconsole); break; case PT_CANRECEIVEGAMESTATE: PT_CanReceiveGamestate(node ); break; case PT_ASKLUAFILE : PT_AskLuaFile (node ); break; diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 9cb3ef3e8..0abd638ce 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -94,6 +94,7 @@ void CL_RemoveSplitscreenPlayer(void); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, kickreason_t reason); +void CL_HandleTimeout(void); // Is there a game running boolean Playing(void); diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index 972342282..3c16392d0 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -27,6 +27,7 @@ #include "d_netfil.h" #include "d_clisrv.h" #include "tic_command.h" +#include "net_command.h" #include "../z_zone.h" #include "i_tcp.h" #include "../d_main.h" // srb2home @@ -461,14 +462,10 @@ void Net_ConnectionTimeout(INT32 node) return; nodes[node].flags |= NF_TIMEOUT; - // Send a very special packet to self (hack the reboundstore queue) - // Main code will handle it - reboundstore[rebound_head].packettype = PT_NODETIMEOUT; - reboundstore[rebound_head].ack = 0; - reboundstore[rebound_head].ackreturn = 0; - reboundstore[rebound_head].u.textcmd[0] = (UINT8)node; - reboundsize[rebound_head] = (INT16)(BASEPACKETSIZE + 1); - rebound_head = (rebound_head+1) % MAXREBOUND; + if (server) + SendKicksForNode(node, KICK_MSG_TIMEOUT | KICK_MSG_KEEP_BODY); + else + CL_HandleTimeout(); // Do not redo it quickly (if we do not close connection it is // for a good reason!) @@ -782,7 +779,6 @@ static const char *packettypename[NUMPACKETTYPE] = "TEXTCMD", "TEXTCMD2", "CLIENTJOIN", - "NODETIMEOUT", "LOGIN", "TELLFILESNEEDED", "MOREFILESNEEDED", @@ -1065,10 +1061,7 @@ boolean HGetPacket(void) { M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]); doomcom->datalength = reboundsize[rebound_tail]; - if (netbuffer->packettype == PT_NODETIMEOUT) - doomcom->remotenode = netbuffer->u.textcmd[0]; - else - doomcom->remotenode = 0; + doomcom->remotenode = 0; rebound_tail = (rebound_tail+1) % MAXREBOUND; #ifdef DEBUGFILE diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 95a49a959..13477d42d 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -315,3 +315,13 @@ void SendKick(UINT8 playernum, UINT8 msg) buf[1] = msg; SendNetXCmd(XD_KICK, &buf, 2); } + +void SendKicksForNode(SINT8 node, UINT8 msg) +{ + if (!netnodes[node].ingame) + return; + + for (INT32 playernum = netnodes[node].player; playernum != -1; playernum = netnodes[node].player2) + if (playernum != -1 && playeringame[playernum]) + SendKick(playernum, msg); +} diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index 1fc5035c8..f1b4b2f3f 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -58,5 +58,6 @@ size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); void SendKick(UINT8 playernum, UINT8 msg); +void SendKicksForNode(SINT8 node, UINT8 msg); #endif diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index cbeb37f36..374cc5bff 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -85,7 +85,6 @@ typedef enum PT_TEXTCMD, // Extra text commands from the client. PT_TEXTCMD2, // Splitscreen text commands. PT_CLIENTJOIN, // Client wants to join; used in start game. - PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_LOGIN, // Login attempt from the client. From 79356fe6280d95828c27479301425410156edc11 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Thu, 12 Jan 2023 19:40:31 +0100 Subject: [PATCH 54/93] Move netgame commands to a new file --- src/netcode/Sourcefile | 1 + src/netcode/commands.c | 489 +++++++++++++++++++++++++++++++++++++++++ src/netcode/commands.h | 33 +++ src/netcode/d_clisrv.c | 460 +------------------------------------- src/netcode/d_net.h | 1 - 5 files changed, 524 insertions(+), 460 deletions(-) create mode 100644 src/netcode/commands.c create mode 100644 src/netcode/commands.h diff --git a/src/netcode/Sourcefile b/src/netcode/Sourcefile index c59050367..7c0354714 100644 --- a/src/netcode/Sourcefile +++ b/src/netcode/Sourcefile @@ -4,6 +4,7 @@ client_connection.c tic_command.c net_command.c gamestate.c +commands.c d_net.c d_netcmd.c d_netfil.c diff --git a/src/netcode/commands.c b/src/netcode/commands.c new file mode 100644 index 000000000..834e1c666 --- /dev/null +++ b/src/netcode/commands.c @@ -0,0 +1,489 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file commands.c +/// \brief Various netgame commands, such as kick and ban + +#include "commands.h" +#include "d_clisrv.h" +#include "client_connection.h" +#include "net_command.h" +#include "d_netcmd.h" +#include "d_net.h" +#include "i_net.h" +#include "protocol.h" +#include "../byteptr.h" +#include "../d_main.h" +#include "../g_game.h" +#include "../w_wad.h" +#include "../z_zone.h" +#include "../doomstat.h" +#include "../doomdef.h" +#include "../r_local.h" +#include +#include +#include +#include + +typedef struct banreason_s +{ + char *reason; + struct banreason_s *prev; //-1 + struct banreason_s *next; //+1 +} banreason_t; + +static banreason_t *reasontail = NULL; //last entry, use prev +static banreason_t *reasonhead = NULL; //1st entry, use next + +void Ban_Add(const char *reason) +{ + banreason_t *reasonlist = malloc(sizeof(*reasonlist)); + + if (!reasonlist) + return; + if (!reason) + reason = "NA"; + + reasonlist->next = NULL; + reasonlist->reason = Z_StrDup(reason); + if ((reasonlist->prev = reasontail) == NULL) + reasonhead = reasonlist; + else + reasontail->next = reasonlist; + reasontail = reasonlist; +} + +static void Ban_Clear(void) +{ + banreason_t *temp; + + I_ClearBans(); + + reasontail = NULL; + + while (reasonhead) + { + temp = reasonhead->next; + Z_Free(reasonhead->reason); + free(reasonhead); + reasonhead = temp; + } +} + +void Ban_Load_File(boolean warning) +{ + FILE *f; + size_t i; + const char *address, *mask; + char buffer[MAX_WADPATH]; + + if (!I_ClearBans) + return; + + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); + + if (!f) + { + if (warning) + CONS_Alert(CONS_WARNING, M_GetText("Could not open ban.txt for ban list\n")); + return; + } + + Ban_Clear(); + + for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) + { + address = strtok(buffer, " \t\r\n"); + mask = strtok(NULL, " \t\r\n"); + + I_SetBanAddress(address, mask); + + Ban_Add(strtok(NULL, "\r\n")); + } + + fclose(f); +} + +void D_SaveBan(void) +{ + FILE *f; + size_t i; + banreason_t *reasonlist = reasonhead; + const char *address, *mask; + const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); + + if (!reasonhead) + { + remove(path); + return; + } + + f = fopen(path, "w"); + + if (!f) + { + CONS_Alert(CONS_WARNING, M_GetText("Could not save ban list into ban.txt\n")); + return; + } + + for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) + { + if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) + fprintf(f, "%s 0", address); + else + fprintf(f, "%s %s", address, mask); + + if (reasonlist && reasonlist->reason) + fprintf(f, " %s\n", reasonlist->reason); + else + fprintf(f, " %s\n", "NA"); + + if (reasonlist) reasonlist = reasonlist->next; + } + + fclose(f); +} + +void Command_ShowBan(void) //Print out ban list +{ + size_t i; + const char *address, *mask; + banreason_t *reasonlist = reasonhead; + + if (I_GetBanAddress) + CONS_Printf(M_GetText("Ban List:\n")); + else + return; + + for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) + { + if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) + CONS_Printf("%s: %s ", sizeu1(i+1), address); + else + CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask); + + if (reasonlist && reasonlist->reason) + CONS_Printf("(%s)\n", reasonlist->reason); + else + CONS_Printf("\n"); + + if (reasonlist) reasonlist = reasonlist->next; + } + + if (i == 0 && !address) + CONS_Printf(M_GetText("(empty)\n")); +} + +void Command_ClearBans(void) +{ + if (!I_ClearBans) + return; + + Ban_Clear(); + D_SaveBan(); +} + +void Command_Ban(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("Ban : ban and kick a player\n")); + return; + } + + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + + if (server || IsPlayerAdmin(consoleplayer)) + { + UINT8 buf[3 + MAX_REASONLENGTH]; + UINT8 *p = buf; + const SINT8 pn = nametonum(COM_Argv(1)); + const INT32 node = playernode[(INT32)pn]; + + if (pn == -1 || pn == 0) + return; + + WRITEUINT8(p, pn); + + if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now + { + CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); + WRITEUINT8(p, KICK_MSG_GO_AWAY); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + if (server) // only the server is allowed to do this right now + { + Ban_Add(COM_Argv(2)); + D_SaveBan(); // save the ban list + } + + if (COM_Argc() == 2) + { + WRITEUINT8(p, KICK_MSG_BANNED); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + size_t i, j = COM_Argc(); + char message[MAX_REASONLENGTH]; + + //Steal from the motd code so you don't have to put the reason in quotes. + strlcpy(message, COM_Argv(2), sizeof message); + for (i = 3; i < j; i++) + { + strlcat(message, " ", sizeof message); + strlcat(message, COM_Argv(i), sizeof message); + } + + WRITEUINT8(p, KICK_MSG_CUSTOM_BAN); + WRITESTRINGN(p, message, MAX_REASONLENGTH); + SendNetXCmd(XD_KICK, &buf, p - buf); + } + } + } + else + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + +} + +void Command_BanIP(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("banip : ban an ip address\n")); + return; + } + + if (server) // Only the server can use this, otherwise does nothing. + { + const char *address = (COM_Argv(1)); + const char *reason; + + if (COM_Argc() == 2) + reason = NULL; + else + reason = COM_Argv(2); + + + if (I_SetBanAddress && I_SetBanAddress(address, NULL)) + { + if (reason) + CONS_Printf("Banned IP address %s for: %s\n", address, reason); + else + CONS_Printf("Banned IP address %s\n", address); + + Ban_Add(reason); + D_SaveBan(); + } + else + { + return; + } + } +} + +void Command_ReloadBan(void) //recheck ban.txt +{ + Ban_Load_File(true); +} + +void Command_Kick(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("kick : kick a player\n")); + return; + } + + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + + if (server || IsPlayerAdmin(consoleplayer)) + { + UINT8 buf[3 + MAX_REASONLENGTH]; + UINT8 *p = buf; + const SINT8 pn = nametonum(COM_Argv(1)); + + if (pn == -1 || pn == 0) + return; + + // Special case if we are trying to kick a player who is downloading the game state: + // trigger a timeout instead of kicking them, because a kick would only + // take effect after they have finished downloading + if (server && playernode[pn] != UINT8_MAX && netnodes[playernode[pn]].sendingsavegame) + { + Net_ConnectionTimeout(playernode[pn]); + return; + } + + WRITESINT8(p, pn); + + if (COM_Argc() == 2) + { + WRITEUINT8(p, KICK_MSG_GO_AWAY); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + size_t i, j = COM_Argc(); + char message[MAX_REASONLENGTH]; + + //Steal from the motd code so you don't have to put the reason in quotes. + strlcpy(message, COM_Argv(2), sizeof message); + for (i = 3; i < j; i++) + { + strlcat(message, " ", sizeof message); + strlcat(message, COM_Argv(i), sizeof message); + } + + WRITEUINT8(p, KICK_MSG_CUSTOM_KICK); + WRITESTRINGN(p, message, MAX_REASONLENGTH); + SendNetXCmd(XD_KICK, &buf, p - buf); + } + } + else + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); +} + +void Command_connect(void) +{ + if (COM_Argc() < 2 || *COM_Argv(1) == 0) + { + CONS_Printf(M_GetText( + "Connect (port): connect to a server\n" + "Connect ANY: connect to the first lan server found\n" + //"Connect SELF: connect to your own server.\n" + )); + return; + } + + if (Playing() || titledemo) + { + CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); + return; + } + + server = false; +/* + if (!stricmp(COM_Argv(1), "self")) + { + servernode = 0; + server = true; + /// \bug should be but... + //SV_SpawnServer(); + } + else +*/ + { + // used in menu to connect to a server in the list + if (netgame && !stricmp(COM_Argv(1), "node")) + { + servernode = (SINT8)atoi(COM_Argv(2)); + } + else if (netgame) + { + CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); + return; + } + else if (I_NetOpenSocket) + { + I_NetOpenSocket(); + netgame = true; + multiplayer = true; + + if (!stricmp(COM_Argv(1), "any")) + servernode = BROADCASTADDR; + else if (I_NetMakeNodewPort) + { + if (COM_Argc() >= 3) // address AND port + servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2)); + else // address only, or address:port + servernode = I_NetMakeNode(COM_Argv(1)); + } + else + { + CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n")); + D_CloseConnection(); + return; + } + } + else + CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n")); + } + + splitscreen = false; + SplitScreen_OnChange(); + botingame = false; + botskin = 0; + CL_ConnectToServer(); +} + +void Command_GetPlayerNum(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + if (serverplayer == i) + CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); + else + CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); + } +} + +/** Lists all players and their player numbers. + * + * \sa Command_GetPlayerNum + */ +void Command_Nodes(void) +{ + INT32 i; + size_t maxlen = 0; + const char *address; + + for (i = 0; i < MAXPLAYERS; i++) + { + const size_t plen = strlen(player_names[i]); + if (playeringame[i] && plen > maxlen) + maxlen = plen; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); + + if (playernode[i] != UINT8_MAX) + { + CONS_Printf(" - node %.2d", playernode[i]); + if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) + CONS_Printf(" - %s", address); + } + + if (IsPlayerAdmin(i)) + CONS_Printf(M_GetText(" (verified admin)")); + + if (players[i].spectator) + CONS_Printf(M_GetText(" (spectator)")); + + CONS_Printf("\n"); + } + } +} diff --git a/src/netcode/commands.h b/src/netcode/commands.h new file mode 100644 index 000000000..5ff4d1cae --- /dev/null +++ b/src/netcode/commands.h @@ -0,0 +1,33 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2022 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file commands.h +/// \brief Various netgame commands, such as kick and ban + +#ifndef __COMMANDS__ +#define __COMMANDS__ + +#include "../doomdef.h" + +#define MAX_REASONLENGTH 30 + +void Ban_Add(const char *reason); +void D_SaveBan(void); +void Ban_Load_File(boolean warning); +void Command_ShowBan(void); +void Command_ClearBans(void); +void Command_Ban(void); +void Command_BanIP(void); +void Command_ReloadBan(void); +void Command_Kick(void); +void Command_connect(void); +void Command_GetPlayerNum(void); +void Command_Nodes(void); + +#endif diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 81d7e5543..506de8c02 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -54,6 +54,7 @@ #include "tic_command.h" #include "net_command.h" #include "gamestate.h" +#include "commands.h" #include "protocol.h" // @@ -69,8 +70,6 @@ // firstticstosend is used to optimize a condition // Normally maketic >= gametic > 0 -#define MAX_REASONLENGTH 30 - boolean server = true; // true or false but !server == client boolean serverrunning = false; INT32 serverplayer = 0; @@ -103,16 +102,6 @@ boolean acceptnewnode = true; UINT16 software_MAXPACKETLENGTH; -typedef struct banreason_s -{ - char *reason; - struct banreason_s *prev; //-1 - struct banreason_s *next; //+1 -} banreason_t; - -static banreason_t *reasontail = NULL; //last entry, use prev -static banreason_t *reasonhead = NULL; //1st entry, use next - static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); @@ -124,232 +113,6 @@ consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); -static void Command_ShowBan(void) //Print out ban list -{ - size_t i; - const char *address, *mask; - banreason_t *reasonlist = reasonhead; - - if (I_GetBanAddress) - CONS_Printf(M_GetText("Ban List:\n")); - else - return; - - for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) - { - if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) - CONS_Printf("%s: %s ", sizeu1(i+1), address); - else - CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask); - - if (reasonlist && reasonlist->reason) - CONS_Printf("(%s)\n", reasonlist->reason); - else - CONS_Printf("\n"); - - if (reasonlist) reasonlist = reasonlist->next; - } - - if (i == 0 && !address) - CONS_Printf(M_GetText("(empty)\n")); -} - -void D_SaveBan(void) -{ - FILE *f; - size_t i; - banreason_t *reasonlist = reasonhead; - const char *address, *mask; - const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); - - if (!reasonhead) - { - remove(path); - return; - } - - f = fopen(path, "w"); - - if (!f) - { - CONS_Alert(CONS_WARNING, M_GetText("Could not save ban list into ban.txt\n")); - return; - } - - for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) - { - if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) - fprintf(f, "%s 0", address); - else - fprintf(f, "%s %s", address, mask); - - if (reasonlist && reasonlist->reason) - fprintf(f, " %s\n", reasonlist->reason); - else - fprintf(f, " %s\n", "NA"); - - if (reasonlist) reasonlist = reasonlist->next; - } - - fclose(f); -} - -static void Ban_Add(const char *reason) -{ - banreason_t *reasonlist = malloc(sizeof(*reasonlist)); - - if (!reasonlist) - return; - if (!reason) - reason = "NA"; - - reasonlist->next = NULL; - reasonlist->reason = Z_StrDup(reason); - if ((reasonlist->prev = reasontail) == NULL) - reasonhead = reasonlist; - else - reasontail->next = reasonlist; - reasontail = reasonlist; -} - -static void Ban_Clear(void) -{ - banreason_t *temp; - - I_ClearBans(); - - reasontail = NULL; - - while (reasonhead) - { - temp = reasonhead->next; - Z_Free(reasonhead->reason); - free(reasonhead); - reasonhead = temp; - } -} - -static void Command_ClearBans(void) -{ - if (!I_ClearBans) - return; - - Ban_Clear(); - D_SaveBan(); -} - -static void Ban_Load_File(boolean warning) -{ - FILE *f; - size_t i; - const char *address, *mask; - char buffer[MAX_WADPATH]; - - if (!I_ClearBans) - return; - - f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); - - if (!f) - { - if (warning) - CONS_Alert(CONS_WARNING, M_GetText("Could not open ban.txt for ban list\n")); - return; - } - - Ban_Clear(); - - for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) - { - address = strtok(buffer, " \t\r\n"); - mask = strtok(NULL, " \t\r\n"); - - I_SetBanAddress(address, mask); - - Ban_Add(strtok(NULL, "\r\n")); - } - - fclose(f); -} - -static void Command_ReloadBan(void) //recheck ban.txt -{ - Ban_Load_File(true); -} - -static void Command_connect(void) -{ - if (COM_Argc() < 2 || *COM_Argv(1) == 0) - { - CONS_Printf(M_GetText( - "Connect (port): connect to a server\n" - "Connect ANY: connect to the first lan server found\n" - //"Connect SELF: connect to your own server.\n" - )); - return; - } - - if (Playing() || titledemo) - { - CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); - return; - } - - server = false; -/* - if (!stricmp(COM_Argv(1), "self")) - { - servernode = 0; - server = true; - /// \bug should be but... - //SV_SpawnServer(); - } - else -*/ - { - // used in menu to connect to a server in the list - if (netgame && !stricmp(COM_Argv(1), "node")) - { - servernode = (SINT8)atoi(COM_Argv(2)); - } - else if (netgame) - { - CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); - return; - } - else if (I_NetOpenSocket) - { - I_NetOpenSocket(); - netgame = true; - multiplayer = true; - - if (!stricmp(COM_Argv(1), "any")) - servernode = BROADCASTADDR; - else if (I_NetMakeNodewPort) - { - if (COM_Argc() >= 3) // address AND port - servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2)); - else // address only, or address:port - servernode = I_NetMakeNode(COM_Argv(1)); - } - else - { - CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n")); - D_CloseConnection(); - return; - } - } - else - CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n")); - } - - splitscreen = false; - SplitScreen_OnChange(); - botingame = false; - botskin = 0; - CL_ConnectToServer(); -} - void ResetNode(INT32 node) { memset(&netnodes[node], 0, sizeof(*netnodes)); @@ -527,20 +290,6 @@ void CL_Reset(void) // D_StartTitle should get done now, but the calling function will handle it } -static void Command_GetPlayerNum(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - if (serverplayer == i) - CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); - else - CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); - } -} - SINT8 nametonum(const char *name) { INT32 playernum, i; @@ -570,213 +319,6 @@ SINT8 nametonum(const char *name) return -1; } -/** Lists all players and their player numbers. - * - * \sa Command_GetPlayerNum - */ -static void Command_Nodes(void) -{ - INT32 i; - size_t maxlen = 0; - const char *address; - - for (i = 0; i < MAXPLAYERS; i++) - { - const size_t plen = strlen(player_names[i]); - if (playeringame[i] && plen > maxlen) - maxlen = plen; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); - - if (playernode[i] != UINT8_MAX) - { - CONS_Printf(" - node %.2d", playernode[i]); - if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) - CONS_Printf(" - %s", address); - } - - if (IsPlayerAdmin(i)) - CONS_Printf(M_GetText(" (verified admin)")); - - if (players[i].spectator) - CONS_Printf(M_GetText(" (spectator)")); - - CONS_Printf("\n"); - } - } -} - -static void Command_Ban(void) -{ - if (COM_Argc() < 2) - { - CONS_Printf(M_GetText("Ban : ban and kick a player\n")); - return; - } - - if (!netgame) // Don't kick Tails in splitscreen! - { - CONS_Printf(M_GetText("This only works in a netgame.\n")); - return; - } - - if (server || IsPlayerAdmin(consoleplayer)) - { - UINT8 buf[3 + MAX_REASONLENGTH]; - UINT8 *p = buf; - const SINT8 pn = nametonum(COM_Argv(1)); - const INT32 node = playernode[(INT32)pn]; - - if (pn == -1 || pn == 0) - return; - - WRITEUINT8(p, pn); - - if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now - { - CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); - WRITEUINT8(p, KICK_MSG_GO_AWAY); - SendNetXCmd(XD_KICK, &buf, 2); - } - else - { - if (server) // only the server is allowed to do this right now - { - Ban_Add(COM_Argv(2)); - D_SaveBan(); // save the ban list - } - - if (COM_Argc() == 2) - { - WRITEUINT8(p, KICK_MSG_BANNED); - SendNetXCmd(XD_KICK, &buf, 2); - } - else - { - size_t i, j = COM_Argc(); - char message[MAX_REASONLENGTH]; - - //Steal from the motd code so you don't have to put the reason in quotes. - strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) - { - strlcat(message, " ", sizeof message); - strlcat(message, COM_Argv(i), sizeof message); - } - - WRITEUINT8(p, KICK_MSG_CUSTOM_BAN); - WRITESTRINGN(p, message, MAX_REASONLENGTH); - SendNetXCmd(XD_KICK, &buf, p - buf); - } - } - } - else - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - -} - -static void Command_BanIP(void) -{ - if (COM_Argc() < 2) - { - CONS_Printf(M_GetText("banip : ban an ip address\n")); - return; - } - - if (server) // Only the server can use this, otherwise does nothing. - { - const char *address = (COM_Argv(1)); - const char *reason; - - if (COM_Argc() == 2) - reason = NULL; - else - reason = COM_Argv(2); - - - if (I_SetBanAddress && I_SetBanAddress(address, NULL)) - { - if (reason) - CONS_Printf("Banned IP address %s for: %s\n", address, reason); - else - CONS_Printf("Banned IP address %s\n", address); - - Ban_Add(reason); - D_SaveBan(); - } - else - { - return; - } - } -} - -static void Command_Kick(void) -{ - if (COM_Argc() < 2) - { - CONS_Printf(M_GetText("kick : kick a player\n")); - return; - } - - if (!netgame) // Don't kick Tails in splitscreen! - { - CONS_Printf(M_GetText("This only works in a netgame.\n")); - return; - } - - if (server || IsPlayerAdmin(consoleplayer)) - { - UINT8 buf[3 + MAX_REASONLENGTH]; - UINT8 *p = buf; - const SINT8 pn = nametonum(COM_Argv(1)); - - if (pn == -1 || pn == 0) - return; - - // Special case if we are trying to kick a player who is downloading the game state: - // trigger a timeout instead of kicking them, because a kick would only - // take effect after they have finished downloading - if (server && playernode[pn] != UINT8_MAX && netnodes[playernode[pn]].sendingsavegame) - { - Net_ConnectionTimeout(playernode[pn]); - return; - } - - WRITESINT8(p, pn); - - if (COM_Argc() == 2) - { - WRITEUINT8(p, KICK_MSG_GO_AWAY); - SendNetXCmd(XD_KICK, &buf, 2); - } - else - { - size_t i, j = COM_Argc(); - char message[MAX_REASONLENGTH]; - - //Steal from the motd code so you don't have to put the reason in quotes. - strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) - { - strlcat(message, " ", sizeof message); - strlcat(message, COM_Argv(i), sizeof message); - } - - WRITEUINT8(p, KICK_MSG_CUSTOM_KICK); - WRITESTRINGN(p, message, MAX_REASONLENGTH); - SendNetXCmd(XD_KICK, &buf, p - buf); - } - } - else - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); -} - static void Got_KickCmd(UINT8 **p, INT32 playernum) { INT32 pnum, msg; diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h index 857c3463c..039f5b3b4 100644 --- a/src/netcode/d_net.h +++ b/src/netcode/d_net.h @@ -68,7 +68,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength); boolean HGetPacket(void); void D_SetDoomcom(void); -void D_SaveBan(void); boolean D_CheckNetGame(void); void D_CloseConnection(void); void Net_UnAcknowledgePacket(INT32 node); From 2c6bb7172678ac54ccbdd2eabc0cd0c9a00ea726 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 13 Jan 2023 22:05:57 +0100 Subject: [PATCH 55/93] Reorder functions in d_clisrv.c --- src/netcode/d_clisrv.c | 1249 ++++++++++++++++++++-------------------- 1 file changed, 623 insertions(+), 626 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 506de8c02..1658856b6 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -83,6 +83,7 @@ UINT8 playernode[MAXPLAYERS]; UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. +static INT32 pingtimeout[MAXPLAYERS]; tic_t servermaxping = 800; // server's max ping. Defaults to 800 tic_t maketic; @@ -120,137 +121,6 @@ void ResetNode(INT32 node) netnodes[node].player2 = -1; } -// -// CL_ClearPlayer -// -// Clears the player data so that a future client can use this slot -// -void CL_ClearPlayer(INT32 playernum) -{ - if (players[playernum].mo) - P_RemoveMobj(players[playernum].mo); - memset(&players[playernum], 0, sizeof (player_t)); - memset(playeraddress[playernum], 0, sizeof(*playeraddress)); -} - -static void UnlinkPlayerFromNode(INT32 playernum) -{ - INT32 node = playernode[playernum]; - - if (node == UINT8_MAX) - return; - - playernode[playernum] = UINT8_MAX; - - netnodes[node].numplayers--; - if (netnodes[node].numplayers <= 0) - { - netnodes[node].ingame = false; - Net_CloseConnection(node); - ResetNode(node); - } -} - -// If in a special stage, redistribute the player's -// spheres across the remaining players. -// I feel like this shouldn't even be in this file at all, but well. -static void RedistributeSpecialStageSpheres(INT32 playernum) -{ - if (!G_IsSpecialStage(gamemap) || D_NumPlayers() <= 1) - return; - - INT32 count = D_NumPlayers() - 1; - INT32 spheres = players[playernum].spheres; - INT32 rings = players[playernum].rings; - - while (spheres || rings) - { - INT32 sincrement = max(spheres / count, 1); - INT32 rincrement = max(rings / count, 1); - - INT32 i, n; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || i == playernum) - continue; - - n = min(spheres, sincrement); - P_GivePlayerSpheres(&players[i], n); - spheres -= n; - - n = min(rings, rincrement); - P_GivePlayerRings(&players[i], n); - rings -= n; - } - } -} - -// -// CL_RemovePlayer -// -// Removes a player from the current game -// -void CL_RemovePlayer(INT32 playernum, kickreason_t reason) -{ - // Sanity check: exceptional cases (i.e. c-fails) can cause multiple - // kick commands to be issued for the same player. - if (!playeringame[playernum]) - return; - - if (server) - UnlinkPlayerFromNode(playernum); - - if (gametyperules & GTR_TEAMFLAGS) - P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! - - RedistributeSpecialStageSpheres(playernum); - - LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting - - // don't look through someone's view who isn't there - if (playernum == displayplayer) - { - // Call ViewpointSwitch hooks here. - // The viewpoint was forcibly changed. - LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); - displayplayer = consoleplayer; - } - - // Reset player data - CL_ClearPlayer(playernum); - - // remove avatar of player - playeringame[playernum] = false; - while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1) - doomcom->numslots--; - - // Reset the name - sprintf(player_names[playernum], "Player %d", playernum+1); - - player_name_changes[playernum] = 0; - - if (IsPlayerAdmin(playernum)) - { - RemoveAdminPlayer(playernum); // don't stay admin after you're gone - } - - LUA_InvalidatePlayer(&players[playernum]); - - if (G_TagGametype()) //Check if you still have a game. Location flexible. =P - P_CheckSurvivors(); - else if (gametyperules & GTR_RACE) - P_CheckRacers(); -} - -void CL_HandleTimeout(void) -{ - LUA_HookBool(false, HOOK(GameQuit)); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); -} - void CL_Reset(void) { if (metalrecording) @@ -290,33 +160,181 @@ void CL_Reset(void) // D_StartTitle should get done now, but the calling function will handle it } -SINT8 nametonum(const char *name) +// +// CL_ClearPlayer +// +// Clears the player data so that a future client can use this slot +// +void CL_ClearPlayer(INT32 playernum) { - INT32 playernum, i; + if (players[playernum].mo) + P_RemoveMobj(players[playernum].mo); + memset(&players[playernum], 0, sizeof (player_t)); + memset(playeraddress[playernum], 0, sizeof(*playeraddress)); +} - if (!strcmp(name, "0")) - return 0; +// Xcmd XD_ADDPLAYER +static void Got_AddPlayer(UINT8 **p, INT32 playernum) +{ + INT16 node, newplayernum; + boolean splitscreenplayer; + boolean rejoined; + player_t *newplayer; - playernum = (SINT8)atoi(name); - - if (playernum < 0 || playernum >= MAXPLAYERS) - return -1; - - if (playernum) + if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { - if (playeringame[playernum]) - return (SINT8)playernum; - else - return -1; + // protect against hacked/buggy client + CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; } - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !stricmp(player_names[i], name)) - return (SINT8)i; + node = READUINT8(*p); + newplayernum = READUINT8(*p); + splitscreenplayer = newplayernum & 0x80; + newplayernum &= ~0x80; - CONS_Printf(M_GetText("There is no player named \"%s\"\n"), name); + rejoined = playeringame[newplayernum]; - return -1; + if (!rejoined) + { + // Clear player before joining, lest some things get set incorrectly + // HACK: don't do this for splitscreen, it relies on preset values + if (!splitscreen && !botingame) + CL_ClearPlayer(newplayernum); + playeringame[newplayernum] = true; + G_AddPlayer(newplayernum); + if (newplayernum+1 > doomcom->numslots) + doomcom->numslots = (INT16)(newplayernum+1); + + if (server && I_GetNodeAddress) + { + const char *address = I_GetNodeAddress(node); + char *port = NULL; + if (address) // MI: fix msvcrt.dll!_mbscat crash? + { + strcpy(playeraddress[newplayernum], address); + port = strchr(playeraddress[newplayernum], ':'); + if (port) + *port = '\0'; + } + } + } + + newplayer = &players[newplayernum]; + + newplayer->jointime = 0; + newplayer->quittime = 0; + + READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); + + // the server is creating my player + if (node == mynode) + { + playernode[newplayernum] = 0; // for information only + if (!splitscreenplayer) + { + consoleplayer = newplayernum; + displayplayer = newplayernum; + secondarydisplayplayer = newplayernum; + DEBFILE("spawning me\n"); + ticcmd_oldangleturn[0] = newplayer->oldrelangleturn; + } + else + { + secondarydisplayplayer = newplayernum; + DEBFILE("spawning my brother\n"); + if (botingame) + newplayer->bot = 1; + ticcmd_oldangleturn[1] = newplayer->oldrelangleturn; + } + P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16)); + D_SendPlayerConfig(); + addedtogame = true; + + if (rejoined) + { + if (newplayer->mo) + { + newplayer->viewheight = 41*newplayer->height/48; + + if (newplayer->mo->eflags & MFE_VERTICALFLIP) + newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight; + else + newplayer->viewz = newplayer->mo->z + newplayer->viewheight; + } + + // wake up the status bar + ST_Start(); + // wake up the heads up text + HU_Start(); + + if (camera.chase && !splitscreenplayer) + P_ResetCamera(newplayer, &camera); + if (camera2.chase && splitscreenplayer) + P_ResetCamera(newplayer, &camera2); + } + } + + if (netgame) + { + char joinmsg[256]; + + if (rejoined) + strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)")); + else + strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)")); + strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); + + // Merge join notification + IP to avoid clogging console/chat + if (server && cv_showjoinaddress.value && I_GetNodeAddress) + { + const char *address = I_GetNodeAddress(node); + if (address) + strcat(joinmsg, va(" (%s)", address)); + } + + HU_AddChatText(joinmsg, false); + } + + if (server && multiplayer && motd[0] != '\0') + COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); + + if (!rejoined) + LUA_HookInt(newplayernum, HOOK(PlayerJoin)); +} + +static void UnlinkPlayerFromNode(INT32 playernum) +{ + INT32 node = playernode[playernum]; + + if (node == UINT8_MAX) + return; + + playernode[playernum] = UINT8_MAX; + + netnodes[node].numplayers--; + if (netnodes[node].numplayers <= 0) + { + netnodes[node].ingame = false; + Net_CloseConnection(node); + ResetNode(node); + } +} + +static void PT_ClientQuit(SINT8 node, INT32 netconsole) +{ + if (client) + return; + + if (netnodes[node].ingame && netconsole != -1 && playeringame[netconsole]) + SendKicksForNode(node, KICK_MSG_PLAYER_QUIT | KICK_MSG_KEEP_BODY); + + Net_CloseConnection(node); + netnodes[node].ingame = false; + netnodes[node].player = -1; + netnodes[node].player2 = -1; } static void Got_KickCmd(UINT8 **p, INT32 playernum) @@ -510,47 +528,175 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -static void Got_AddPlayer(UINT8 **p, INT32 playernum); - -// called one time at init -void D_ClientServerInit(void) +// If in a special stage, redistribute the player's +// spheres across the remaining players. +// I feel like this shouldn't even be in this file at all, but well. +static void RedistributeSpecialStageSpheres(INT32 playernum) { - DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", - VERSION/100, VERSION%100, SUBVERSION)); + if (!G_IsSpecialStage(gamemap) || D_NumPlayers() <= 1) + return; - COM_AddCommand("getplayernum", Command_GetPlayerNum); - COM_AddCommand("kick", Command_Kick); - COM_AddCommand("ban", Command_Ban); - COM_AddCommand("banip", Command_BanIP); - COM_AddCommand("clearbans", Command_ClearBans); - COM_AddCommand("showbanlist", Command_ShowBan); - COM_AddCommand("reloadbans", Command_ReloadBan); - COM_AddCommand("connect", Command_connect); - COM_AddCommand("nodes", Command_Nodes); - COM_AddCommand("resendgamestate", Command_ResendGamestate); -#ifdef PACKETDROP - COM_AddCommand("drop", Command_Drop); - COM_AddCommand("droprate", Command_Droprate); + INT32 count = D_NumPlayers() - 1; + INT32 spheres = players[playernum].spheres; + INT32 rings = players[playernum].rings; + + while (spheres || rings) + { + INT32 sincrement = max(spheres / count, 1); + INT32 rincrement = max(rings / count, 1); + + INT32 i, n; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || i == playernum) + continue; + + n = min(spheres, sincrement); + P_GivePlayerSpheres(&players[i], n); + spheres -= n; + + n = min(rings, rincrement); + P_GivePlayerRings(&players[i], n); + rings -= n; + } + } +} + +// +// CL_RemovePlayer +// +// Removes a player from the current game +// +void CL_RemovePlayer(INT32 playernum, kickreason_t reason) +{ + // Sanity check: exceptional cases (i.e. c-fails) can cause multiple + // kick commands to be issued for the same player. + if (!playeringame[playernum]) + return; + + if (server) + UnlinkPlayerFromNode(playernum); + + if (gametyperules & GTR_TEAMFLAGS) + P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! + + RedistributeSpecialStageSpheres(playernum); + + LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting + + // don't look through someone's view who isn't there + if (playernum == displayplayer) + { + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + displayplayer = consoleplayer; + } + + // Reset player data + CL_ClearPlayer(playernum); + + // remove avatar of player + playeringame[playernum] = false; + while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1) + doomcom->numslots--; + + // Reset the name + sprintf(player_names[playernum], "Player %d", playernum+1); + + player_name_changes[playernum] = 0; + + if (IsPlayerAdmin(playernum)) + { + RemoveAdminPlayer(playernum); // don't stay admin after you're gone + } + + LUA_InvalidatePlayer(&players[playernum]); + + if (G_TagGametype()) //Check if you still have a game. Location flexible. =P + P_CheckSurvivors(); + else if (gametyperules & GTR_RACE) + P_CheckRacers(); +} + +// +// D_QuitNetGame +// Called before quitting to leave a net game +// without hanging the other players +// +void D_QuitNetGame(void) +{ + mousegrabbedbylua = true; + I_UpdateMouseGrab(); + + if (!netgame || !netbuffer) + return; + + DEBFILE("===========================================================================\n" + " Quitting Game, closing connection\n" + "===========================================================================\n"); + + // abort send/receive of files + CloseNetFile(); + RemoveAllLuaFileTransfers(); + waitingforluafiletransfer = false; + waitingforluafilecommand = false; + + if (server) + { + INT32 i; + + netbuffer->packettype = PT_SERVERSHUTDOWN; + for (i = 0; i < MAXNETNODES; i++) + if (netnodes[i].ingame) + HSendPacket(i, true, 0, 0); +#ifdef MASTERSERVER + if (serverrunning && ms_RoomId > 0) + UnregisterServer(); #endif -#ifdef _DEBUG - COM_AddCommand("numnodes", Command_Numnodes); + } + else if (servernode > 0 && servernode < MAXNETNODES && netnodes[(UINT8)servernode].ingame) + { + netbuffer->packettype = PT_CLIENTQUIT; + HSendPacket(servernode, true, 0, 0); + } + + D_CloseConnection(); + ClearAdminPlayers(); + + DEBFILE("===========================================================================\n" + " Log finish\n" + "===========================================================================\n"); +#ifdef DEBUGFILE + if (debugfile) + { + fclose(debugfile); + debugfile = NULL; + } #endif +} - RegisterNetXCmd(XD_KICK, Got_KickCmd); - RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); -#ifdef DUMPCONSISTENCY - CV_RegisterVar(&cv_dumpconsistency); -#endif - Ban_Load_File(false); +void CL_HandleTimeout(void) +{ + LUA_HookBool(false, HOOK(GameQuit)); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); +} - gametic = 0; - localgametic = 0; +void CL_AddSplitscreenPlayer(void) +{ + if (cl_mode == CL_CONNECTED) + CL_SendJoin(); +} - // do not send anything before the real begin - SV_StopServer(); - SV_ResetServer(); - if (dedicated) - SV_SpawnServer(); +void CL_RemoveSplitscreenPlayer(void) +{ + if (cl_mode != CL_CONNECTED) + return; + + SendKick(secondarydisplayplayer, KICK_MSG_PLAYER_QUIT); } void SV_ResetServer(void) @@ -622,215 +768,6 @@ static inline void SV_GenContext(void) } } -// -// D_QuitNetGame -// Called before quitting to leave a net game -// without hanging the other players -// -void D_QuitNetGame(void) -{ - mousegrabbedbylua = true; - I_UpdateMouseGrab(); - - if (!netgame || !netbuffer) - return; - - DEBFILE("===========================================================================\n" - " Quitting Game, closing connection\n" - "===========================================================================\n"); - - // abort send/receive of files - CloseNetFile(); - RemoveAllLuaFileTransfers(); - waitingforluafiletransfer = false; - waitingforluafilecommand = false; - - if (server) - { - INT32 i; - - netbuffer->packettype = PT_SERVERSHUTDOWN; - for (i = 0; i < MAXNETNODES; i++) - if (netnodes[i].ingame) - HSendPacket(i, true, 0, 0); -#ifdef MASTERSERVER - if (serverrunning && ms_RoomId > 0) - UnregisterServer(); -#endif - } - else if (servernode > 0 && servernode < MAXNETNODES && netnodes[(UINT8)servernode].ingame) - { - netbuffer->packettype = PT_CLIENTQUIT; - HSendPacket(servernode, true, 0, 0); - } - - D_CloseConnection(); - ClearAdminPlayers(); - - DEBFILE("===========================================================================\n" - " Log finish\n" - "===========================================================================\n"); -#ifdef DEBUGFILE - if (debugfile) - { - fclose(debugfile); - debugfile = NULL; - } -#endif -} - -// Xcmd XD_ADDPLAYER -static void Got_AddPlayer(UINT8 **p, INT32 playernum) -{ - INT16 node, newplayernum; - boolean splitscreenplayer; - boolean rejoined; - player_t *newplayer; - - if (playernum != serverplayer && !IsPlayerAdmin(playernum)) - { - // protect against hacked/buggy client - CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); - if (server) - SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - return; - } - - node = READUINT8(*p); - newplayernum = READUINT8(*p); - splitscreenplayer = newplayernum & 0x80; - newplayernum &= ~0x80; - - rejoined = playeringame[newplayernum]; - - if (!rejoined) - { - // Clear player before joining, lest some things get set incorrectly - // HACK: don't do this for splitscreen, it relies on preset values - if (!splitscreen && !botingame) - CL_ClearPlayer(newplayernum); - playeringame[newplayernum] = true; - G_AddPlayer(newplayernum); - if (newplayernum+1 > doomcom->numslots) - doomcom->numslots = (INT16)(newplayernum+1); - - if (server && I_GetNodeAddress) - { - const char *address = I_GetNodeAddress(node); - char *port = NULL; - if (address) // MI: fix msvcrt.dll!_mbscat crash? - { - strcpy(playeraddress[newplayernum], address); - port = strchr(playeraddress[newplayernum], ':'); - if (port) - *port = '\0'; - } - } - } - - newplayer = &players[newplayernum]; - - newplayer->jointime = 0; - newplayer->quittime = 0; - - READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); - - // the server is creating my player - if (node == mynode) - { - playernode[newplayernum] = 0; // for information only - if (!splitscreenplayer) - { - consoleplayer = newplayernum; - displayplayer = newplayernum; - secondarydisplayplayer = newplayernum; - DEBFILE("spawning me\n"); - ticcmd_oldangleturn[0] = newplayer->oldrelangleturn; - } - else - { - secondarydisplayplayer = newplayernum; - DEBFILE("spawning my brother\n"); - if (botingame) - newplayer->bot = 1; - ticcmd_oldangleturn[1] = newplayer->oldrelangleturn; - } - P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16)); - D_SendPlayerConfig(); - addedtogame = true; - - if (rejoined) - { - if (newplayer->mo) - { - newplayer->viewheight = 41*newplayer->height/48; - - if (newplayer->mo->eflags & MFE_VERTICALFLIP) - newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight; - else - newplayer->viewz = newplayer->mo->z + newplayer->viewheight; - } - - // wake up the status bar - ST_Start(); - // wake up the heads up text - HU_Start(); - - if (camera.chase && !splitscreenplayer) - P_ResetCamera(newplayer, &camera); - if (camera2.chase && splitscreenplayer) - P_ResetCamera(newplayer, &camera2); - } - } - - if (netgame) - { - char joinmsg[256]; - - if (rejoined) - strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)")); - else - strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)")); - strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); - - // Merge join notification + IP to avoid clogging console/chat - if (server && cv_showjoinaddress.value && I_GetNodeAddress) - { - const char *address = I_GetNodeAddress(node); - if (address) - strcat(joinmsg, va(" (%s)", address)); - } - - HU_AddChatText(joinmsg, false); - } - - if (server && multiplayer && motd[0] != '\0') - COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); - - if (!rejoined) - LUA_HookInt(newplayernum, HOOK(PlayerJoin)); -} - -void CL_AddSplitscreenPlayer(void) -{ - if (cl_mode == CL_CONNECTED) - CL_SendJoin(); -} - -void CL_RemoveSplitscreenPlayer(void) -{ - if (cl_mode != CL_CONNECTED) - return; - - SendKick(secondarydisplayplayer, KICK_MSG_PLAYER_QUIT); -} - -// is there a game running -boolean Playing(void) -{ - return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); -} - void SV_SpawnServer(void) { if (demoplayback) @@ -860,6 +797,21 @@ void SV_SpawnServer(void) } } +// called at singleplayer start and stopdemo +void SV_StartSinglePlayerServer(void) +{ + server = true; + netgame = false; + multiplayer = false; + G_SetGametype(GT_COOP); + + // no more tic the game with this settings! + SV_StopServer(); + + if (splitscreen) + multiplayer = true; +} + void SV_StopServer(void) { tic_t i; @@ -881,21 +833,6 @@ void SV_StopServer(void) serverrunning = false; } -// called at singleplayer start and stopdemo -void SV_StartSinglePlayerServer(void) -{ - server = true; - netgame = false; - multiplayer = false; - G_SetGametype(GT_COOP); - - // no more tic the game with this settings! - SV_StopServer(); - - if (splitscreen) - multiplayer = true; -} - /** Called when a PT_SERVERSHUTDOWN packet is received * * \param node The packet sender (should be the server) @@ -948,20 +885,6 @@ static void PT_Login(SINT8 node, INT32 netconsole) #endif } -static void PT_ClientQuit(SINT8 node, INT32 netconsole) -{ - if (client) - return; - - if (netnodes[node].ingame && netconsole != -1 && playeringame[netconsole]) - SendKicksForNode(node, KICK_MSG_PLAYER_QUIT | KICK_MSG_KEEP_BODY); - - Net_CloseConnection(node); - netnodes[node].ingame = false; - netnodes[node].player = -1; - netnodes[node].player2 = -1; -} - static void PT_AskLuaFile(SINT8 node) { if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) @@ -974,6 +897,94 @@ static void PT_HasLuaFile(SINT8 node) SV_HandleLuaFileSent(node); } +static void PT_SendingLuaFile(SINT8 node) +{ + (void)node; + + if (client) + CL_PrepareDownloadLuaFile(); +} + +/* +Ping Update except better: +We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. +If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. +*/ + +static inline void PingUpdate(void) +{ + INT32 i; + boolean laggers[MAXPLAYERS]; + UINT8 numlaggers = 0; + memset(laggers, 0, sizeof(boolean) * MAXPLAYERS); + + netbuffer->packettype = PT_PING; + + //check for ping limit breakage. + if (cv_maxping.value) + { + for (i = 1; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].quittime + && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) + { + if (players[i].jointime > 30 * TICRATE) + laggers[i] = true; + numlaggers++; + } + else + pingtimeout[i] = 0; + } + + //kick lagging players... unless everyone but the server's ping sucks. + //in that case, it is probably the server's fault. + if (numlaggers < D_NumPlayers() - 1) + { + for (i = 1; i < MAXPLAYERS; i++) + { + if (playeringame[i] && laggers[i]) + { + pingtimeout[i]++; + // ok your net has been bad for too long, you deserve to die. + if (pingtimeout[i] > cv_pingtimeout.value) + { + pingtimeout[i] = 0; + SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY); + } + } + /* + you aren't lagging, + but you aren't free yet. + In case you'll keep spiking, + we just make the timer go back down. (Very unstable net must still get kicked). + */ + else + pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1); + } + } + } + + //make the ping packet and clear server data for next one + for (i = 0; i < MAXPLAYERS; i++) + { + netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; + //server takes a snapshot of the real ping for display. + //otherwise, pings fluctuate a lot and would be odd to look at. + playerpingtable[i] = realpingtable[i] / pingmeasurecount; + realpingtable[i] = 0; //Reset each as we go. + } + + // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. + netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; + + //send out our ping packets + for (i = 0; i < MAXNETNODES; i++) + if (netnodes[i].ingame) + HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); + + pingmeasurecount = 1; //Reset count +} + static void PT_Ping(SINT8 node, INT32 netconsole) { // Only accept PT_PING from the server. @@ -997,14 +1008,6 @@ static void PT_Ping(SINT8 node, INT32 netconsole) } } -static void PT_SendingLuaFile(SINT8 node) -{ - (void)node; - - if (client) - CL_PrepareDownloadLuaFile(); -} - /** Handles a packet received from a node that isn't in game * * \param node The packet sender @@ -1124,120 +1127,6 @@ void GetPackets(void) } } -// -// NetUpdate -// Builds ticcmds for console player, -// sends out a packet -// -// no more use random generator, because at very first tic isn't yet synchronized -// Note: It is called consistAncy on purpose. -// -INT16 Consistancy(void) -{ - INT32 i; - UINT32 ret = 0; -#ifdef MOBJCONSISTANCY - thinker_t *th; - mobj_t *mo; -#endif - - DEBFILE(va("TIC %u ", gametic)); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - ret ^= 0xCCCC; - else if (!players[i].mo); - else - { - ret += players[i].mo->x; - ret -= players[i].mo->y; - ret += players[i].powers[pw_shield]; - ret *= i+1; - } - } - // I give up - // Coop desynching enemies is painful - if (!G_PlatformGametype()) - ret += P_GetRandSeed(); - -#ifdef MOBJCONSISTANCY - if (gamestate == GS_LEVEL) - { - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo = (mobj_t *)th; - - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) - { - ret -= mo->type; - ret += mo->x; - ret -= mo->y; - ret += mo->z; - ret -= mo->momx; - ret += mo->momy; - ret -= mo->momz; - ret += mo->angle; - ret -= mo->flags; - ret += mo->flags2; - ret -= mo->eflags; - if (mo->target) - { - ret += mo->target->type; - ret -= mo->target->x; - ret += mo->target->y; - ret -= mo->target->z; - ret += mo->target->momx; - ret -= mo->target->momy; - ret += mo->target->momz; - ret -= mo->target->angle; - ret += mo->target->flags; - ret -= mo->target->flags2; - ret += mo->target->eflags; - ret -= mo->target->state - states; - ret += mo->target->tics; - ret -= mo->target->sprite; - ret += mo->target->frame; - } - else - ret ^= 0x3333; - if (mo->tracer && mo->tracer->type != MT_OVERLAY) - { - ret += mo->tracer->type; - ret -= mo->tracer->x; - ret += mo->tracer->y; - ret -= mo->tracer->z; - ret += mo->tracer->momx; - ret -= mo->tracer->momy; - ret += mo->tracer->momz; - ret -= mo->tracer->angle; - ret += mo->tracer->flags; - ret -= mo->tracer->flags2; - ret += mo->tracer->eflags; - ret -= mo->tracer->state - states; - ret += mo->tracer->tics; - ret -= mo->tracer->sprite; - ret += mo->tracer->frame; - } - else - ret ^= 0xAAAA; - ret -= mo->state - states; - ret += mo->tics; - ret -= mo->sprite; - ret += mo->frame; - } - } - } -#endif - - DEBFILE(va("Consistancy = %u\n", (ret & 0xFFFF))); - - return (INT16)(ret & 0xFFFF); -} - boolean TryRunTics(tic_t realtics) { // the machine has lagged but it is not so bad @@ -1331,88 +1220,6 @@ boolean TryRunTics(tic_t realtics) } } -/* -Ping Update except better: -We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. -If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. -*/ - -static INT32 pingtimeout[MAXPLAYERS]; - -static inline void PingUpdate(void) -{ - INT32 i; - boolean laggers[MAXPLAYERS]; - UINT8 numlaggers = 0; - memset(laggers, 0, sizeof(boolean) * MAXPLAYERS); - - netbuffer->packettype = PT_PING; - - //check for ping limit breakage. - if (cv_maxping.value) - { - for (i = 1; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].quittime - && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) - { - if (players[i].jointime > 30 * TICRATE) - laggers[i] = true; - numlaggers++; - } - else - pingtimeout[i] = 0; - } - - //kick lagging players... unless everyone but the server's ping sucks. - //in that case, it is probably the server's fault. - if (numlaggers < D_NumPlayers() - 1) - { - for (i = 1; i < MAXPLAYERS; i++) - { - if (playeringame[i] && laggers[i]) - { - pingtimeout[i]++; - // ok your net has been bad for too long, you deserve to die. - if (pingtimeout[i] > cv_pingtimeout.value) - { - pingtimeout[i] = 0; - SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY); - } - } - /* - you aren't lagging, - but you aren't free yet. - In case you'll keep spiking, - we just make the timer go back down. (Very unstable net must still get kicked). - */ - else - pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1); - } - } - } - - //make the ping packet and clear server data for next one - for (i = 0; i < MAXPLAYERS; i++) - { - netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; - //server takes a snapshot of the real ping for display. - //otherwise, pings fluctuate a lot and would be odd to look at. - playerpingtable[i] = realpingtable[i] / pingmeasurecount; - realpingtable[i] = 0; //Reset each as we go. - } - - // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. - netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; - - //send out our ping packets - for (i = 0; i < MAXNETNODES; i++) - if (netnodes[i].ingame) - HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); - - pingmeasurecount = 1; //Reset count -} - void NetUpdate(void) { static tic_t gametime = 0; @@ -1537,6 +1344,82 @@ void NetUpdate(void) FileSendTicker(); } +// called one time at init +void D_ClientServerInit(void) +{ + DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", + VERSION/100, VERSION%100, SUBVERSION)); + + COM_AddCommand("getplayernum", Command_GetPlayerNum); + COM_AddCommand("kick", Command_Kick); + COM_AddCommand("ban", Command_Ban); + COM_AddCommand("banip", Command_BanIP); + COM_AddCommand("clearbans", Command_ClearBans); + COM_AddCommand("showbanlist", Command_ShowBan); + COM_AddCommand("reloadbans", Command_ReloadBan); + COM_AddCommand("connect", Command_connect); + COM_AddCommand("nodes", Command_Nodes); + COM_AddCommand("resendgamestate", Command_ResendGamestate); +#ifdef PACKETDROP + COM_AddCommand("drop", Command_Drop); + COM_AddCommand("droprate", Command_Droprate); +#endif +#ifdef _DEBUG + COM_AddCommand("numnodes", Command_Numnodes); +#endif + + RegisterNetXCmd(XD_KICK, Got_KickCmd); + RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); +#ifdef DUMPCONSISTENCY + CV_RegisterVar(&cv_dumpconsistency); +#endif + Ban_Load_File(false); + + gametic = 0; + localgametic = 0; + + // do not send anything before the real begin + SV_StopServer(); + SV_ResetServer(); + if (dedicated) + SV_SpawnServer(); +} + +SINT8 nametonum(const char *name) +{ + INT32 playernum, i; + + if (!strcmp(name, "0")) + return 0; + + playernum = (SINT8)atoi(name); + + if (playernum < 0 || playernum >= MAXPLAYERS) + return -1; + + if (playernum) + { + if (playeringame[playernum]) + return (SINT8)playernum; + else + return -1; + } + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && !stricmp(player_names[i], name)) + return (SINT8)i; + + CONS_Printf(M_GetText("There is no player named \"%s\"\n"), name); + + return -1; +} + +// is there a game running +boolean Playing(void) +{ + return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); +} + /** Returns the number of players playing. * \return Number of players. Can be zero if we're running a ::dedicated * server. @@ -1551,6 +1434,120 @@ INT32 D_NumPlayers(void) return num; } +// +// NetUpdate +// Builds ticcmds for console player, +// sends out a packet +// +// no more use random generator, because at very first tic isn't yet synchronized +// Note: It is called consistAncy on purpose. +// +INT16 Consistancy(void) +{ + INT32 i; + UINT32 ret = 0; +#ifdef MOBJCONSISTANCY + thinker_t *th; + mobj_t *mo; +#endif + + DEBFILE(va("TIC %u ", gametic)); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + ret ^= 0xCCCC; + else if (!players[i].mo); + else + { + ret += players[i].mo->x; + ret -= players[i].mo->y; + ret += players[i].powers[pw_shield]; + ret *= i+1; + } + } + // I give up + // Coop desynching enemies is painful + if (!G_PlatformGametype()) + ret += P_GetRandSeed(); + +#ifdef MOBJCONSISTANCY + if (gamestate == GS_LEVEL) + { + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + { + ret -= mo->type; + ret += mo->x; + ret -= mo->y; + ret += mo->z; + ret -= mo->momx; + ret += mo->momy; + ret -= mo->momz; + ret += mo->angle; + ret -= mo->flags; + ret += mo->flags2; + ret -= mo->eflags; + if (mo->target) + { + ret += mo->target->type; + ret -= mo->target->x; + ret += mo->target->y; + ret -= mo->target->z; + ret += mo->target->momx; + ret -= mo->target->momy; + ret += mo->target->momz; + ret -= mo->target->angle; + ret += mo->target->flags; + ret -= mo->target->flags2; + ret += mo->target->eflags; + ret -= mo->target->state - states; + ret += mo->target->tics; + ret -= mo->target->sprite; + ret += mo->target->frame; + } + else + ret ^= 0x3333; + if (mo->tracer && mo->tracer->type != MT_OVERLAY) + { + ret += mo->tracer->type; + ret -= mo->tracer->x; + ret += mo->tracer->y; + ret -= mo->tracer->z; + ret += mo->tracer->momx; + ret -= mo->tracer->momy; + ret += mo->tracer->momz; + ret -= mo->tracer->angle; + ret += mo->tracer->flags; + ret -= mo->tracer->flags2; + ret += mo->tracer->eflags; + ret -= mo->tracer->state - states; + ret += mo->tracer->tics; + ret -= mo->tracer->sprite; + ret += mo->tracer->frame; + } + else + ret ^= 0xAAAA; + ret -= mo->state - states; + ret += mo->tics; + ret -= mo->sprite; + ret += mo->frame; + } + } + } +#endif + + DEBFILE(va("Consistancy = %u\n", (ret & 0xFFFF))); + + return (INT16)(ret & 0xFFFF); +} + tic_t GetLag(INT32 node) { return gametic - netnodes[node].tic; From 684382fc5e18de501b88ab292b1a7c81bbc78843 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 13 Jan 2023 22:28:03 +0100 Subject: [PATCH 56/93] Add missing include directive --- src/sdl/i_system.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 50ceae34c..38769e667 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -194,6 +194,7 @@ static char returnWadPath[256]; #include "../i_threads.h" #include "../screen.h" //vid.WndParent #include "../netcode/d_net.h" +#include "../netcode/commands.h" #include "../g_game.h" #include "../filesrch.h" #include "endtxt.h" From 715893ad25ba2c5077de8c60b9516edd822da954 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 14:49:33 +0100 Subject: [PATCH 57/93] Split PT_ClientCmd into functions --- src/netcode/tic_command.c | 95 +++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index bab0fad0a..417a2fdfd 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -103,6 +103,55 @@ void D_ResetTiccmds(void) D_Clearticcmd(textcmds[i]->tic); } +// Check ticcmd for "speed hacks" +static void CheckTiccmdHacks(INT32 playernum) +{ + ticcmd_t *cmd = &netcmds[maketic%BACKUPTICS][playernum]; + if (cmd->forwardmove > MAXPLMOVE || cmd->forwardmove < -MAXPLMOVE + || cmd->sidemove > MAXPLMOVE || cmd->sidemove < -MAXPLMOVE) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernum); + SendKick(playernum, KICK_MSG_CON_FAIL); + } +} + +// Check player consistancy during the level +static void CheckConsistancy(SINT8 nodenum, tic_t tic) +{ + netnode_t *node = &netnodes[nodenum]; + INT16 neededconsistancy = consistancy[tic%BACKUPTICS]; + INT16 clientconsistancy = SHORT(netbuffer->u.clientpak.consistancy); + + if (tic > gametic || tic + BACKUPTICS - 1 <= gametic || gamestate != GS_LEVEL + || neededconsistancy == clientconsistancy || SV_ResendingSavegameToAnyone() + || node->resendingsavegame || node->savegameresendcooldown > I_GetTime()) + return; + + if (cv_resynchattempts.value) + { + // Tell the client we are about to resend them the gamestate + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + HSendPacket(nodenum, true, 0, 0); + + node->resendingsavegame = true; + + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + node->player+1, player_names[node->player], + neededconsistancy, clientconsistancy); + + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + node->player, tic, neededconsistancy, clientconsistancy)); + } + else + { + SendKick(node->player, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", + node->player, tic, neededconsistancy, clientconsistancy)); + } +} + void PT_ClientCmd(SINT8 node, INT32 netconsole) { tic_t realend, realstart; @@ -143,56 +192,14 @@ void PT_ClientCmd(SINT8 node, INT32 netconsole) // Copy ticcmd G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); - // Check ticcmd for "speed hacks" - if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) - { - CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); - //D_Clearticcmd(k); - - SendKick(netconsole, KICK_MSG_CON_FAIL); - return; - } - // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) && netnodes[node].player2 >= 0) G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)netnodes[node].player2], &netbuffer->u.client2pak.cmd2, 1); - // Check player consistancy during the level - if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) - && !SV_ResendingSavegameToAnyone() - && !netnodes[node].resendingsavegame && netnodes[node].savegameresendcooldown <= I_GetTime()) - { - if (cv_resynchattempts.value) - { - // Tell the client we are about to resend them the gamestate - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - HSendPacket(node, true, 0, 0); - - netnodes[node].resendingsavegame = true; - - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), - netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy)); - DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - return; - } - else - { - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - return; - } - } + CheckTiccmdHacks(netconsole); + CheckConsistancy(node, realstart); } void PT_ServerTics(SINT8 node, INT32 netconsole) From 2639dc176df55f14a5fa1310554d4d768da2d8c3 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 14:52:13 +0100 Subject: [PATCH 58/93] Move net command copying to a new function --- src/netcode/net_command.c | 20 ++++++++++++++++++++ src/netcode/net_command.h | 1 + src/netcode/tic_command.c | 21 +++------------------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 13477d42d..227b78660 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -304,6 +304,26 @@ void PT_TextCmd(SINT8 node, INT32 netconsole) } } +void SV_CopyNetCommandsToServerPacket(tic_t tic) +{ + servertics_pak *packet = &netbuffer->u.serverpak; + UINT8 *cmds = (UINT8*)&packet->cmds[packet->numslots * packet->numtics]; + UINT8 numcmds; + + numcmds = *cmds++; + + for (UINT32 i = 0; i < numcmds; i++) + { + INT32 playernum = *cmds++; // playernum + size_t size = cmds[0]+1; + + if (tic >= gametic) // Don't copy old net commands + M_Memcpy(D_GetTextcmd(tic, playernum), cmds, size); + cmds += size; + } +} + +void CL_SendNetCommands(void) void SendKick(UINT8 playernum, UINT8 msg) { UINT8 buf[2]; diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index f1b4b2f3f..a9447ed7a 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -57,6 +57,7 @@ void ExtraDataTicker(void); size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); +void SV_CopyNetCommandsToServerPacket(tic_t tic); void SendKick(UINT8 playernum, UINT8 msg); void SendKicksForNode(SINT8 node, UINT8 msg); diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 417a2fdfd..2eb3b10ac 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -204,7 +204,6 @@ void PT_ClientCmd(SINT8 node, INT32 netconsole) void PT_ServerTics(SINT8 node, INT32 netconsole) { - UINT8 *pak, *txtpak, numtxtpak; tic_t realend, realstart; if (!netnodes[node].ingame) @@ -230,19 +229,15 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) realstart = netbuffer->u.serverpak.starttic; realend = realstart + netbuffer->u.serverpak.numtics; - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; - if (realend > gametic + CLIENTBACKUPTICS) realend = gametic + CLIENTBACKUPTICS; cl_packetmissed = realstart > neededtic; if (realstart <= neededtic && realend > neededtic) { - tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + UINT8 *pak = (UINT8 *)&netbuffer->u.serverpak.cmds; - for (i = realstart; i < realend; i++) + for (tic_t i = realstart; i < realend; i++) { // clear first D_Clearticcmd(i); @@ -251,17 +246,7 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - // copy the textcmds - numtxtpak = *txtpak++; - for (j = 0; j < numtxtpak; j++) - { - INT32 k = *txtpak++; // playernum - const size_t txtsize = txtpak[0]+1; - - if (i >= gametic) // Don't copy old net commands - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); - txtpak += txtsize; - } + SV_CopyNetCommandsToServerPacket(i); } neededtic = realend; From e4c403408b1b3a306b316c135a91e0121c44a33e Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 14:53:27 +0100 Subject: [PATCH 59/93] Move net command sending to a new function --- src/netcode/net_command.c | 22 ++++++++++++++++++++++ src/netcode/net_command.h | 1 + src/netcode/tic_command.c | 22 +--------------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 227b78660..9e089a1a2 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -324,6 +324,28 @@ void SV_CopyNetCommandsToServerPacket(tic_t tic) } void CL_SendNetCommands(void) +{ + // Send extra data if needed + if (localtextcmd[0]) + { + netbuffer->packettype = PT_TEXTCMD; + M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... + localtextcmd[0] = 0; + } + + // Send extra data if needed for player 2 (splitscreen) + if (localtextcmd2[0]) + { + netbuffer->packettype = PT_TEXTCMD2; + M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... + localtextcmd2[0] = 0; + } +} + void SendKick(UINT8 playernum, UINT8 msg) { UINT8 buf[2]; diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index a9447ed7a..3a433ebe4 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -58,6 +58,7 @@ size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); void SV_CopyNetCommandsToServerPacket(tic_t tic); +void CL_SendNetCommands(void); void SendKick(UINT8 playernum, UINT8 msg); void SendKicksForNode(SINT8 node, UINT8 msg); diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 2eb3b10ac..76d46451f 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -295,27 +295,7 @@ void CL_SendClientCmd(void) } if (cl_mode == CL_CONNECTED || dedicated) - { - // Send extra data if needed - if (localtextcmd[0]) - { - netbuffer->packettype = PT_TEXTCMD; - M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); - // All extra data have been sent - if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... - localtextcmd[0] = 0; - } - - // Send extra data if needed for player 2 (splitscreen) - if (localtextcmd2[0]) - { - netbuffer->packettype = PT_TEXTCMD2; - M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); - // All extra data have been sent - if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... - localtextcmd2[0] = 0; - } - } + CL_SendNetCommands(); } // send the server packet From a69204b609376532eacb255199e628d791904fa5 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 15:14:09 +0100 Subject: [PATCH 60/93] Fix function name --- src/netcode/net_command.c | 2 +- src/netcode/net_command.h | 2 +- src/netcode/tic_command.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 9e089a1a2..98c578b79 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -304,7 +304,7 @@ void PT_TextCmd(SINT8 node, INT32 netconsole) } } -void SV_CopyNetCommandsToServerPacket(tic_t tic) +void CL_CopyNetCommandsFromServerPacket(tic_t tic) { servertics_pak *packet = &netbuffer->u.serverpak; UINT8 *cmds = (UINT8*)&packet->cmds[packet->numslots * packet->numtics]; diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index 3a433ebe4..0e8339ef7 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -57,7 +57,7 @@ void ExtraDataTicker(void); size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); -void SV_CopyNetCommandsToServerPacket(tic_t tic); +void CL_CopyNetCommandsFromServerPacket(tic_t tic); void CL_SendNetCommands(void); void SendKick(UINT8 playernum, UINT8 msg); void SendKicksForNode(SINT8 node, UINT8 msg); diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 76d46451f..6b237ed61 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -246,7 +246,7 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - SV_CopyNetCommandsToServerPacket(i); + CL_CopyNetCommandsFromServerPacket(i); } neededtic = realend; From 8df0debd541a253a2161267bc77cba1823184852 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 19:01:36 +0100 Subject: [PATCH 61/93] Split SV_SendTics into functions --- src/netcode/net_command.c | 21 +++++++++ src/netcode/net_command.h | 1 + src/netcode/tic_command.c | 95 ++++++++++++++++++--------------------- 3 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 98c578b79..11b351af7 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -304,6 +304,27 @@ void PT_TextCmd(SINT8 node, INT32 netconsole) } } +void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf) +{ + UINT8 *numcmds; + + numcmds = (*buf)++; + *numcmds = 0; + for (INT32 i = 0; i < MAXPLAYERS; i++) + { + UINT8 *cmd = D_GetExistingTextcmd(tic, i); + INT32 size = cmd ? cmd[0] : 0; + + if ((!i || playeringame[i]) && size) + { + (*numcmds)++; + WRITEUINT8(*buf, i); + M_Memcpy(*buf, cmd, size + 1); + *buf += size + 1; + } + } +} + void CL_CopyNetCommandsFromServerPacket(tic_t tic) { servertics_pak *packet = &netbuffer->u.serverpak; diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index 0e8339ef7..cc26aeb0e 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -57,6 +57,7 @@ void ExtraDataTicker(void); size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); +void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf); void CL_CopyNetCommandsFromServerPacket(tic_t tic); void CL_SendNetCommands(void); void SendKick(UINT8 playernum, UINT8 msg); diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 6b237ed61..bf8c5d21d 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -298,16 +298,56 @@ void CL_SendClientCmd(void) CL_SendNetCommands(); } +// PT_SERVERTICS packets can grow too large for a single UDP packet, +// So this checks how many tics worth of data can be sent in one packet. +// The rest can be sent later, usually the next tic. +static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t lasttic) +{ + size_t size = BASESERVERTICSSIZE; + tic_t tic; + + for (tic = firsttic; tic < lasttic; tic++) + { + size += sizeof (ticcmd_t) * doomcom->numslots; + size += TotalTextCmdPerTic(tic); + + if (size > software_MAXPACKETLENGTH) + { + DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", + sizeu1(size), tic, firsttic, lasttic)); + lasttic = tic; + + // too bad: too much player have send extradata and there is too + // much data in one tic. + // To avoid it put the data on the next tic. (see getpacket + // textcmd case) but when numplayer changes the computation can be different + if (lasttic == firsttic) + { + if (size > MAXPACKETLENGTH) + I_Error("Too many players: can't send %s data for %d players to node %d\n" + "Well sorry nobody is perfect....\n", + sizeu1(size), doomcom->numslots, nodenum); + else + { + lasttic++; // send it anyway! + DEBFILE("sending it anyway\n"); + } + } + break; + } + } + + return lasttic - firsttic; +} + // send the server packet // send tic from firstticstosend to maketic-1 void SV_SendTics(void) { tic_t realfirsttic, lasttictosend, i; UINT32 n; - INT32 j; size_t packsize; UINT8 *bufpos; - UINT8 *ntextcmd; // send to all client but not to me // for each node create a packet with x tics and send it @@ -336,38 +376,7 @@ void SV_SendTics(void) if (realfirsttic < firstticstosend) realfirsttic = firstticstosend; - // compute the length of the packet and cut it if too large - packsize = BASESERVERTICSSIZE; - for (i = realfirsttic; i < lasttictosend; i++) - { - packsize += sizeof (ticcmd_t) * doomcom->numslots; - packsize += TotalTextCmdPerTic(i); - - if (packsize > software_MAXPACKETLENGTH) - { - DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", - sizeu1(packsize), i, realfirsttic, lasttictosend)); - lasttictosend = i; - - // too bad: too much player have send extradata and there is too - // much data in one tic. - // To avoid it put the data on the next tic. (see getpacket - // textcmd case) but when numplayer changes the computation can be different - if (lasttictosend == realfirsttic) - { - if (packsize > MAXPACKETLENGTH) - I_Error("Too many players: can't send %s data for %d players to node %d\n" - "Well sorry nobody is perfect....\n", - sizeu1(packsize), doomcom->numslots, n); - else - { - lasttictosend++; // send it anyway! - DEBFILE("sending it anyway\n"); - } - } - break; - } - } + lasttictosend = realfirsttic + SV_CalculateNumTicsForPacket(n, realfirsttic, lasttictosend); // Send the tics netbuffer->packettype = PT_SERVERTICS; @@ -383,23 +392,7 @@ void SV_SendTics(void) // add textcmds for (i = realfirsttic; i < lasttictosend; i++) - { - ntextcmd = bufpos++; - *ntextcmd = 0; - for (j = 0; j < MAXPLAYERS; j++) - { - UINT8 *textcmd = D_GetExistingTextcmd(i, j); - INT32 size = textcmd ? textcmd[0] : 0; - - if ((!j || playeringame[j]) && size) - { - (*ntextcmd)++; - WRITEUINT8(bufpos, j); - M_Memcpy(bufpos, textcmd, size + 1); - bufpos += size + 1; - } - } - } + SV_WriteNetCommandsForTic(); packsize = bufpos - (UINT8 *)&(netbuffer->u); HSendPacket(n, false, 0, packsize); From a54155e2cccacd6a8025485088d1c7ba0fcf3efa Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 20:02:06 +0100 Subject: [PATCH 62/93] Cleanup --- src/netcode/client_connection.c | 21 ++++------ src/netcode/commands.c | 23 +++++------ src/netcode/d_clisrv.c | 57 ++++++++++---------------- src/netcode/d_net.c | 66 ++++++++++++------------------ src/netcode/d_netfil.c | 71 ++++++++++++--------------------- src/netcode/gamestate.c | 8 +--- src/netcode/i_tcp.c | 34 ++++++---------- src/netcode/net_command.c | 11 ++--- src/netcode/server_connection.c | 11 ++--- src/netcode/tic_command.c | 56 +++++++++++--------------- 10 files changed, 132 insertions(+), 226 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index ff20a6fc7..faa91b6d7 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -60,7 +60,7 @@ static inline void CL_DrawConnectionStatus(void) if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES) { - INT32 i, animtime = ((ccstime / 4) & 15) + 16; + INT32 animtime = ((ccstime / 4) & 15) + 16; UINT8 palstart; const char *cltext; @@ -75,7 +75,7 @@ static inline void CL_DrawConnectionStatus(void) palstart = 96; // Green if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) - for (i = 0; i < 16; ++i) // 15 pal entries total. + for (INT32 i = 0; i < 16; ++i) // 15 pal entries total. V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); switch (cl_mode) @@ -134,14 +134,13 @@ static inline void CL_DrawConnectionStatus(void) { INT32 totalfileslength; INT32 loadcompletednum = 0; - INT32 i; V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); //ima just count files here if (fileneeded) { - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_OPEN) loadcompletednum++; } @@ -277,9 +276,7 @@ UINT32 serverlistcount = 0; static void SL_ClearServerList(INT32 connectedserver) { - UINT32 i; - - for (i = 0; i < serverlistcount; i++) + for (UINT32 i = 0; i < serverlistcount; i++) if (connectedserver != serverlist[i].node) { Net_CloseConnection(serverlist[i].node|FORCECLOSE); @@ -290,8 +287,7 @@ static void SL_ClearServerList(INT32 connectedserver) static UINT32 SL_SearchServer(INT32 node) { - UINT32 i; - for (i = 0; i < serverlistcount; i++) + for (UINT32 i = 0; i < serverlistcount; i++) if (serverlist[i].node == node) return i; @@ -388,9 +384,7 @@ Fetch_servers_thread (struct Fetch_servers_ctx *ctx) void CL_QueryServerList (msg_server_t *server_list) { - INT32 i; - - for (i = 0; server_list[i].header.buffer[0]; i++) + for (INT32 i = 0; server_list[i].header.buffer[0]; i++) { // Make sure MS version matches our own, to // thwart nefarious servers who lie to the MS. @@ -781,7 +775,6 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic_t *asksent) { boolean waitmore; - INT32 i; switch (cl_mode) { @@ -808,7 +801,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic break; case CL_DOWNLOADFILES: waitmore = false; - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_DOWNLOADING || fileneeded[i].status == FS_REQUESTED) { diff --git a/src/netcode/commands.c b/src/netcode/commands.c index 834e1c666..4d9a48b6b 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -79,7 +79,6 @@ static void Ban_Clear(void) void Ban_Load_File(boolean warning) { FILE *f; - size_t i; const char *address, *mask; char buffer[MAX_WADPATH]; @@ -97,7 +96,7 @@ void Ban_Load_File(boolean warning) Ban_Clear(); - for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) + for (size_t i=0; fgets(buffer, (int)sizeof(buffer), f); i++) { address = strtok(buffer, " \t\r\n"); mask = strtok(NULL, " \t\r\n"); @@ -113,7 +112,6 @@ void Ban_Load_File(boolean warning) void D_SaveBan(void) { FILE *f; - size_t i; banreason_t *reasonlist = reasonhead; const char *address, *mask; const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); @@ -132,7 +130,7 @@ void D_SaveBan(void) return; } - for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) + for (size_t i = 0;(address = I_GetBanAddress(i)) != NULL;i++) { if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) fprintf(f, "%s 0", address); @@ -236,12 +234,12 @@ void Command_Ban(void) } else { - size_t i, j = COM_Argc(); + size_t j = COM_Argc(); char message[MAX_REASONLENGTH]; //Steal from the motd code so you don't have to put the reason in quotes. strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) + for (size_t i = 3; i < j; i++) { strlcat(message, " ", sizeof message); strlcat(message, COM_Argv(i), sizeof message); @@ -340,12 +338,12 @@ void Command_Kick(void) } else { - size_t i, j = COM_Argc(); + size_t j = COM_Argc(); char message[MAX_REASONLENGTH]; //Steal from the motd code so you don't have to put the reason in quotes. strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) + for (size_t i = 3; i < j; i++) { strlcat(message, " ", sizeof message); strlcat(message, COM_Argv(i), sizeof message); @@ -435,9 +433,7 @@ void Command_connect(void) void Command_GetPlayerNum(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) { if (serverplayer == i) @@ -453,18 +449,17 @@ void Command_GetPlayerNum(void) */ void Command_Nodes(void) { - INT32 i; size_t maxlen = 0; const char *address; - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { const size_t plen = strlen(player_names[i]); if (playeringame[i] && plen > maxlen) maxlen = plen; } - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 1658856b6..105526dd2 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -440,11 +440,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (M_CheckParm("-consisdump")) // Helps debugging some problems { - INT32 i; - CONS_Printf(M_GetText("Player kicked is #%d, dumping consistency...\n"), pnum); - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) continue; @@ -545,8 +543,8 @@ static void RedistributeSpecialStageSpheres(INT32 playernum) INT32 sincrement = max(spheres / count, 1); INT32 rincrement = max(rings / count, 1); - INT32 i, n; - for (i = 0; i < MAXPLAYERS; i++) + INT32 n; + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || i == playernum) continue; @@ -644,10 +642,8 @@ void D_QuitNetGame(void) if (server) { - INT32 i; - netbuffer->packettype = PT_SERVERSHUTDOWN; - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) if (netnodes[i].ingame) HSendPacket(i, true, 0, 0); #ifdef MASTERSERVER @@ -701,8 +697,6 @@ void CL_RemoveSplitscreenPlayer(void) void SV_ResetServer(void) { - INT32 i; - // +1 because this command will be executed in com_executebuffer in // tryruntic so gametic will be incremented, anyway maketic > gametic // is not an issue @@ -713,10 +707,10 @@ void SV_ResetServer(void) joindelay = 0; - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) ResetNode(i); - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { LUA_InvalidatePlayer(&players[i]); playeringame[i] = false; @@ -755,10 +749,9 @@ void SV_ResetServer(void) static inline void SV_GenContext(void) { - UINT8 i; // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z // (hopefully M_Random is initialized!! if not this will be awfully silly!) - for (i = 0; i < 8; i++) + for (UINT8 i = 0; i < 8; i++) { const char a = M_RandomKey(26*2); if (a < 26) // uppercase @@ -814,8 +807,6 @@ void SV_StartSinglePlayerServer(void) void SV_StopServer(void) { - tic_t i; - if (gamestate == GS_INTERMISSION) Y_EndIntermission(); gamestate = wipegamestate = GS_NULL; @@ -823,7 +814,7 @@ void SV_StopServer(void) localtextcmd[0] = 0; localtextcmd2[0] = 0; - for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) + for (tic_t i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) D_Clearticcmd(i); consoleplayer = 0; @@ -913,7 +904,6 @@ If they're not lagging, decrement the timer by 1. Of course, reset all of this i static inline void PingUpdate(void) { - INT32 i; boolean laggers[MAXPLAYERS]; UINT8 numlaggers = 0; memset(laggers, 0, sizeof(boolean) * MAXPLAYERS); @@ -923,7 +913,7 @@ static inline void PingUpdate(void) //check for ping limit breakage. if (cv_maxping.value) { - for (i = 1; i < MAXPLAYERS; i++) + for (INT32 i = 1; i < MAXPLAYERS; i++) { if (playeringame[i] && !players[i].quittime && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) @@ -940,7 +930,7 @@ static inline void PingUpdate(void) //in that case, it is probably the server's fault. if (numlaggers < D_NumPlayers() - 1) { - for (i = 1; i < MAXPLAYERS; i++) + for (INT32 i = 1; i < MAXPLAYERS; i++) { if (playeringame[i] && laggers[i]) { @@ -965,7 +955,7 @@ static inline void PingUpdate(void) } //make the ping packet and clear server data for next one - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; //server takes a snapshot of the real ping for display. @@ -978,7 +968,7 @@ static inline void PingUpdate(void) netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; //send out our ping packets - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) if (netnodes[i].ingame) HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); @@ -999,8 +989,7 @@ static void PT_Ping(SINT8 node, INT32 netconsole) //Update client ping table from the server. if (client) { - UINT8 i; - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; @@ -1225,7 +1214,6 @@ void NetUpdate(void) static tic_t gametime = 0; static tic_t resptime = 0; tic_t nowtime; - INT32 i; INT32 realtics; nowtime = I_GetTime(); @@ -1248,7 +1236,7 @@ void NetUpdate(void) if (netgame && !(gametime % 35)) // update once per second. PingUpdate(); // update node latency values so we can take an average later. - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && playernode[i] != UINT8_MAX) realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); pingmeasurecount++; @@ -1287,7 +1275,7 @@ void NetUpdate(void) hu_redownloadinggamestate = false; firstticstosend = gametic; - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) if (netnodes[i].ingame && netnodes[i].tic < firstticstosend) { firstticstosend = netnodes[i].tic; @@ -1301,7 +1289,7 @@ void NetUpdate(void) if (maketic + counts >= firstticstosend + BACKUPTICS) counts = firstticstosend+BACKUPTICS-maketic-1; - for (i = 0; i < counts; i++) + for (INT32 i = 0; i < counts; i++) SV_Maketic(); // Create missed tics and increment maketic for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged @@ -1318,7 +1306,7 @@ void NetUpdate(void) // Handle timeouts to prevent definitive freezes from happenning if (server) { - for (i = 1; i < MAXNETNODES; i++) + for (INT32 i = 1; i < MAXNETNODES; i++) if (netnodes[i].ingame && netnodes[i].freezetimeout < I_GetTime()) Net_ConnectionTimeout(i); @@ -1387,7 +1375,7 @@ void D_ClientServerInit(void) SINT8 nametonum(const char *name) { - INT32 playernum, i; + INT32 playernum; if (!strcmp(name, "0")) return 0; @@ -1405,7 +1393,7 @@ SINT8 nametonum(const char *name) return -1; } - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && !stricmp(player_names[i], name)) return (SINT8)i; @@ -1427,8 +1415,8 @@ boolean Playing(void) */ INT32 D_NumPlayers(void) { - INT32 num = 0, ix; - for (ix = 0; ix < MAXPLAYERS; ix++) + INT32 num = 0; + for (INT32 ix = 0; ix < MAXPLAYERS; ix++) if (playeringame[ix]) num++; return num; @@ -1444,7 +1432,6 @@ INT32 D_NumPlayers(void) // INT16 Consistancy(void) { - INT32 i; UINT32 ret = 0; #ifdef MOBJCONSISTANCY thinker_t *th; @@ -1453,7 +1440,7 @@ INT16 Consistancy(void) DEBFILE(va("TIC %u ", gametic)); - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) ret ^= 0xCCCC; diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index 3c16392d0..a4b0778e3 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -211,7 +211,7 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b) static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) { node_t *node = &nodes[doomcom->remotenode]; - INT32 i, numfreeslot = 0; + INT32 numfreeslot = 0; if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0) { @@ -219,7 +219,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) return false; } - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (!ackpak[i].acknum) { // For low priority packets, make sure to let freeslots so urgent packets can be sent @@ -276,10 +276,10 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) */ INT32 Net_GetFreeAcks(boolean urgent) { - INT32 i, numfreeslot = 0; + INT32 numfreeslot = 0; INT32 n = 0; // Number of free acks found - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (!ackpak[i].acknum) { // For low priority packets, make sure to let freeslots so urgent packets can be sent @@ -315,7 +315,6 @@ static void RemoveAck(INT32 i) // We have got a packet, proceed the ack request and ack return static boolean Processackpak(void) { - INT32 i; boolean goodpacket = true; node_t *node = &nodes[doomcom->remotenode]; @@ -324,7 +323,7 @@ static boolean Processackpak(void) { node->remotefirstack = netbuffer->ackreturn; // Search the ackbuffer and free it - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes && cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0) { @@ -346,7 +345,7 @@ static boolean Processackpak(void) else { // Check if it is not already in the queue - for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND) + for (INT32 i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND) if (node->acktosend[i] == ack) { DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack)); @@ -374,7 +373,7 @@ static boolean Processackpak(void) while (change) { change = false; - for (i = node->acktosend_tail; i != node->acktosend_head; + for (INT32 i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND) { if (cmpack(node->acktosend[i], nextfirstack) <= 0) @@ -434,11 +433,9 @@ void Net_SendAcks(INT32 node) static void GotAcks(void) { - INT32 i, j; - - for (j = 0; j < MAXACKTOSEND; j++) + for (INT32 j = 0; j < MAXACKTOSEND; j++) if (netbuffer->u.textcmd[j]) - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode) { if (ackpak[i].acknum == netbuffer->u.textcmd[j]) @@ -475,9 +472,8 @@ void Net_ConnectionTimeout(INT32 node) // Resend the data if needed void Net_AckTicker(void) { - INT32 i; - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) { const INT32 nodei = ackpak[i].destinationnode; node_t *node = &nodes[nodei]; @@ -504,7 +500,7 @@ void Net_AckTicker(void) } } - for (i = 1; i < MAXNETNODES; i++) + for (INT32 i = 1; i < MAXNETNODES; i++) { // This is something like node open flag if (nodes[i].firstacktosend) @@ -567,9 +563,7 @@ void Net_UnAcknowledgePacket(INT32 node) */ static boolean Net_AllAcksReceived(void) { - INT32 i; - - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum) return false; @@ -611,12 +605,10 @@ static void InitNode(node_t *node) static void InitAck(void) { - INT32 i; - - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) ackpak[i].acknum = 0; - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) InitNode(&nodes[i]); } @@ -627,8 +619,7 @@ static void InitAck(void) */ void Net_AbortPacketType(UINT8 packettype) { - INT32 i; - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype || packettype == UINT8_MAX)) { @@ -643,7 +634,6 @@ void Net_AbortPacketType(UINT8 packettype) // remove a node, clear all ack from this node and reset askret void Net_CloseConnection(INT32 node) { - INT32 i; boolean forceclose = (node & FORCECLOSE) != 0; if (node == -1) @@ -673,7 +663,7 @@ void Net_CloseConnection(INT32 node) } // check if we are waiting for an ack from this node - for (i = 0; i < MAXACKPACKETS; i++) + for (INT32 i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && ackpak[i].destinationnode == node) { if (!forceclose) @@ -697,9 +687,8 @@ static UINT32 NetbufferChecksum(void) UINT32 c = 0x1234567; const INT32 l = doomcom->datalength - 4; const UINT8 *buf = (UINT8 *)netbuffer + 4; - INT32 i; - for (i = 0; i < l; i++, buf++) + for (INT32 i = 0; i < l; i++, buf++) c += (*buf) * (i+1); return LONG(c); @@ -710,9 +699,8 @@ static UINT32 NetbufferChecksum(void) static void fprintfstring(char *s, size_t len) { INT32 mode = 0; - size_t i; - for (i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) if (s[i] < 32) { if (!mode) @@ -879,7 +867,6 @@ void Command_Drop(void) { INT32 packetquantity; const char *packetname; - size_t i; if (COM_Argc() < 2) { @@ -909,11 +896,11 @@ void Command_Drop(void) packetname = COM_Argv(1); if (!(stricmp(packetname, "all") && stricmp(packetname, "any"))) - for (i = 0; i < NUMPACKETTYPE; i++) + for (size_t i = 0; i < NUMPACKETTYPE; i++) packetdropquantity[i] = packetquantity; else { - for (i = 0; i < NUMPACKETTYPE; i++) + for (size_t i = 0; i < NUMPACKETTYPE; i++) if (!stricmp(packetname, packettypename[i])) { packetdropquantity[i] = packetquantity; @@ -1336,13 +1323,12 @@ void Command_Ping_f(void) int name_width = 0; int ms_width = 0; - int n; - INT32 i; - pingc = 0; - for (i = 1; i < MAXPLAYERS; ++i) + for (INT32 i = 1; i < MAXPLAYERS; ++i) if (playeringame[i]) { + int n; + n = strlen(player_names[i]); if (n > name_width) name_width = n; @@ -1362,7 +1348,7 @@ void Command_Ping_f(void) qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp); - for (i = 0; i < pingc; ++i) + for (INT32 i = 0; i < pingc; ++i) { CONS_Printf("%02d : %-*s %*d ms\n", pingv[i].num, @@ -1378,15 +1364,13 @@ void Command_Ping_f(void) void D_CloseConnection(void) { - INT32 i; - if (netgame) { // wait the ackreturn with timout of 5 Sec Net_WaitAllAckReceived(5); // close all connection - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) Net_CloseConnection(i|FORCECLOSE); InitAck(); diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 205abf713..10b7359ad 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -128,9 +128,7 @@ consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR static UINT16 GetWadNumFromFileNeededId(UINT8 id) { - UINT16 wadnum; - - for (wadnum = mainwads; wadnum < numwadfiles; wadnum++) + for (UINT16 wadnum = mainwads; wadnum < numwadfiles; wadnum++) { if (!wadfiles[wadnum]->important) continue; @@ -150,14 +148,13 @@ static UINT16 GetWadNumFromFileNeededId(UINT8 id) */ UINT8 *PutFileNeeded(UINT16 firstfile) { - size_t i; UINT8 count = 0; UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded; UINT8 *p = p_start; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus, folder; - for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad + for (size_t i = mainwads; i < numwadfiles; i++) //mainwads, 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) @@ -232,7 +229,6 @@ void FreeFileNeeded(void) */ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile) { - INT32 i; UINT8 *p; UINT8 filestatus; @@ -241,7 +237,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi AllocFileNeeded(fileneedednum); - for (i = firstfile; i < fileneedednum; i++) + for (INT32 i = firstfile; i < fileneedednum; i++) { fileneeded[i].type = FILENEEDED_WAD; fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet @@ -281,9 +277,9 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave) */ boolean CL_CheckDownloadable(void) { - UINT8 i,dlstatus = 0; + UINT8 dlstatus = 0; - for (i = 0; i < fileneedednum; i++) + for (UINT8 i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { if (fileneeded[i].willsend == 1) @@ -304,7 +300,7 @@ boolean CL_CheckDownloadable(void) // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); - for (i = 0; i < fileneedednum; i++) + for (UINT8 i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); @@ -374,14 +370,13 @@ void CL_AbortDownloadResume(void) boolean CL_SendFileRequest(void) { char *p; - INT32 i; INT64 totalfreespaceneeded = 0, availablefreespace; #ifdef PARANOIA if (M_CheckParm("-nodownload")) I_Error("Attempted to download files in -nodownload mode"); - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) { @@ -391,7 +386,7 @@ boolean CL_SendFileRequest(void) netbuffer->packettype = PT_REQUESTFILE; p = (char *)netbuffer->u.textcmd; - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) { totalfreespaceneeded += fileneeded[i].totalsize; @@ -422,7 +417,6 @@ boolean CL_SendFileRequest(void) void PT_RequestFile(SINT8 node) { UINT8 *p = netbuffer->u.textcmd; - UINT8 id; if (client || !cv_downloading.value) { @@ -432,7 +426,7 @@ void PT_RequestFile(SINT8 node) while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow { - id = READUINT8(p); + UINT8 id = READUINT8(p); if (id == 0xFF) break; @@ -543,9 +537,7 @@ INT32 CL_CheckFiles(void) // Load it now boolean CL_LoadServerFiles(void) { - INT32 i; - - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) { if (fileneeded[i].status == FS_OPEN) continue; // Already loaded @@ -641,11 +633,10 @@ void AddLuaFileTransfer(const char *filename, const char *mode) static void SV_PrepareSendLuaFileToNextNode(void) { - INT32 i; UINT8 success = 1; // Find a client to send the file to - for (i = 1; i < MAXNETNODES; i++) + for (INT32 i = 1; i < MAXNETNODES; i++) if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting { // Tell the client we're about to send them the file @@ -667,12 +658,11 @@ static void SV_PrepareSendLuaFileToNextNode(void) void SV_PrepareSendLuaFile(void) { char *binfilename; - INT32 i; luafiletransfers->ongoing = true; // Set status to "waiting" for everyone - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) luafiletransfers->nodestatus[i] = (netnodes[i].ingame ? LFTNS_WAITING : LFTNS_NONE); if (FIL_ReadFileOK(luafiletransfers->realfilename)) @@ -1153,7 +1143,6 @@ void PT_FileAck(SINT8 node) { fileack_pak *packet = &netbuffer->u.fileack; filetran_t *trans = &transfer[node]; - INT32 i, j; if (client) return; @@ -1175,11 +1164,11 @@ void PT_FileAck(SINT8 node) trans->dontsenduntil = 0; } - for (i = 0; i < packet->numsegments; i++) + for (INT32 i = 0; i < packet->numsegments; i++) { fileacksegment_t *segment = &packet->segments[i]; - for (j = 0; j < 32; j++) + for (INT32 j = 0; j < 32; j++) if (LONG(segment->acks) & (1 << j)) { if (LONG(segment->start) * FILEFRAGMENTSIZE >= trans->txlist->size) @@ -1215,13 +1204,12 @@ void PT_FileReceived(SINT8 node) static void SendAckPacket(fileack_pak *packet, UINT8 fileid) { size_t packetsize; - INT32 i; packetsize = sizeof(*packet) + packet->numsegments * sizeof(*packet->segments); // Finalise the packet packet->fileid = fileid; - for (i = 0; i < packet->numsegments; i++) + for (INT32 i = 0; i < packet->numsegments; i++) { packet->segments[i].start = LONG(packet->segments[i].start); packet->segments[i].acks = LONG(packet->segments[i].acks); @@ -1261,9 +1249,7 @@ static void AddFragmentToAckPacket(fileack_pak *packet, UINT8 iteration, UINT32 void FileReceiveTicker(void) { - INT32 i; - - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) { fileneeded_t *file = &fileneeded[i]; @@ -1277,8 +1263,7 @@ void FileReceiveTicker(void) if (file->ackresendposition != UINT32_MAX && file->status == FS_DOWNLOADING) { // Acknowledge ~70 MB/s, whichs means the client sends ~18 KB/s - INT32 j; - for (j = 0; j < 2048; j++) + for (INT32 j = 0; j < 2048; j++) { if (file->receivedfragments[file->ackresendposition]) AddFragmentToAckPacket(file->ackpacket, file->iteration, file->ackresendposition, i); @@ -1500,15 +1485,14 @@ void SV_AbortSendFiles(INT32 node) void CloseNetFile(void) { - INT32 i; // Is sending? - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) SV_AbortSendFiles(i); // Receiving a file? if (fileneeded) { - for (i = 0; i < fileneedednum; i++) + for (INT32 i = 0; i < fileneedednum; i++) if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) { fclose(fileneeded[i].file); @@ -1541,9 +1525,7 @@ void CloseNetFile(void) void Command_Downloads_f(void) { - INT32 node; - - for (node = 0; node < MAXNETNODES; node++) + for (INT32 node = 0; node < MAXNETNODES; node++) if (transfer[node].txlist && transfer[node].txlist->ram == SF_FILE) // Node is downloading a file? { @@ -1577,14 +1559,11 @@ void Command_Downloads_f(void) void nameonly(char *s) { - size_t j, len; - void *ns; - - for (j = strlen(s); j != (size_t)-1; j--) + for (size_t j = strlen(s); j != (size_t)-1; j--) if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/')) { - ns = &(s[j+1]); - len = strlen(ns); + void *ns = &(s[j+1]); + size_t len = strlen(ns); #if 0 M_Memcpy(s, ns, len+1); #else @@ -1597,9 +1576,9 @@ void nameonly(char *s) // Returns the length in characters of the last element of a path. size_t nameonlylength(const char *s) { - size_t j, len = strlen(s); + size_t len = strlen(s); - for (j = len; j != (size_t)-1; j--) + for (size_t j = len; j != (size_t)-1; j--) if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/')) return len - j - 1; diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index 4a3e9f3af..d284164c0 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -43,9 +43,7 @@ boolean cl_redownloadinggamestate = false; boolean SV_ResendingSavegameToAnyone(void) { - INT32 i; - - for (i = 0; i < MAXNETNODES; i++) + for (INT32 i = 0; i < MAXNETNODES; i++) if (netnodes[i].resendingsavegame) return true; return false; @@ -236,9 +234,7 @@ void CL_LoadReceivedSavegame(boolean reloading) void CL_ReloadReceivedSavegame(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { LUA_InvalidatePlayer(&players[i]); sprintf(player_names[i], "Player %d", i + 1); diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 6baba6275..bd950c355 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -416,24 +416,20 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) */ static void cleanupnodes(void) { - SINT8 j; - if (!Playing()) return; // Why can't I start at zero? - for (j = 1; j < MAXNETNODES; j++) + for (SINT8 j = 1; j < MAXNETNODES; j++) if (!(netnodes[j].ingame || SendingFile(j))) nodeconnected[j] = false; } static SINT8 getfreenode(void) { - SINT8 j; - cleanupnodes(); - for (j = 0; j < MAXNETNODES; j++) + for (SINT8 j = 0; j < MAXNETNODES; j++) if (!nodeconnected[j]) { nodeconnected[j] = true; @@ -446,7 +442,7 @@ static SINT8 getfreenode(void) * downloading a needed wad, but it's better than not letting anyone join... */ /*I_Error("No more free nodes!!1!11!11!!1111\n"); - for (j = 1; j < MAXNETNODES; j++) + for (SINT8 j = 1; j < MAXNETNODES; j++) if (!netnodes[j].ingame) return j;*/ @@ -458,9 +454,8 @@ void Command_Numnodes(void) { INT32 connected = 0; INT32 ingame = 0; - INT32 i; - for (i = 1; i < MAXNETNODES; i++) + for (INT32 i = 1; i < MAXNETNODES; i++) { if (!(nodeconnected[i] || netnodes[i].ingame)) continue; @@ -496,13 +491,13 @@ void Command_Numnodes(void) // Returns true if a packet was received from a new node, false in all other cases static boolean SOCK_Get(void) { - size_t i, n; + size_t i; int j; ssize_t c; mysockaddr_t fromaddress; socklen_t fromlen; - for (n = 0; n < mysocketses; n++) + for (size_t n = 0; n < mysocketses; n++) { fromlen = (socklen_t)sizeof(fromaddress); c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0, @@ -563,10 +558,9 @@ static fd_set masterset; #ifdef SELECTTEST static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len) { - size_t i; boolean testset = false; FD_ZERO(dst); - for (i = 0; i < len;i++) + for (size_t i = 0; i < len;i++) { if(fd[i] != (SOCKET_TYPE)ERRSOCKET && FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups @@ -630,16 +624,15 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr static void SOCK_Send(void) { ssize_t c = ERRSOCKET; - size_t i, j; if (!nodeconnected[doomcom->remotenode]) return; if (doomcom->remotenode == BROADCASTADDR) { - for (i = 0; i < mysocketses; i++) + for (size_t i = 0; i < mysocketses; i++) { - for (j = 0; j < broadcastaddresses; j++) + for (size_t j = 0; j < broadcastaddresses; j++) { if (myfamily[i] == broadcastaddress[j].any.sa_family) SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); @@ -649,7 +642,7 @@ static void SOCK_Send(void) } else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) { - for (i = 0; i < mysocketses; i++) + for (size_t i = 0; i < mysocketses; i++) { if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); @@ -1082,8 +1075,7 @@ boolean I_InitTcpDriver(void) static void SOCK_CloseSocket(void) { - size_t i; - for (i=0; i < MAXNETNODES+1; i++) + for (size_t i=0; i < MAXNETNODES+1; i++) { if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET && FD_ISSET(mysockets[i], &masterset)) @@ -1154,12 +1146,10 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) static boolean SOCK_OpenSocket(void) { - size_t i; - memset(clientaddress, 0, sizeof (clientaddress)); nodeconnected[0] = true; // always connected to self - for (i = 1; i < MAXNETNODES; i++) + for (size_t i = 1; i < MAXNETNODES; i++) nodeconnected[i] = false; nodeconnected[BROADCASTADDR] = true; I_NetSend = SOCK_Send; diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 11b351af7..887b7fa2a 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -90,13 +90,11 @@ void D_FreeTextcmd(tic_t tic) if (textcmdtic) { - INT32 i; - // Remove this tic from the list. *tctprev = textcmdtic->next; // Free all players. - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + for (INT32 i = 0; i < TEXTCMD_HASH_SIZE; i++) { textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; @@ -174,9 +172,7 @@ UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) void ExtraDataTicker(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) if (playeringame[i] || i == 0) { UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); @@ -221,10 +217,9 @@ void ExtraDataTicker(void) // used at txtcmds received to check packetsize bound size_t TotalTextCmdPerTic(tic_t tic) { - INT32 i; size_t total = 1; // num of textcmds in the tic (ntextcmd byte) - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { UINT8 *textcmd = D_GetExistingTextcmd(tic, i); if ((!i || playeringame[i]) && textcmd) diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index ed0e28309..f8ec3c7bd 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -55,7 +55,6 @@ static INT32 FindRejoinerNum(SINT8 node) char strippednodeaddress[64]; const char *nodeaddress; char *port; - INT32 i; // Make sure there is no dead dress before proceeding to the stripping if (!I_GetNodeAddress) @@ -71,7 +70,7 @@ static INT32 FindRejoinerNum(SINT8 node) *port = '\0'; // Check if any player matches the stripped address - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX && !strcmp(playeraddress[i], strippednodeaddress)) @@ -162,10 +161,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) static void SV_SendPlayerInfo(INT32 node) { - UINT8 i; netbuffer->packettype = PT_PLAYERINFO; - for (i = 0; i < MAXPLAYERS; i++) + for (UINT8 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) { @@ -425,7 +423,6 @@ void PT_ClientJoin(SINT8 node) char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; INT32 numplayers = netbuffer->u.clientcfg.localplayers; INT32 rejoinernum; - INT32 i; // Ignore duplicate packets if (client || netnodes[node].ingame) @@ -440,7 +437,7 @@ void PT_ClientJoin(SINT8 node) return; } - for (i = 0; i < numplayers; i++) + for (INT32 i = 0; i < numplayers; i++) { strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) @@ -469,7 +466,7 @@ void PT_ClientJoin(SINT8 node) } // Splitscreen can allow 2 players in one node - for (i = 0; i < numplayers; i++) + for (INT32 i = 0; i < numplayers; i++) SV_AddPlayer(node, names[i]); joindelay += cv_joindelay.value * TICRATE; diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index bf8c5d21d..befe8a5cd 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -80,11 +80,9 @@ tic_t ExpandTics(INT32 low, INT32 node) void D_Clearticcmd(tic_t tic) { - INT32 i; - D_FreeTextcmd(tic); - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) netcmds[tic%BACKUPTICS][i].angleturn = 0; DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); @@ -92,13 +90,11 @@ void D_Clearticcmd(tic_t tic) void D_ResetTiccmds(void) { - INT32 i; - memset(&localcmds, 0, sizeof(ticcmd_t)); memset(&localcmds2, 0, sizeof(ticcmd_t)); // Reset the net command list - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + for (INT32 i = 0; i < TEXTCMD_HASH_SIZE; i++) while (textcmds[i]) D_Clearticcmd(textcmds[i]->tic); } @@ -229,8 +225,7 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) realstart = netbuffer->u.serverpak.starttic; realend = realstart + netbuffer->u.serverpak.numtics; - if (realend > gametic + CLIENTBACKUPTICS) - realend = gametic + CLIENTBACKUPTICS; + realend = min(realend, gametic + CLIENTBACKUPTICS); cl_packetmissed = realstart > neededtic; if (realstart <= neededtic && realend > neededtic) @@ -304,9 +299,8 @@ void CL_SendClientCmd(void) static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t lasttic) { size_t size = BASESERVERTICSSIZE; - tic_t tic; - for (tic = firsttic; tic < lasttic; tic++) + for (tic_t tic = firsttic; tic < lasttic; tic++) { size += sizeof (ticcmd_t) * doomcom->numslots; size += TotalTextCmdPerTic(tic); @@ -344,15 +338,12 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l // send tic from firstticstosend to maketic-1 void SV_SendTics(void) { - tic_t realfirsttic, lasttictosend, i; - UINT32 n; - size_t packsize; - UINT8 *bufpos; + tic_t realfirsttic, lasttictosend; // send to all client but not to me // for each node create a packet with x tics and send it // x is computed using netnodes[n].supposedtic, max packet size and maketic - for (n = 1; n < MAXNETNODES; n++) + for (INT32 n = 1; n < MAXNETNODES; n++) if (netnodes[n].ingame) { // assert netnodes[n].supposedtic>=netnodes[n].tic @@ -367,42 +358,42 @@ void SV_SendTics(void) // (getpacket servertics case) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", n, maketic, netnodes[n].supposedtic, netnodes[n].tic)); + realfirsttic = netnodes[n].tic; + if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) // all tic are ok continue; + DEBFILE(va("Sent %d anyway\n", realfirsttic)); } - if (realfirsttic < firstticstosend) - realfirsttic = firstticstosend; + realfirsttic = max(realfirsttic, firstticstosend); lasttictosend = realfirsttic + SV_CalculateNumTicsForPacket(n, realfirsttic, lasttictosend); - // Send the tics + // Prepare the packet header netbuffer->packettype = PT_SERVERTICS; netbuffer->u.serverpak.starttic = realfirsttic; netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); - bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; - for (i = realfirsttic; i < lasttictosend; i++) - { + // Fill and send the packet + UINT8 *bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; + for (tic_t i = realfirsttic; i < lasttictosend; i++) bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); - } - - // add textcmds - for (i = realfirsttic; i < lasttictosend; i++) - SV_WriteNetCommandsForTic(); - packsize = bufpos - (UINT8 *)&(netbuffer->u); - + for (tic_t i = realfirsttic; i < lasttictosend; i++) + SV_WriteNetCommandsForTic(i, &bufpos); + size_t packsize = bufpos - (UINT8 *)&(netbuffer->u); HSendPacket(n, false, 0, packsize); + // when tic are too large, only one tic is sent so don't go backward! if (lasttictosend-doomcom->extratics > realfirsttic) netnodes[n].supposedtic = lasttictosend-doomcom->extratics; else netnodes[n].supposedtic = lasttictosend; - if (netnodes[n].supposedtic < netnodes[n].tic) netnodes[n].supposedtic = netnodes[n].tic; + netnodes[n].supposedtic = max(netnodes[n].supposedtic, netnodes[n].tic); } + // node 0 is me! netnodes[0].supposedtic = maketic; } @@ -413,7 +404,8 @@ void Local_Maketic(INT32 realtics) D_ProcessEvents(); // menu responder, cons responder, // game responder calls HU_Responder, AM_Responder, // and G_MapEventsToControls - if (!dedicated) rendergametic = gametic; + if (!dedicated) + rendergametic = gametic; // translate inputs (keyboard/mouse/gamepad) into game controls G_BuildTiccmd(&localcmds, realtics, 1); if (splitscreen || botingame) @@ -426,9 +418,7 @@ void Local_Maketic(INT32 realtics) // create missed tic void SV_Maketic(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) continue; From 69af7e1ea486d946557004eb308508ac1a56fb79 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sat, 14 Jan 2023 20:02:20 +0100 Subject: [PATCH 63/93] Add missing include directive --- src/netcode/net_command.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index 887b7fa2a..efc8bd0ef 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -16,6 +16,7 @@ #include "server_connection.h" #include "d_clisrv.h" #include "i_net.h" +#include "../byteptr.h" #include "../g_game.h" #include "../z_zone.h" #include "../doomtype.h" From 6f536835194bee1dfbd495ba658cf9ab3ca29ef3 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 15 Jan 2023 13:08:31 +0100 Subject: [PATCH 64/93] Cleanup --- src/netcode/gamestate.c | 3 +-- src/netcode/tic_command.c | 43 +++++++++++++++++++++------------------ src/netcode/tic_command.h | 2 +- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index d284164c0..c1ceb95b5 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -242,8 +242,7 @@ void CL_ReloadReceivedSavegame(void) CL_LoadReceivedSavegame(true); - if (neededtic < gametic) - neededtic = gametic; + neededtic = max(neededtic, gametic); maketic = neededtic; ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn; diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index befe8a5cd..0fbf87c0c 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -148,8 +148,9 @@ static void CheckConsistancy(SINT8 nodenum, tic_t tic) } } -void PT_ClientCmd(SINT8 node, INT32 netconsole) +void PT_ClientCmd(SINT8 nodenum, INT32 netconsole) { + netnode_t *node = &netnodes[nodenum]; tic_t realend, realstart; if (client) @@ -157,24 +158,24 @@ void PT_ClientCmd(SINT8 node, INT32 netconsole) // To save bytes, only the low byte of tic numbers are sent // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, nodenum); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, nodenum); if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || netnodes[node].supposedtic < realend) + || node->supposedtic < realend) { - netnodes[node].supposedtic = realend; + node->supposedtic = realend; } // Discard out of order packet - if (netnodes[node].tic > realend) + if (node->tic > realend) { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", netnodes[node].tic)); + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", node->tic)); return; } // Update the nettics - netnodes[node].tic = realend; + node->tic = realend; // Don't do anything for packets of type NODEKEEPALIVE? if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE @@ -183,19 +184,19 @@ void PT_ClientCmd(SINT8 node, INT32 netconsole) // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? - netnodes[node].freezetimeout = I_GetTime() + connectiontimeout; + node->freezetimeout = I_GetTime() + connectiontimeout; // Copy ticcmd G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) - && netnodes[node].player2 >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)netnodes[node].player2], + && node->player2 >= 0) + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)node->player2], &netbuffer->u.client2pak.cmd2, 1); CheckTiccmdHacks(netconsole); - CheckConsistancy(node, realstart); + CheckConsistancy(nodenum, realstart); } void PT_ServerTics(SINT8 node, INT32 netconsole) @@ -346,9 +347,11 @@ void SV_SendTics(void) for (INT32 n = 1; n < MAXNETNODES; n++) if (netnodes[n].ingame) { - // assert netnodes[n].supposedtic>=netnodes[n].tic - realfirsttic = netnodes[n].supposedtic; - lasttictosend = min(maketic, netnodes[n].tic + CLIENTBACKUPTICS); + netnode_t *node = netnodes[n]; + + // assert node->supposedtic>=node->tic + realfirsttic = node->supposedtic; + lasttictosend = min(maketic, node->tic + CLIENTBACKUPTICS); if (realfirsttic >= lasttictosend) { @@ -357,9 +360,9 @@ void SV_SendTics(void) // packet detection work when we have received packet with firsttic > neededtic // (getpacket servertics case) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, netnodes[n].supposedtic, netnodes[n].tic)); + n, maketic, node->supposedtic, node->tic)); - realfirsttic = netnodes[n].tic; + realfirsttic = node->tic; if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) // all tic are ok @@ -388,10 +391,10 @@ void SV_SendTics(void) // when tic are too large, only one tic is sent so don't go backward! if (lasttictosend-doomcom->extratics > realfirsttic) - netnodes[n].supposedtic = lasttictosend-doomcom->extratics; + node->supposedtic = lasttictosend-doomcom->extratics; else - netnodes[n].supposedtic = lasttictosend; - netnodes[n].supposedtic = max(netnodes[n].supposedtic, netnodes[n].tic); + node->supposedtic = lasttictosend; + node->supposedtic = max(node->supposedtic, node->tic); } // node 0 is me! diff --git a/src/netcode/tic_command.h b/src/netcode/tic_command.h index d19f4c1aa..289750fb3 100644 --- a/src/netcode/tic_command.h +++ b/src/netcode/tic_command.h @@ -31,7 +31,7 @@ tic_t ExpandTics(INT32 low, INT32 node); void D_Clearticcmd(tic_t tic); void D_ResetTiccmds(void); -void PT_ClientCmd(SINT8 node, INT32 netconsole); +void PT_ClientCmd(SINT8 nodenum, INT32 netconsole); void PT_ServerTics(SINT8 node, INT32 netconsole); // send the client packet to the server From 7f4e82e7d9e1fdb5f01b3381c0f70d3c70eea7dd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Sun, 15 Jan 2023 13:10:23 +0100 Subject: [PATCH 65/93] Cleanup comments --- src/netcode/client_connection.c | 41 ++++++++++++++------------------- src/netcode/d_clisrv.c | 11 ++++----- src/netcode/protocol.h | 3 +-- src/netcode/tic_command.c | 35 ++++++++++++++-------------- 4 files changed, 39 insertions(+), 51 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index faa91b6d7..d363d7d5a 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -34,7 +34,7 @@ cl_mode_t cl_mode = CL_SEARCHING; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list -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 +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; UINT8 mynode; static void *snake = NULL; @@ -137,7 +137,7 @@ static inline void CL_DrawConnectionStatus(void) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); - //ima just count files here + // ima just count files here if (fileneeded) { for (INT32 i = 0; i < fileneedednum; i++) @@ -248,7 +248,7 @@ boolean CL_SendJoin(void) CleanupPlayerName(consoleplayer, cv_playername.zstring); if (splitscreen) - CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ + CleanupPlayerName(1, cv_playername2.zstring); // 1 is a HACK? oh no strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); @@ -306,14 +306,14 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (serverlistcount >= MAXSERVERLIST) return; // list full - /* check it later if connecting to this one */ + // check it later if connecting to this one if (node != servernode) { if (info->_255 != 255) - return;/* old packet format */ + return; // Old packet format if (info->packetversion != PACKETVERSION) - return;/* old new packet format */ + return; // Old new packet format if (info->version != VERSION) return; // Not same version. @@ -322,7 +322,7 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) return; // Close, but no cigar. if (strcmp(info->application, SRB2APPLICATION)) - return;/* that's a different mod */ + return; // That's a different mod } i = serverlistcount++; @@ -380,7 +380,7 @@ Fetch_servers_thread (struct Fetch_servers_ctx *ctx) free(ctx); } -#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ +#endif // defined (MASTERSERVER) && defined (HAVE_THREADS) void CL_QueryServerList (msg_server_t *server_list) { @@ -389,7 +389,7 @@ void CL_QueryServerList (msg_server_t *server_list) // Make sure MS version matches our own, to // thwart nefarious servers who lie to the MS. - /* lol bruh, that version COMES from the servers */ + // lol bruh, that version COMES from the servers //if (strcmp(version, server_list[i].version) == 0) { INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); @@ -441,7 +441,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) ctx = malloc(sizeof *ctx); - /* This called from M_Refresh so I don't use a mutex */ + // This called from M_Refresh so I don't use a mutex m_waiting_mode = M_WAITING_SERVERS; I_lock_mutex(&ms_QueryId_mutex); @@ -465,7 +465,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) } #endif } -#endif/*MASTERSERVER*/ +#endif // MASTERSERVER } static void M_ConfirmConnect(event_t *ev) @@ -619,7 +619,7 @@ static const char * InvalidServerReason (serverinfo_pak *info) { #define EOT "\nPress ESC\n" - /* magic number for new packet format */ + // Magic number for new packet format if (info->_255 != 255) { return @@ -691,10 +691,10 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) { INT32 i; - // serverlist is updated by GetPacket function + // serverlist is updated by GetPackets if (serverlistcount > 0) { - // this can be a responce to our broadcast request + // This can be a response to our broadcast request if (servernode == -1 || servernode >= MAXNETNODES) { i = 0; @@ -819,7 +819,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (CL_LoadServerFiles()) { FreeFileNeeded(); - *asksent = 0; //This ensure the first join ask is right away + *asksent = 0; // This ensures the first join request is right away firstconnectattempttime = I_GetTime(); cl_mode = CL_ASKJOIN; } @@ -841,9 +841,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic return false; } - // 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... + // Prepare structures to save the file CL_PrepareDownloadSaveGame(tmpsave); if (I_GetTime() >= *asksent && CL_SendJoin()) @@ -954,11 +952,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic #define TMPSAVENAME "$$$.sav" -/** Use adaptive send using net_bandwidth and stat.sendbytes - * - * \todo Better description... - * - */ void CL_ConnectToServer(void) { INT32 pnumnodes, nodewaited = doomcom->numnodes, i; @@ -1158,7 +1151,7 @@ void PT_ServerCFG(SINT8 node) DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? - /// Shouldn't them be downloaded even at intermission time? + /// Shouldn't they be downloaded even at intermission time? /// Also, according to PT_ClientJoin, the server will send the savegame even during intermission... if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 105526dd2..18eae580c 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1252,8 +1252,8 @@ void NetUpdate(void) GetPackets(); // get packet from client or from server - // client send the command after a receive of the server - // the server send before because in single player is beter + // The client sends the command after receiving from the server + // The server sends it before because this is better in single player #ifdef MASTERSERVER MasterClient_Ticker(); // Acking the Master Server @@ -1402,7 +1402,7 @@ SINT8 nametonum(const char *name) return -1; } -// is there a game running +// Is there a game running? boolean Playing(void) { return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); @@ -1423,11 +1423,8 @@ INT32 D_NumPlayers(void) } // -// NetUpdate -// Builds ticcmds for console player, -// sends out a packet +// Consistancy // -// no more use random generator, because at very first tic isn't yet synchronized // Note: It is called consistAncy on purpose. // INT16 Consistancy(void) diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index 374cc5bff..9866e4c5a 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -123,13 +123,12 @@ typedef struct #endif // Server to client packet -// this packet is too large typedef struct { tic_t starttic; UINT8 numtics; UINT8 numslots; // "Slots filled": Highest player number in use plus one. - ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large + ticcmd_t cmds[45]; } ATTRPACK servertics_pak; typedef struct diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 0fbf87c0c..620a10f7a 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -24,8 +24,8 @@ #include "../doomstat.h" #include "../doomtype.h" -tic_t firstticstosend; // min of the nettics -tic_t tictoclear = 0; // optimize d_clearticcmd +tic_t firstticstosend; // Smallest netnode.tic +tic_t tictoclear = 0; // Optimize D_ClearTiccmd ticcmd_t localcmds; ticcmd_t localcmds2; boolean cl_packetmissed; @@ -312,10 +312,9 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l sizeu1(size), tic, firsttic, lasttic)); lasttic = tic; - // too bad: too much player have send extradata and there is too - // much data in one tic. - // To avoid it put the data on the next tic. (see getpacket - // textcmd case) but when numplayer changes the computation can be different + // Too bad: too many players have sent extra data + // and there is too much data for a single tic. + // To avoid that, keep the data for the next tic (see PT_TEXTCMD). if (lasttic == firsttic) { if (size > MAXPACKETLENGTH) @@ -335,15 +334,15 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l return lasttic - firsttic; } -// send the server packet -// send tic from firstticstosend to maketic-1 +// Sends the server packet +// Sends tic/net commands from firstticstosend to maketic-1 void SV_SendTics(void) { tic_t realfirsttic, lasttictosend; - // send to all client but not to me - // for each node create a packet with x tics and send it - // x is computed using netnodes[n].supposedtic, max packet size and maketic + // Send to all clients except yourself + // For each node, create a packet with x tics and send it + // x is computed using node.supposedtic, max packet size and maketic for (INT32 n = 1; n < MAXNETNODES; n++) if (netnodes[n].ingame) { @@ -355,17 +354,17 @@ void SV_SendTics(void) if (realfirsttic >= lasttictosend) { - // well we have sent all tics we will so use extrabandwidth - // to resent packet that are supposed lost (this is necessary since lost - // packet detection work when we have received packet with firsttic > neededtic - // (getpacket servertics case) + // Well, we have sent all the tics, so we will use extra bandwidth + // to resend packets that are supposed lost. + // This is necessary since lost packet detection + // works when we receive a packet with firsttic > neededtic (PT_SERVERTICS) DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", n, maketic, node->supposedtic, node->tic)); realfirsttic = node->tic; if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) - // all tic are ok + // All tics are Ok continue; DEBFILE(va("Sent %d anyway\n", realfirsttic)); @@ -389,7 +388,7 @@ void SV_SendTics(void) size_t packsize = bufpos - (UINT8 *)&(netbuffer->u); HSendPacket(n, false, 0, packsize); - // when tic are too large, only one tic is sent so don't go backward! + // When tics are too large, only one tic is sent so don't go backwards! if (lasttictosend-doomcom->extratics > realfirsttic) node->supposedtic = lasttictosend-doomcom->extratics; else @@ -450,6 +449,6 @@ void SV_Maketic(void) } } - // all tic are now proceed make the next + // All tics have been processed, make the next maketic++; } From b2441114e8da63b442386f8577494c3d215a9f02 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Tue, 1 Aug 2023 18:24:07 +0200 Subject: [PATCH 66/93] Reapply recent netcode changes --- src/g_demo.c | 4 +- src/netcode/client_connection.c | 34 +- src/netcode/client_connection.h | 2 +- src/netcode/commands.c | 2 +- src/netcode/commands.h | 2 +- src/netcode/d_clisrv.c | 290 ++++++++++++---- src/netcode/d_clisrv.h | 8 +- src/netcode/d_net.c | 33 +- src/netcode/d_net.h | 2 +- src/netcode/d_netcmd.c | 594 +++++++++++++++++--------------- src/netcode/d_netcmd.h | 14 +- src/netcode/d_netfil.c | 4 +- src/netcode/d_netfil.h | 2 +- src/netcode/gamestate.c | 5 +- src/netcode/gamestate.h | 2 +- src/netcode/http-mserv.c | 30 +- src/netcode/i_addrinfo.c | 2 +- src/netcode/i_addrinfo.h | 2 +- src/netcode/i_net.h | 13 +- src/netcode/i_tcp.c | 73 ++-- src/netcode/i_tcp.h | 2 +- src/netcode/mserv.c | 10 +- src/netcode/mserv.h | 6 +- src/netcode/net_command.c | 16 +- src/netcode/net_command.h | 2 +- src/netcode/protocol.h | 5 +- src/netcode/server_connection.c | 22 +- src/netcode/server_connection.h | 2 +- src/netcode/tic_command.c | 61 ++-- src/netcode/tic_command.h | 2 +- src/snake.c | 70 +++- src/snake.h | 3 + 32 files changed, 846 insertions(+), 473 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index dea80e793..0a5114351 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -39,7 +39,7 @@ #include "v_video.h" #include "lua_hook.h" #include "md5.h" // demo checksums -#include "d_netfil.h" // G_CheckDemoExtraFiles +#include "netcode/d_netfil.h" // G_CheckDemoExtraFiles boolean timingdemo; // if true, exit with report on completion boolean nodrawers; // for comparative timing purposes @@ -1885,7 +1885,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) switch(oldversion) // demoversion { case DEMOVERSION: // latest always supported - case 0x000f: // The previous demoversions also supported + case 0x000f: // The previous demoversions also supported case 0x000e: case 0x000d: // all that changed between then and now was longer color name case 0x000c: diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index d363d7d5a..8155d1b33 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,11 +17,12 @@ #include "../d_main.h" #include "../f_finale.h" #include "../g_game.h" -#include "../i_gamepad.h" +#include "../g_input.h" #include "i_net.h" #include "../i_system.h" #include "../i_time.h" #include "../i_video.h" +#include "../keys.h" #include "../m_menu.h" #include "../m_misc.h" #include "../snake.h" @@ -233,6 +234,7 @@ static boolean CL_AskFileList(INT32 firstfile) boolean CL_SendJoin(void) { UINT8 localplayers = 1; + char const *player2name; if (netgame) CONS_Printf(M_GetText("Sending join request...\n")); netbuffer->packettype = PT_CLIENTJOIN; @@ -250,8 +252,14 @@ boolean CL_SendJoin(void) if (splitscreen) CleanupPlayerName(1, cv_playername2.zstring); // 1 is a HACK? oh no + // Avoid empty string on bots to avoid softlocking in singleplayer + if (botingame) + player2name = strcmp(cv_playername.zstring, "Tails") == 0 ? "Tail" : "Tails"; + else + player2name = cv_playername2.zstring; + strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); - strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); } @@ -470,9 +478,9 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) static void M_ConfirmConnect(event_t *ev) { - if (ev->type == ev_keydown || ev->type == ev_gamepad_down) + if (ev->type == ev_keydown) { - if ((ev->type == ev_keydown && (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_A)) + if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER || ev->key == KEY_JOY1) { if (totalfilesrequestednum > 0) { @@ -487,7 +495,7 @@ static void M_ConfirmConnect(event_t *ev) M_ClearMenus(true); } - else if ((ev->type == ev_keydown && (ev->key == 'n' || ev->key == KEY_ESCAPE)) || (ev->type == ev_gamepad_down && ev->which == 0 && ev->key == GAMEPAD_BUTTON_B)) + else if (ev->key == 'n' || ev->key == KEY_ESCAPE || ev->key == KEY_JOY1 + 3) { cl_mode = CL_ABORTED; M_ClearMenus(true); @@ -663,7 +671,7 @@ static const char * InvalidServerReason (serverinfo_pak *info) case REFUSE_SLOTS_FULL: return va( "Maximum players reached: %d\n" EOT, - info->maxplayer); + info->maxplayer - D_NumBots()); default: if (info->refusereason) { @@ -893,11 +901,12 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic // my hand has been forced and I am dearly sorry for this awful hack :vomit: for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { - G_MapEventsToControls(&events[eventtail]); + if (!Snake_JoyGrabber(snake, &events[eventtail])) + G_MapEventsToControls(&events[eventtail]); } } - if (gamekeydown[KEY_ESCAPE] || gamepads[0].buttons[GAMEPAD_BUTTON_B] || cl_mode == CL_ABORTED) + if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED) { CONS_Printf(M_GetText("Network game synchronization aborted.\n")); M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); @@ -922,7 +931,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic { if (!snake) { - F_MenuPresTicker(true); // title sky + F_MenuPresTicker(); // title sky F_TitleScreenTicker(true); F_TitleScreenDrawer(); } @@ -1020,6 +1029,9 @@ void CL_ConnectToServer(void) } while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); + if (netgame) + F_StartWaitingPlayers(); + DEBFILE(va("Synchronisation Finished\n")); displayplayer = consoleplayer; @@ -1136,6 +1148,8 @@ void PT_ServerCFG(SINT8 node) maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + if (netbuffer->u.servercfg.usedCheats) + G_SetUsedCheats(true); memcpy(server_context, netbuffer->u.servercfg.server_context, 8); } diff --git a/src/netcode/client_connection.h b/src/netcode/client_connection.h index 74cff61ff..4d75160d4 100644 --- a/src/netcode/client_connection.h +++ b/src/netcode/client_connection.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/commands.c b/src/netcode/commands.c index 4d9a48b6b..4228027d2 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/commands.h b/src/netcode/commands.h index 5ff4d1cae..d328114ee 100644 --- a/src/netcode/commands.h +++ b/src/netcode/commands.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 18eae580c..f06192f2c 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,8 +25,6 @@ #include "../st_stuff.h" #include "../hu_stuff.h" #include "../keys.h" -#include "../g_input.h" -#include "../i_gamepad.h" #include "../m_menu.h" #include "../console.h" #include "d_netfil.h" @@ -34,7 +32,6 @@ #include "../p_saveg.h" #include "../z_zone.h" #include "../p_local.h" -#include "../p_haptic.h" #include "../m_misc.h" #include "../am_map.h" #include "../m_random.h" @@ -103,6 +100,8 @@ boolean acceptnewnode = true; UINT16 software_MAXPACKETLENGTH; +static tic_t gametime = 0; + static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); @@ -114,6 +113,8 @@ consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); +consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); + void ResetNode(INT32 node) { memset(&netnodes[node], 0, sizeof(*netnodes)); @@ -210,14 +211,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (server && I_GetNodeAddress) { + char addressbuffer[64]; const char *address = I_GetNodeAddress(node); - char *port = NULL; if (address) // MI: fix msvcrt.dll!_mbscat crash? { - strcpy(playeraddress[newplayernum], address); - port = strchr(playeraddress[newplayernum], ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, address); + strcpy(playeraddress[newplayernum], + I_NetSplitAddress(addressbuffer, NULL)); } } } @@ -744,6 +744,9 @@ void SV_ResetServer(void) CV_RevertNetVars(); + // Ensure synched when creating a new server + M_CopyGameData(serverGamedata, clientGamedata); + DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } @@ -997,6 +1000,45 @@ static void PT_Ping(SINT8 node, INT32 netconsole) } } +static void PT_BasicKeepAlive(SINT8 node, INT32 netconsole) +{ + if (client) + return; + + // This should probably still timeout though, as the node should always have a player 1 number + if (netconsole == -1) + return; + + // If a client sends this it should mean they are done receiving the savegame + netnodes[node].sendingsavegame = false; + + // As long as clients send keep alives, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + netnodes[node].freezetimeout = I_GetTime() + connectiontimeout; + return; +} + +// Confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE +// Used during wipes to tell the server that a node is still connected +static void CL_SendClientKeepAlive(void) +{ + netbuffer->packettype = PT_BASICKEEPALIVE; + + HSendPacket(servernode, false, 0, 0); +} + +static void SV_SendServerKeepAlive(void) +{ + for (INT32 n = 1; n < MAXNETNODES; n++) + { + if (netnodes[n].ingame) + { + netbuffer->packettype = PT_BASICKEEPALIVE; + HSendPacket(n, false, 0, 0); + } + } +} + /** Handles a packet received from a node that isn't in game * * \param node The packet sender @@ -1052,6 +1094,7 @@ static void HandlePacketFromPlayer(SINT8 node) netconsole = 0; else netconsole = netnodes[node].player; + #ifdef PARANOIA if (netconsole >= MAXPLAYERS) I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); @@ -1068,6 +1111,7 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_NODEKEEPALIVEMIS: PT_ClientCmd(node, netconsole); break; + case PT_BASICKEEPALIVE : PT_BasicKeepAlive (node, netconsole); break; case PT_TEXTCMD : PT_TextCmd (node, netconsole); break; case PT_TEXTCMD2 : PT_TextCmd (node, netconsole); break; case PT_LOGIN : PT_Login (node, netconsole); break; @@ -1209,28 +1253,8 @@ boolean TryRunTics(tic_t realtics) } } -void NetUpdate(void) +static void UpdatePingTable(void) { - static tic_t gametime = 0; - static tic_t resptime = 0; - tic_t nowtime; - INT32 realtics; - - nowtime = I_GetTime(); - realtics = nowtime - gametime; - - if (realtics <= 0) // nothing new to update - return; - if (realtics > 5) - { - if (server) - realtics = 1; - else - realtics = 5; - } - - gametime = nowtime; - if (server) { if (netgame && !(gametime % 35)) // update once per second. @@ -1241,6 +1265,149 @@ void NetUpdate(void) realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); pingmeasurecount++; } +} + +// Handle timeouts to prevent definitive freezes from happenning +static void HandleNodeTimeouts(void) +{ + if (server) + { + for (INT32 i = 1; i < MAXNETNODES; i++) + if (netnodes[i].ingame && netnodes[i].freezetimeout < I_GetTime()) + Net_ConnectionTimeout(i); + + // In case the cvar value was lowered + if (joindelay) + joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); + } +} + +// Keep the network alive while not advancing tics! +void NetKeepAlive(void) +{ + tic_t nowtime; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + // return if there's no time passed since the last call + if (realtics <= 0) // nothing new to update + return; + + UpdatePingTable(); + + GetPackets(); + +#ifdef MASTERSERVER + MasterClient_Ticker(); +#endif + + if (client) + { + // send keep alive + CL_SendClientKeepAlive(); + // No need to check for resynch because we aren't running any tics + } + else + { + SV_SendServerKeepAlive(); + } + + // No else because no tics are being run and we can't resynch during this + + Net_AckTicker(); + HandleNodeTimeouts(); + FileSendTicker(); +} + +void NetUpdate(void) +{ + static tic_t resptime = 0; + tic_t nowtime; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + if (realtics <= 0) // nothing new to update + return; + + if (realtics > 5) + { + if (server) + realtics = 1; + else + realtics = 5; + } + + if (server && dedicated && gamestate == GS_LEVEL) + { + const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; + static tic_t dedicatedidletimeprev = 0; + static tic_t dedicatedidle = 0; + + if (dedicatedidletime > 0) + { + INT32 i; + + for (i = 1; i < MAXNETNODES; ++i) + if (netnodes[i].ingame) + { + if (dedicatedidle >= dedicatedidletime) + { + CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i); + dedicatedidle = 0; + } + break; + } + + if (i == MAXNETNODES) + { + if (leveltime == 2) + { + // On next tick... + dedicatedidle = dedicatedidletime-1; + } + else if (dedicatedidle >= dedicatedidletime) + { + if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0)) + { + CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); + dedicatedidle = 0; + } + else + { + realtics = 0; + } + } + else if ((dedicatedidle += realtics) >= dedicatedidletime) + { + const char *idlereason = "at round start"; + if (leveltime > 3) + idlereason = va("for %d seconds", dedicatedidle/TICRATE); + + CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason); + realtics = 0; + dedicatedidle = dedicatedidletime; + } + } + } + else + { + if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) + { + CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); + } + dedicatedidle = 0; + } + + dedicatedidletimeprev = dedicatedidletime; + } + + gametime = nowtime; + + UpdatePingTable(); if (client) maketic = neededtic; @@ -1270,17 +1437,18 @@ void NetUpdate(void) } else { - if (!demoplayback) + if (!demoplayback && realtics > 0) { hu_redownloadinggamestate = false; firstticstosend = gametic; for (INT32 i = 0; i < MAXNETNODES; i++) - if (netnodes[i].ingame && netnodes[i].tic < firstticstosend) + if (netnodes[i].ingame) { - firstticstosend = netnodes[i].tic; + if (netnodes[i].tic < firstticstosend) + firstticstosend = netnodes[i].tic; - if (maketic + 1 >= netnodes[i].tic + BACKUPTICS) + if (maketic + realtics >= netnodes[i].tic + BACKUPTICS - TICRATE) Net_ConnectionTimeout(i); } @@ -1302,20 +1470,10 @@ void NetUpdate(void) } Net_AckTicker(); - - // Handle timeouts to prevent definitive freezes from happenning - if (server) - { - for (INT32 i = 1; i < MAXNETNODES; i++) - if (netnodes[i].ingame && netnodes[i].freezetimeout < I_GetTime()) - Net_ConnectionTimeout(i); - - // In case the cvar value was lowered - if (joindelay) - joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); - } + HandleNodeTimeouts(); nowtime /= NEWTICRATERATIO; + if (nowtime > resptime) { resptime = nowtime; @@ -1338,22 +1496,22 @@ void D_ClientServerInit(void) DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", VERSION/100, VERSION%100, SUBVERSION)); - COM_AddCommand("getplayernum", Command_GetPlayerNum); - COM_AddCommand("kick", Command_Kick); - COM_AddCommand("ban", Command_Ban); - COM_AddCommand("banip", Command_BanIP); - COM_AddCommand("clearbans", Command_ClearBans); - COM_AddCommand("showbanlist", Command_ShowBan); - COM_AddCommand("reloadbans", Command_ReloadBan); - COM_AddCommand("connect", Command_connect); - COM_AddCommand("nodes", Command_Nodes); - COM_AddCommand("resendgamestate", Command_ResendGamestate); + COM_AddCommand("getplayernum", Command_GetPlayerNum, COM_LUA); + COM_AddCommand("kick", Command_Kick, COM_LUA); + COM_AddCommand("ban", Command_Ban, COM_LUA); + COM_AddCommand("banip", Command_BanIP, COM_LUA); + COM_AddCommand("clearbans", Command_ClearBans, COM_LUA); + COM_AddCommand("showbanlist", Command_ShowBan, COM_LUA); + COM_AddCommand("reloadbans", Command_ReloadBan, COM_LUA); + COM_AddCommand("connect", Command_connect, COM_LUA); + COM_AddCommand("nodes", Command_Nodes, COM_LUA); + COM_AddCommand("resendgamestate", Command_ResendGamestate, COM_LUA); #ifdef PACKETDROP - COM_AddCommand("drop", Command_Drop); - COM_AddCommand("droprate", Command_Droprate); + COM_AddCommand("drop", Command_Drop, COM_LUA); + COM_AddCommand("droprate", Command_Droprate, COM_LUA); #endif #ifdef _DEBUG - COM_AddCommand("numnodes", Command_Numnodes); + COM_AddCommand("numnodes", Command_Numnodes, COM_LUA); #endif RegisterNetXCmd(XD_KICK, Got_KickCmd); @@ -1422,6 +1580,20 @@ INT32 D_NumPlayers(void) return num; } +/** Similar to the above, but counts only bots. + * Purpose is to remove bots from both the player count and the + * max player count on the server view +*/ +INT32 D_NumBots(void) +{ + INT32 num = 0, ix; + for (ix = 0; ix < MAXPLAYERS; ix++) + if (playeringame[ix] && players[ix].bot) + num++; + return num; +} + + // // Consistancy // diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 0abd638ce..d87ead9ec 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_dedicatedidletime; // Used in d_net, the only dependence void D_ClientServerInit(void); @@ -81,6 +81,9 @@ void D_ClientServerInit(void); // Create any new ticcmds and broadcast to other players. void NetUpdate(void); +// Maintain connections to nodes without timing them all out. +void NetKeepAlive(void); + void GetPackets(void); void ResetNode(INT32 node); INT16 Consistancy(void); @@ -118,6 +121,7 @@ extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); +INT32 D_NumBots(void); tic_t GetLag(INT32 node); diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index a4b0778e3..cfb1963b9 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -760,6 +760,8 @@ static const char *packettypename[NUMPACKETTYPE] = "ASKLUAFILE", "HASLUAFILE", + "PT_BASICKEEPALIVE", + "FILEFRAGMENT", "FILEACK", "FILERECEIVED", @@ -818,6 +820,9 @@ static void DebugPrintpacket(const char *header) (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode), (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode)); break; + case PT_BASICKEEPALIVE: + fprintf(debugfile, " wipetime\n"); + break; case PT_TEXTCMD: case PT_TEXTCMD2: fprintf(debugfile, " length %d\n ", netbuffer->u.textcmd[0]); @@ -1140,26 +1145,32 @@ static void Internal_FreeNodenum(INT32 nodenum) (void)nodenum; } +char *I_NetSplitAddress(char *host, char **port) +{ + boolean v4 = (strchr(host, '.') != NULL); + + host = strtok(host, v4 ? ":" : "[]"); + + if (port) + *port = strtok(NULL, ":"); + + return host; +} + SINT8 I_NetMakeNode(const char *hostname) { SINT8 newnode = -1; if (I_NetMakeNodewPort) { char *localhostname = strdup(hostname); - char *t = localhostname; - const char *port; + char *port; if (!localhostname) return newnode; + // retrieve portnum from address! - strtok(localhostname, ":"); - port = strtok(NULL, ":"); + hostname = I_NetSplitAddress(localhostname, &port); - // remove the port in the hostname as we've it already - while ((*t != ':') && (*t != '\0')) - t++; - *t = '\0'; - - newnode = I_NetMakeNodewPort(localhostname, port); + newnode = I_NetMakeNodewPort(hostname, port); free(localhostname); } return newnode; diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h index 039f5b3b4..549f2b93c 100644 --- a/src/netcode/d_net.h +++ b/src/netcode/d_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 0d1785510..8f5b433bc 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,7 +21,6 @@ #include "../g_game.h" #include "../hu_stuff.h" #include "../g_input.h" -#include "../i_gamepad.h" #include "../m_menu.h" #include "../r_local.h" #include "../r_skins.h" @@ -52,6 +51,7 @@ #include "../m_anigif.h" #include "../md5.h" #include "../m_perfstats.h" +#include "../u_list.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -184,6 +184,14 @@ static CV_PossibleValue_t mouse2port_cons_t[] = {{1, "COM1"}, {2, "COM2"}, {3, " {0, NULL}}; #endif +#ifdef LJOYSTICK +static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {3, "/dev/js2"}, + {4, "/dev/js3"}, {0, NULL}}; +#else +// accept whatever value - it is in fact the joystick device number +#define usejoystick_cons_t NULL +#endif + static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}}; static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; @@ -197,37 +205,37 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; -consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL); +consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", CV_ALLOWLUA, CV_OnOff, NULL); #ifdef NETGAME_DEVMODE static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange); #endif static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); -consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); -consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, NULL); +consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL); +consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, startingliveslimit_cons_t, NULL); static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); +consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, respawntime_cons_t, NULL); -consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); +consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, competitionboxes_cons_t, NULL); static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; -consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0); -consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE|CV_ALLOWLUA, seenames_cons_t, 0); +consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); // names consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange); // player colors UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE; -consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange); -consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange); +consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color_OnChange); +consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT|CV_ALLOWLUA, Color_cons_t, Color2_OnChange); // player's skin, saved for commodity, when using a favorite skins wad.. -consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange); -consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange); +consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin_OnChange); +consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Skin2_OnChange); // saved versions of the above six consvar_t cv_defaultplayercolor = CVAR_INIT ("defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL); @@ -242,61 +250,19 @@ INT32 cv_debug; consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse); consvar_t cv_usemouse2 = CVAR_INIT ("use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2); -// We use cv_usegamepad.string as the USER-SET var -// and cv_usegamepad.value as the INTERNAL var -// -// In practice, if cv_usegamepad.string == 0, this overrides -// cv_usegamepad.value and always disables - -static void UseGamepad_OnChange(void) -{ - I_ChangeGamepad(0); -} - -static void UseGamepad2_OnChange(void) -{ - I_ChangeGamepad(1); -} - -consvar_t cv_usegamepad[2] = { - CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, NULL, UseGamepad_OnChange), - CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, NULL, UseGamepad2_OnChange) -}; - -static void PadScale_OnChange(void) -{ - I_SetGamepadDigital(0, cv_gamepad_scale[0].value == 0); -} - -static void PadScale2_OnChange(void) -{ - I_SetGamepadDigital(1, cv_gamepad_scale[1].value == 0); -} - -consvar_t cv_gamepad_scale[2] = { - CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, PadScale_OnChange), - CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, PadScale2_OnChange) -}; - -static void PadRumble_OnChange(void) -{ - if (!cv_gamepad_rumble[0].value) - I_StopGamepadRumble(0); -} - -static void PadRumble2_OnChange(void) -{ - if (!cv_gamepad_rumble[1].value) - I_StopGamepadRumble(1); -} - -consvar_t cv_gamepad_rumble[2] = { - CVAR_INIT ("padrumble", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble_OnChange), - CVAR_INIT ("padrumble2", "Off", CV_SAVE|CV_CALL, CV_OnOff, PadRumble2_OnChange) -}; - -consvar_t cv_gamepad_autopause = CVAR_INIT ("pauseongamepaddisconnect", "On", CV_SAVE, CV_OnOff, NULL); - +consvar_t cv_usejoystick = CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick); +consvar_t cv_usejoystick2 = CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2); +#if (defined (LJOYSTICK) || defined (HAVE_SDL)) +#ifdef LJOYSTICK +consvar_t cv_joyport = CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); +consvar_t cv_joyport2 = CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); //Alam: for later +#endif +consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale); +consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2); +#else +consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save +consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save +#endif #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL); consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); @@ -304,43 +270,43 @@ consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL); #endif -consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL); -consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, matchboxes_cons_t, NULL); +consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); +consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, chances_cons_t, NULL); -consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange); -consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); +consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT|CV_ALLOWLUA, CV_YesNo, Ringslinger_OnChange); +consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL|CV_ALLOWLUA, NULL, Gravity_OnChange); consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange); static CV_PossibleValue_t minitimelimit_cons_t[] = {{1, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); +consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT|CV_ALLOWLUA, minitimelimit_cons_t, NULL); -consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange); +consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, minitimelimit_cons_t, Hidetime_OnChange); -consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); -consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); -consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL); +consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, AutoBalance_OnChange); +consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, teamscramble_cons_t, TeamScramble_OnChange); +consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, teamscramble_cons_t, NULL); -consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange); +consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); +consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL|CV_ALLOWLUA, CV_OnOff, ItemFinder_OnChange); // Scoring type options -consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL); @@ -351,13 +317,13 @@ static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-pe consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL); static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); +consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, pointlimit_cons_t, PointLimit_OnChange); static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); +consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, timelimit_cons_t, TimeLimit_OnChange); static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}}; -consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); +consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, numlaps_cons_t, NumLaps_OnChange); static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); +consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, basenumlaps_cons_t, BaseNumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -366,11 +332,11 @@ INT32 timelimits[NUMGAMETYPES]; // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL); -consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); +consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, NULL, ForceSkin_OnChange); consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); -consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; @@ -388,26 +354,26 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; -consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL); +consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, inttime_cons_t, NULL); static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}}; -consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange); +consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, coopstarposts_cons_t, CoopStarposts_OnChange); static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}}; -consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange); +consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT|CV_ALLOWLUA, cooplives_cons_t, CoopLives_OnChange); static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; -consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL); +consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, advancemap_cons_t, NULL); static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}}; -consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL); +consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, playersforexit_cons_t, NULL); -consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange); +consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, ExitMove_OnChange); -consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL); +consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", CV_ALLOWLUA, CV_YesNo, NULL); -consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL); -consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange); +consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, pause_cons_t, NULL); +consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_OnOff, Mute_OnChange); consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); @@ -500,57 +466,57 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_LUAFILE, Got_LuaFile); // Remote Administration - COM_AddCommand("password", Command_Changepassword_f); - COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin - COM_AddCommand("promote", Command_Verify_f); + COM_AddCommand("password", Command_Changepassword_f, COM_LUA); + COM_AddCommand("login", Command_Login_f, COM_LUA); // useful in dedicated to kick off remote admin + COM_AddCommand("promote", Command_Verify_f, COM_LUA); RegisterNetXCmd(XD_VERIFIED, Got_Verification); - COM_AddCommand("demote", Command_RemoveAdmin_f); + COM_AddCommand("demote", Command_RemoveAdmin_f, COM_LUA); RegisterNetXCmd(XD_DEMOTED, Got_Removal); - COM_AddCommand("motd", Command_MotD_f); + COM_AddCommand("motd", Command_MotD_f, COM_LUA); RegisterNetXCmd(XD_SETMOTD, Got_MotD_f); // For remote admin RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange); - COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f); + COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA); RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores); - COM_AddCommand("clearscores", Command_Clearscores_f); - COM_AddCommand("map", Command_Map_f); + COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA); + COM_AddCommand("map", Command_Map_f, COM_LUA); - COM_AddCommand("exitgame", Command_ExitGame_f); - COM_AddCommand("retry", Command_Retry_f); - COM_AddCommand("exitlevel", Command_ExitLevel_f); - COM_AddCommand("showmap", Command_Showmap_f); - COM_AddCommand("mapmd5", Command_Mapmd5_f); + COM_AddCommand("exitgame", Command_ExitGame_f, COM_LUA); + COM_AddCommand("retry", Command_Retry_f, COM_LUA); + COM_AddCommand("exitlevel", Command_ExitLevel_f, COM_LUA); + COM_AddCommand("showmap", Command_Showmap_f, COM_LUA); + COM_AddCommand("mapmd5", Command_Mapmd5_f, COM_LUA); - COM_AddCommand("addfolder", Command_Addfolder); - COM_AddCommand("addfile", Command_Addfile); - COM_AddCommand("listwad", Command_ListWADS_f); + COM_AddCommand("addfolder", Command_Addfolder, COM_LUA); + COM_AddCommand("addfile", Command_Addfile, COM_LUA); + COM_AddCommand("listwad", Command_ListWADS_f, COM_LUA); - COM_AddCommand("runsoc", Command_RunSOC); - COM_AddCommand("pause", Command_Pause); - COM_AddCommand("suicide", Command_Suicide); + COM_AddCommand("runsoc", Command_RunSOC, COM_LUA); + COM_AddCommand("pause", Command_Pause, COM_LUA); + COM_AddCommand("suicide", Command_Suicide, COM_LUA); - COM_AddCommand("gametype", Command_ShowGametype_f); - COM_AddCommand("version", Command_Version_f); + COM_AddCommand("gametype", Command_ShowGametype_f, COM_LUA); + COM_AddCommand("version", Command_Version_f, COM_LUA); #ifdef UPDATE_ALERT - COM_AddCommand("mod_details", Command_ModDetails_f); + COM_AddCommand("mod_details", Command_ModDetails_f, COM_LUA); #endif - COM_AddCommand("quit", Command_Quit_f); + COM_AddCommand("quit", Command_Quit_f, COM_LUA); - COM_AddCommand("saveconfig", Command_SaveConfig_f); - COM_AddCommand("loadconfig", Command_LoadConfig_f); - COM_AddCommand("changeconfig", Command_ChangeConfig_f); - COM_AddCommand("isgamemodified", Command_Isgamemodified_f); // test - COM_AddCommand("showscores", Command_ShowScores_f); - COM_AddCommand("showtime", Command_ShowTime_f); - COM_AddCommand("cheats", Command_Cheats_f); // test + COM_AddCommand("saveconfig", Command_SaveConfig_f, 0); + COM_AddCommand("loadconfig", Command_LoadConfig_f, 0); + COM_AddCommand("changeconfig", Command_ChangeConfig_f, 0); + COM_AddCommand("isgamemodified", Command_Isgamemodified_f, COM_LUA); // test + COM_AddCommand("showscores", Command_ShowScores_f, COM_LUA); + COM_AddCommand("showtime", Command_ShowTime_f, COM_LUA); + COM_AddCommand("cheats", Command_Cheats_f, COM_LUA); // test #ifdef _DEBUG - COM_AddCommand("togglemodified", Command_Togglemodified_f); - COM_AddCommand("archivetest", Command_Archivetest_f); + COM_AddCommand("togglemodified", Command_Togglemodified_f, COM_LUA); + COM_AddCommand("archivetest", Command_Archivetest_f, COM_LUA); #endif - COM_AddCommand("downloads", Command_Downloads_f); + COM_AddCommand("downloads", Command_Downloads_f, COM_LUA); // for master server connection AddMServCommands(); @@ -633,8 +599,9 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allownewplayer); CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); + CV_RegisterVar(&cv_dedicatedidletime); - COM_AddCommand("ping", Command_Ping_f); + COM_AddCommand("ping", Command_Ping_f, COM_LUA); CV_RegisterVar(&cv_nettimeout); CV_RegisterVar(&cv_jointimeout); @@ -646,6 +613,10 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allowseenames); + // Other filesrch.c consvars are defined in D_RegisterClientCommands + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_dummyconsvar); } @@ -678,25 +649,25 @@ void D_RegisterClientCommands(void) if (dedicated) return; - COM_AddCommand("numthinkers", Command_Numthinkers_f); - COM_AddCommand("countmobjs", Command_CountMobjs_f); + COM_AddCommand("numthinkers", Command_Numthinkers_f, COM_LUA); + COM_AddCommand("countmobjs", Command_CountMobjs_f, COM_LUA); - COM_AddCommand("changeteam", Command_Teamchange_f); - COM_AddCommand("changeteam2", Command_Teamchange2_f); + COM_AddCommand("changeteam", Command_Teamchange_f, COM_LUA); + COM_AddCommand("changeteam2", Command_Teamchange2_f, COM_LUA); - COM_AddCommand("playdemo", Command_Playdemo_f); - COM_AddCommand("timedemo", Command_Timedemo_f); - COM_AddCommand("stopdemo", Command_Stopdemo_f); - COM_AddCommand("playintro", Command_Playintro_f); + COM_AddCommand("playdemo", Command_Playdemo_f, 0); + COM_AddCommand("timedemo", Command_Timedemo_f, 0); + COM_AddCommand("stopdemo", Command_Stopdemo_f, COM_LUA); + COM_AddCommand("playintro", Command_Playintro_f, COM_LUA); - COM_AddCommand("resetcamera", Command_ResetCamera_f); + COM_AddCommand("resetcamera", Command_ResetCamera_f, COM_LUA); - COM_AddCommand("setcontrol", Command_Setcontrol_f); - COM_AddCommand("setcontrol2", Command_Setcontrol2_f); + COM_AddCommand("setcontrol", Command_Setcontrol_f, 0); + COM_AddCommand("setcontrol2", Command_Setcontrol2_f, 0); - COM_AddCommand("screenshot", M_ScreenShot); - COM_AddCommand("startmovie", Command_StartMovie_f); - COM_AddCommand("stopmovie", Command_StopMovie_f); + COM_AddCommand("screenshot", M_ScreenShot, COM_LUA); + COM_AddCommand("startmovie", Command_StartMovie_f, COM_LUA); + COM_AddCommand("stopmovie", Command_StopMovie_f, COM_LUA); CV_RegisterVar(&cv_screenshot_option); CV_RegisterVar(&cv_screenshot_folder); @@ -758,7 +729,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ghost_last); CV_RegisterVar(&cv_ghost_guest); - COM_AddCommand("displayplayer", Command_Displayplayer_f); + COM_AddCommand("displayplayer", Command_Displayplayer_f, COM_LUA); // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_globalgamma); @@ -805,30 +776,30 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_pauseifunfocused); // g_input.c - CV_RegisterVar(&cv_sideaxis[0]); - CV_RegisterVar(&cv_sideaxis[1]); - CV_RegisterVar(&cv_turnaxis[0]); - CV_RegisterVar(&cv_turnaxis[1]); - CV_RegisterVar(&cv_moveaxis[0]); - CV_RegisterVar(&cv_moveaxis[1]); - CV_RegisterVar(&cv_lookaxis[0]); - CV_RegisterVar(&cv_lookaxis[1]); - CV_RegisterVar(&cv_jumpaxis[0]); - CV_RegisterVar(&cv_jumpaxis[1]); - CV_RegisterVar(&cv_spinaxis[0]); - CV_RegisterVar(&cv_spinaxis[1]); - CV_RegisterVar(&cv_fireaxis[0]); - CV_RegisterVar(&cv_fireaxis[1]); - CV_RegisterVar(&cv_firenaxis[0]); - CV_RegisterVar(&cv_firenaxis[1]); - CV_RegisterVar(&cv_deadzone[0]); - CV_RegisterVar(&cv_deadzone[1]); - CV_RegisterVar(&cv_digitaldeadzone[0]); - CV_RegisterVar(&cv_digitaldeadzone[1]); + CV_RegisterVar(&cv_sideaxis); + CV_RegisterVar(&cv_sideaxis2); + CV_RegisterVar(&cv_turnaxis); + CV_RegisterVar(&cv_turnaxis2); + CV_RegisterVar(&cv_moveaxis); + CV_RegisterVar(&cv_moveaxis2); + CV_RegisterVar(&cv_lookaxis); + CV_RegisterVar(&cv_lookaxis2); + CV_RegisterVar(&cv_jumpaxis); + CV_RegisterVar(&cv_jumpaxis2); + CV_RegisterVar(&cv_spinaxis); + CV_RegisterVar(&cv_spinaxis2); + CV_RegisterVar(&cv_fireaxis); + CV_RegisterVar(&cv_fireaxis2); + CV_RegisterVar(&cv_firenaxis); + CV_RegisterVar(&cv_firenaxis2); + CV_RegisterVar(&cv_deadzone); + CV_RegisterVar(&cv_deadzone2); + CV_RegisterVar(&cv_digitaldeadzone); + CV_RegisterVar(&cv_digitaldeadzone2); // filesrch.c - CV_RegisterVar(&cv_addons_option); - CV_RegisterVar(&cv_addons_folder); + //CV_RegisterVar(&cv_addons_option); // These two are now defined + //CV_RegisterVar(&cv_addons_folder); // in D_RegisterServerCommands CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); CV_RegisterVar(&cv_addons_search_type); @@ -853,14 +824,14 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_mousemove); CV_RegisterVar(&cv_mousemove2); - for (i = 0; i < 2; i++) - { - CV_RegisterVar(&cv_usegamepad[i]); - CV_RegisterVar(&cv_gamepad_scale[i]); - CV_RegisterVar(&cv_gamepad_rumble[i]); - } - - CV_RegisterVar(&cv_gamepad_autopause); + CV_RegisterVar(&cv_usejoystick); + CV_RegisterVar(&cv_usejoystick2); +#ifdef LJOYSTICK + CV_RegisterVar(&cv_joyport); + CV_RegisterVar(&cv_joyport2); +#endif + CV_RegisterVar(&cv_joyscale); + CV_RegisterVar(&cv_joyscale2); // Analog Control CV_RegisterVar(&cv_analog[0]); @@ -902,10 +873,15 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderhitboxinterpolation); + CV_RegisterVar(&cv_renderhitboxgldepth); + CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); + CV_RegisterVar(&cv_scr_width_w); + CV_RegisterVar(&cv_scr_height_w); CV_RegisterVar(&cv_soundtest); @@ -914,7 +890,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ps_descriptor); // ingame object placing - COM_AddCommand("objectplace", Command_ObjectPlace_f); + COM_AddCommand("objectplace", Command_ObjectPlace_f, COM_LUA); //COM_AddCommand("writethings", Command_Writethings_f); CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_opflags); @@ -926,32 +902,32 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_freedemocamera); // add cheat commands - COM_AddCommand("noclip", Command_CheatNoClip_f); - COM_AddCommand("god", Command_CheatGod_f); - COM_AddCommand("notarget", Command_CheatNoTarget_f); - COM_AddCommand("getallemeralds", Command_Getallemeralds_f); - COM_AddCommand("resetemeralds", Command_Resetemeralds_f); - COM_AddCommand("setrings", Command_Setrings_f); - COM_AddCommand("setlives", Command_Setlives_f); - COM_AddCommand("setcontinues", Command_Setcontinues_f); - COM_AddCommand("devmode", Command_Devmode_f); - COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f); - COM_AddCommand("scale", Command_Scale_f); - COM_AddCommand("gravflip", Command_Gravflip_f); - COM_AddCommand("hurtme", Command_Hurtme_f); - COM_AddCommand("jumptoaxis", Command_JumpToAxis_f); - COM_AddCommand("charability", Command_Charability_f); - COM_AddCommand("charspeed", Command_Charspeed_f); - COM_AddCommand("teleport", Command_Teleport_f); - COM_AddCommand("rteleport", Command_RTeleport_f); - COM_AddCommand("skynum", Command_Skynum_f); - COM_AddCommand("weather", Command_Weather_f); - COM_AddCommand("toggletwod", Command_Toggletwod_f); + COM_AddCommand("noclip", Command_CheatNoClip_f, COM_LUA); + COM_AddCommand("god", Command_CheatGod_f, COM_LUA); + COM_AddCommand("notarget", Command_CheatNoTarget_f, COM_LUA); + COM_AddCommand("getallemeralds", Command_Getallemeralds_f, COM_LUA); + COM_AddCommand("resetemeralds", Command_Resetemeralds_f, COM_LUA); + COM_AddCommand("setrings", Command_Setrings_f, COM_LUA); + COM_AddCommand("setlives", Command_Setlives_f, COM_LUA); + COM_AddCommand("setcontinues", Command_Setcontinues_f, COM_LUA); + COM_AddCommand("devmode", Command_Devmode_f, COM_LUA); + COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f, COM_LUA); + COM_AddCommand("scale", Command_Scale_f, COM_LUA); + COM_AddCommand("gravflip", Command_Gravflip_f, COM_LUA); + COM_AddCommand("hurtme", Command_Hurtme_f, COM_LUA); + COM_AddCommand("jumptoaxis", Command_JumpToAxis_f, COM_LUA); + COM_AddCommand("charability", Command_Charability_f, COM_LUA); + COM_AddCommand("charspeed", Command_Charspeed_f, COM_LUA); + COM_AddCommand("teleport", Command_Teleport_f, COM_LUA); + COM_AddCommand("rteleport", Command_RTeleport_f, COM_LUA); + COM_AddCommand("skynum", Command_Skynum_f, COM_LUA); + COM_AddCommand("weather", Command_Weather_f, COM_LUA); + COM_AddCommand("toggletwod", Command_Toggletwod_f, COM_LUA); #ifdef _DEBUG - COM_AddCommand("causecfail", Command_CauseCfail_f); + COM_AddCommand("causecfail", Command_CauseCfail_f, COM_LUA); #endif #ifdef LUA_ALLOW_BYTECODE - COM_AddCommand("dumplua", Command_Dumplua_f); + COM_AddCommand("dumplua", Command_Dumplua_f, COM_LUA); #endif } @@ -1666,9 +1642,14 @@ static void Command_Playdemo_f(void) { char name[256]; - if (COM_Argc() != 2) + if (COM_Argc() < 2) { - CONS_Printf(M_GetText("playdemo : playback a demo\n")); + CONS_Printf("playdemo [-addfiles / -force]:\n"); + CONS_Printf(M_GetText( + "Play back a demo file. The full path from your SRB2 directory must be given.\n\n" + + "* With \"-addfiles\", any required files are added from a list contained within the demo file.\n" + "* With \"-force\", the demo is played even if the necessary files have not been added.\n")); return; } @@ -1690,6 +1671,16 @@ static void Command_Playdemo_f(void) CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); + demofileoverride = DFILE_OVERRIDE_NONE; + if (strcmp(COM_Argv(2), "-addfiles") == 0) + { + demofileoverride = DFILE_OVERRIDE_LOAD; + } + else if (strcmp(COM_Argv(2), "-force") == 0) + { + demofileoverride = DFILE_OVERRIDE_SKIP; + } + // Internal if no extension, external if one exists // If external, convert the file name to a path in SRB2's home directory if (FIL_CheckExtension(name)) @@ -1910,7 +1901,7 @@ static void Command_Map_f(void) const char *gametypename; boolean newresetplayers; - boolean mustmodifygame; + boolean wouldSetCheats; INT32 newmapnum; @@ -1931,11 +1922,11 @@ static void Command_Map_f(void) option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - mustmodifygame = - !( netgame || multiplayer ) && - (!modifiedgame || savemoddata ); + wouldSetCheats = + !( netgame || multiplayer ) && + !( usedCheats ); - if (mustmodifygame && !option_force) + if (wouldSetCheats && !option_force) { /* May want to be more descriptive? */ CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); @@ -1989,9 +1980,9 @@ static void Command_Map_f(void) return; } - if (mustmodifygame && option_force) + if (wouldSetCheats && option_force) { - G_SetGameModified(false); + G_SetUsedCheats(false); } // new gametype value @@ -2064,7 +2055,7 @@ static void Command_Map_f(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - if (!dedicated && M_MapLocked(newmapnum)) + if (!dedicated && M_MapLocked(newmapnum, serverGamedata)) { CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); Z_Free(realmapname); @@ -2199,7 +2190,7 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION)) + if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_WAITINGPLAYERS) || (marathonmode && gamestate == GS_INTERMISSION)) { CONS_Printf(M_GetText("You can't pause here.\n")); return; @@ -2248,14 +2239,9 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) { if (!menuactive || netgame) S_PauseAudio(); - - P_PauseRumble(NULL); } else - { S_ResumeAudio(); - P_UnpauseRumble(NULL); - } } I_UpdateMouseGrab(); @@ -2367,7 +2353,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) } for (i = 0; i < MAXPLAYERS; i++) - players[i].score = 0; + players[i].score = players[i].recordscore = 0; CONS_Printf(M_GetText("Scores have been reset by the server.\n")); } @@ -3310,6 +3296,69 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) G_SetGameModified(true); } +// C++ would make this SO much simpler! +typedef struct addedfile_s +{ + struct addedfile_s *next; + struct addedfile_s *prev; + char *value; +} addedfile_t; + +static boolean AddedFileContains(addedfile_t *list, const char *value) +{ + addedfile_t *node; + for (node = list; node; node = node->next) + { + if (!strcmp(value, node->value)) + return true; + } + + return false; +} + +static void AddedFilesAdd(addedfile_t **list, const char *value) +{ + addedfile_t *item = Z_Calloc(sizeof(addedfile_t), PU_STATIC, NULL); + item->value = Z_StrDup(value); + ListAdd(item, (listitem_t**)list); +} + +static void AddedFilesRemove(void *pItem, addedfile_t **itemHead) +{ + addedfile_t *item = (addedfile_t *)pItem; + + if (item == *itemHead) // Start of list + { + *itemHead = item->next; + + if (*itemHead) + (*itemHead)->prev = NULL; + } + else if (item->next == NULL) // end of list + { + item->prev->next = NULL; + } + else // Somewhere in between + { + item->prev->next = item->next; + item->next->prev = item->prev; + } + + Z_Free(item->value); + Z_Free(item); +} + +static void AddedFilesClearList(addedfile_t **itemHead) +{ + addedfile_t *item; + addedfile_t *next; + for (item = *itemHead; item; item = next) + { + next = item->next; + AddedFilesRemove(item, itemHead); + } +} + /** Adds a pwad at runtime. * Searches for sounds, maps, music, new images. */ @@ -3318,8 +3367,7 @@ static void Command_Addfile(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - const char *addedfiles[argc]; // list of filenames already processed - size_t numfilesadded = 0; // the amount of filenames processed + addedfile_t *addedfiles = NULL; // list of filenames already processed if (argc < 2) { @@ -3334,25 +3382,14 @@ static void Command_Addfile(void) char buf[256]; char *buf_p = buf; INT32 i; - size_t ii; int musiconly; // W_VerifyNMUSlumps isn't boolean boolean fileadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - for (ii = 0; ii < numfilesadded; ii++) - { - // If this is one of them, don't try to add it. - if (!strcmp(fn, addedfiles[ii])) - { - fileadded = true; - break; - } - } - - // If we've added this one, skip to the next one. - if (fileadded) + fileadded = AddedFileContains(addedfiles, fn); + if (fileadded) // If this is one of them, don't try to add it. { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3361,13 +3398,16 @@ static void Command_Addfile(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') + { + AddedFilesClearList(&addedfiles); return; + } musiconly = W_VerifyNMUSlumps(fn, false); if (musiconly == -1) { - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); continue; } @@ -3386,7 +3426,7 @@ static void Command_Addfile(void) if (!(netgame || multiplayer) || musiconly) { P_AddWadFile(fn); - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); continue; } @@ -3401,6 +3441,7 @@ static void Command_Addfile(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + AddedFilesClearList(&addedfiles); return; } @@ -3440,13 +3481,15 @@ static void Command_Addfile(void) WRITEMEM(buf_p, md5sum, 16); } - addedfiles[numfilesadded++] = fn; + AddedFilesAdd(&addedfiles, fn); if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } + + AddedFilesClearList(&addedfiles); } static void Command_Addfolder(void) @@ -3454,8 +3497,7 @@ static void Command_Addfolder(void) size_t argc = COM_Argc(); // amount of arguments total size_t curarg; // current argument index - const char *addedfolders[argc]; // list of filenames already processed - size_t numfoldersadded = 0; // the amount of filenames processed + addedfile_t *addedfolders = NULL; // list of filenames already processed if (argc < 2) { @@ -3471,24 +3513,13 @@ static void Command_Addfolder(void) char buf[256]; char *buf_p = buf; INT32 i, stat; - size_t ii; boolean folderadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - for (ii = 0; ii < numfoldersadded; ii++) - { - // If this is one of them, don't try to add it. - if (!strcmp(fn, addedfolders[ii])) - { - folderadded = true; - break; - } - } - - // If we've added this one, skip to the next one. - if (folderadded) + folderadded = AddedFileContains(addedfolders, fn); + if (folderadded) // If we've added this one, skip to the next one. { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -3497,13 +3528,16 @@ static void Command_Addfolder(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) if (!isprint(fn[i]) || fn[i] == ';') + { + AddedFilesClearList(&addedfolders); return; + } // Add file on your client directly if you aren't in a netgame. if (!(netgame || multiplayer)) { P_AddFolder(fn); - addedfolders[numfoldersadded++] = fn; + AddedFilesAdd(&addedfolders, fn); continue; } @@ -3525,6 +3559,7 @@ static void Command_Addfolder(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + AddedFilesClearList(&addedfolders); return; } @@ -3570,7 +3605,7 @@ static void Command_Addfolder(void) Z_Free(fullpath); - addedfolders[numfoldersadded++] = fn; + AddedFilesAdd(&addedfolders, fn); WRITESTRINGN(buf_p,p,240); @@ -3929,18 +3964,12 @@ void ItemFinder_OnChange(void) if (!cv_itemfinder.value) return; // it's fine. - if (!M_SecretUnlocked(SECRET_ITEMFINDER)) + if (!M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_itemfinder, 0); return; } - else if (netgame || multiplayer) - { - CONS_Printf(M_GetText("This only works in single player.\n")); - CV_StealthSetValue(&cv_itemfinder, 0); - return; - } } /** Deals with a pointlimit change by printing the change to the console. @@ -4289,7 +4318,7 @@ void D_GameTypeChanged(INT32 lastgametype) static void Ringslinger_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && cv_ringslinger.value && !cv_debug) + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && cv_ringslinger.value && !cv_debug) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_ringslinger, 0); @@ -4297,12 +4326,12 @@ static void Ringslinger_OnChange(void) } if (cv_ringslinger.value) // Only if it's been turned on - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void Gravity_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && !cv_debug && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); @@ -4318,7 +4347,7 @@ static void Gravity_OnChange(void) #endif if (!CV_IsSetToDefault(&cv_gravity)) - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); gravity = cv_gravity.value; } @@ -4599,10 +4628,9 @@ void Command_ExitGame_f(void) botskin = 0; cv_debug = 0; emeralds = 0; + automapactive = false; memset(&luabanks, 0, sizeof(luabanks)); - P_StopRumble(NULL); - if (dirmenu) closefilemenu(true); @@ -4636,7 +4664,7 @@ static void Fishcake_OnChange(void) // so don't make modifiedgame always on! if (cv_debug) { - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } else if (cv_debug != cv_fishcake.value) @@ -4653,11 +4681,11 @@ static void Fishcake_OnChange(void) static void Command_Isgamemodified_f(void) { if (savemoddata) - CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n")); + CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n")); else if (modifiedgame) - CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); + CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n")); else - CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); + CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n")); } static void Command_Cheats_f(void) diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h index 797a686a7..22ee0695d 100644 --- a/src/netcode/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,10 +33,14 @@ extern consvar_t cv_defaultskin2; extern consvar_t cv_seenames, cv_allowseenames; extern consvar_t cv_usemouse; -extern consvar_t cv_usegamepad[2]; -extern consvar_t cv_gamepad_scale[2]; -extern consvar_t cv_gamepad_rumble[2]; -extern consvar_t cv_gamepad_autopause; +extern consvar_t cv_usejoystick; +extern consvar_t cv_usejoystick2; +#ifdef LJOYSTICK +extern consvar_t cv_joyport; +extern consvar_t cv_joyport2; +#endif +extern consvar_t cv_joyscale; +extern consvar_t cv_joyscale2; // splitscreen with second mouse extern consvar_t cv_mouse2port; diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 10b7359ad..c5ddef7b6 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -504,7 +504,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; j < numwadfiles; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && diff --git a/src/netcode/d_netfil.h b/src/netcode/d_netfil.h index 850e24d49..fdbec8c53 100644 --- a/src/netcode/d_netfil.h +++ b/src/netcode/d_netfil.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index c1ceb95b5..9c243ea73 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,7 +29,6 @@ #include "../lua_script.h" #include "../lzf.h" #include "../m_misc.h" -#include "../p_haptic.h" #include "../p_local.h" #include "../p_saveg.h" #include "../r_main.h" @@ -200,8 +199,6 @@ void CL_LoadReceivedSavegame(boolean reloading) titledemo = false; automapactive = false; - P_StopRumble(NULL); - // load a base level if (P_LoadNetGame(reloading)) { diff --git a/src/netcode/gamestate.h b/src/netcode/gamestate.h index 9d2779772..a2fae1f14 100644 --- a/src/netcode/gamestate.h +++ b/src/netcode/gamestate.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index 68e46b52a..7dc157ee4 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -66,6 +66,8 @@ static I_mutex hms_api_mutex; static char *hms_server_token; +static char hms_useragent[512]; + struct HMS_buffer { CURL *curl; @@ -82,6 +84,22 @@ Contact_error (void) ); } +static void +get_user_agent(char *buf, size_t len) +{ + if (snprintf(buf, len, "%s/%s (%s; %s; %i; %i) SRB2BASE/%i", SRB2APPLICATION, VERSIONSTRING, compbranch, comprevision, MODID, MODVERSION, CODEBASE) < 0) + I_Error("http-mserv: get_user_agent failed"); +} + +static void +init_user_agent_once(void) +{ + if (hms_useragent[0] != '\0') + return; + + get_user_agent(hms_useragent, 512); +} + static size_t HMS_on_read (char *s, size_t _1, size_t n, void *userdata) { @@ -157,6 +175,8 @@ HMS_connect (const char *format, ...) I_lock_mutex(&hms_api_mutex); #endif + init_user_agent_once(); + seek = strlen(hms_api) + 1;/* + '/' */ va_start (ap, format); @@ -197,12 +217,18 @@ HMS_connect (const char *format, ...) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + +#ifndef NO_IPV6 + if (M_CheckParm("-noipv6")) +#endif + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer); + curl_easy_setopt(curl, CURLOPT_USERAGENT, hms_useragent); + curl_free(quack_token); free(url); diff --git a/src/netcode/i_addrinfo.c b/src/netcode/i_addrinfo.c index 49aadf27d..9efaff4da 100644 --- a/src/netcode/i_addrinfo.c +++ b/src/netcode/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2022 by Sonic Team Junior. +// Copyright (C) 2011-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/i_addrinfo.h b/src/netcode/i_addrinfo.h index 592e693f4..79cfb05b2 100644 --- a/src/netcode/i_addrinfo.h +++ b/src/netcode/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2022 by Sonic Team Junior. +// Copyright (C) 2011-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/i_net.h b/src/netcode/i_net.h index 66126d050..09b842296 100644 --- a/src/netcode/i_net.h +++ b/src/netcode/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -109,6 +109,17 @@ extern boolean (*I_NetCanSend)(void); */ extern void (*I_NetFreeNodenum)(INT32 nodenum); +/** + \brief split a string into address and port + + \param address string to split + + \param port double pointer to hold port component (optional) + + \return address component +*/ +extern char *I_NetSplitAddress(char *address, char **port); + /** \brief open a connection with specified address \param address address to connect to diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index bd950c355..698234579 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -328,8 +328,14 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype) static const char *SOCK_AddrToStr(mysockaddr_t *sk) { - static char s[64]; // 255.255.255.255:65535 or IPv6:65535 + static char s[64]; // 255.255.255.255:65535 or + // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 #ifdef HAVE_NTOP +#ifdef HAVE_IPV6 + int v6 = (sk->any.sa_family == AF_INET6); +#else + int v6 = 0; +#endif void *addr; if(sk->any.sa_family == AF_INET) @@ -343,14 +349,21 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) if(addr == NULL) sprintf(s, "No address"); - else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL) + else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) sprintf(s, "Unknown family type, error #%u", errno); #ifdef HAVE_IPV6 - else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0) - strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + else if(sk->any.sa_family == AF_INET6) + { + s[0] = '['; + strcat(s, "]"); + + if (sk->ip6.sin6_port != 0) + strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + } #endif else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); + #else if (sk->any.sa_family == AF_INET) { @@ -401,7 +414,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) && (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port)); #ifdef HAVE_IPV6 else if (b->any.sa_family == AF_INET6) - return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) + return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) && (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port)); #endif else @@ -692,8 +705,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen unsigned long trueval = true; #endif mysockaddr_t straddr; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); + socklen_t len = sizeof(straddr); if (s == (SOCKET_TYPE)ERRSOCKET) return (SOCKET_TYPE)ERRSOCKET; @@ -711,14 +723,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } #endif - straddr.any = *addr; + memcpy(&straddr, addr, addrlen); I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr)); if (family == AF_INET) { - mysockaddr_t tmpaddr; - tmpaddr.any = *addr ; - if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) + if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) { opt = true; opts = (socklen_t)sizeof(opt); @@ -735,7 +745,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen #ifdef HAVE_IPV6 else if (family == AF_INET6) { - if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL + if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL { opt = true; opts = (socklen_t)sizeof(opt); @@ -745,7 +755,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen // make it IPv6 ony opt = true; opts = (socklen_t)sizeof(opt); - if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts)) + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore } @@ -787,10 +797,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); } - if (getsockname(s, (struct sockaddr *)&sin, &len) == -1) + if (getsockname(s, &straddr.any, &len) == -1) CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); else - current_port = (UINT16)ntohs(sin.sin_port); + { + if (family == AF_INET) + current_port = (UINT16)ntohs(straddr.ip4.sin_port); +#ifdef HAVE_IPV6 + else if (family == AF_INET6) + current_port = (UINT16)ntohs(straddr.ip6.sin6_port); +#endif + } return s; } @@ -801,7 +818,7 @@ static boolean UDP_Socket(void) struct my_addrinfo *ai, *runp, hints; int gaie; #ifdef HAVE_IPV6 - const INT32 b_ipv6 = M_CheckParm("-ipv6"); + const INT32 b_ipv6 = !M_CheckParm("-noipv6"); #endif const char *serv; @@ -1105,6 +1122,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) SINT8 newnode = -1; struct my_addrinfo *ai = NULL, *runp, hints; int gaie; + size_t i; if (!port || !port[0]) port = DEFAULTPORT; @@ -1132,13 +1150,24 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) while (runp != NULL) { - // find ip of the server - if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0) + // test ip address of server + for (i = 0; i < mysocketses; ++i) { - memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); - break; + /* sendto tests that there is a network to this + address */ + if (runp->ai_addr->sa_family == myfamily[i] && + sendto(mysockets[i], NULL, 0, 0, + runp->ai_addr, runp->ai_addrlen) == 0) + { + memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); + break; + } } - runp = runp->ai_next; + + if (i < mysocketses) + runp = runp->ai_next; + else + break; } I_freeaddrinfo(ai); return newnode; diff --git a/src/netcode/i_tcp.h b/src/netcode/i_tcp.h index b6e5b9235..ae9983bf1 100644 --- a/src/netcode/i_tcp.h +++ b/src/netcode/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index f603d78e5..1c7f3e08d 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -61,7 +61,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); @@ -95,8 +95,8 @@ void AddMServCommands(void) CV_RegisterVar(&cv_masterserver_token); CV_RegisterVar(&cv_servername); #ifdef MASTERSERVER - COM_AddCommand("listserv", Command_Listserv_f); - COM_AddCommand("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident + COM_AddCommand("listserv", Command_Listserv_f, 0); + COM_AddCommand("masterserver_update", Update_parameters, COM_LUA); // allows people to updates manually in case you were delisted by accident #endif } diff --git a/src/netcode/mserv.h b/src/netcode/mserv.h index 7fdf3ed1b..0bc8c8e6b 100644 --- a/src/netcode/mserv.h +++ b/src/netcode/mserv.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. -// Copyright (C) 2020-2022 by James R. +// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,7 +33,7 @@ typedef union typedef struct { msg_header_t header; - char ip[16]; + char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; char port[8]; char name[32]; INT32 room; diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c index efc8bd0ef..2b3abfd02 100644 --- a/src/netcode/net_command.c +++ b/src/netcode/net_command.c @@ -321,22 +321,18 @@ void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf) } } -void CL_CopyNetCommandsFromServerPacket(tic_t tic) +void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf) { - servertics_pak *packet = &netbuffer->u.serverpak; - UINT8 *cmds = (UINT8*)&packet->cmds[packet->numslots * packet->numtics]; - UINT8 numcmds; - - numcmds = *cmds++; + UINT8 numcmds = *(*buf)++; for (UINT32 i = 0; i < numcmds; i++) { - INT32 playernum = *cmds++; // playernum - size_t size = cmds[0]+1; + INT32 playernum = *(*buf)++; // playernum + size_t size = (*buf)[0]+1; if (tic >= gametic) // Don't copy old net commands - M_Memcpy(D_GetTextcmd(tic, playernum), cmds, size); - cmds += size; + M_Memcpy(D_GetTextcmd(tic, playernum), *buf, size); + *buf += size; } } diff --git a/src/netcode/net_command.h b/src/netcode/net_command.h index cc26aeb0e..a0c46f3a2 100644 --- a/src/netcode/net_command.h +++ b/src/netcode/net_command.h @@ -58,7 +58,7 @@ size_t TotalTextCmdPerTic(tic_t tic); void PT_TextCmd(SINT8 node, INT32 netconsole); void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf); -void CL_CopyNetCommandsFromServerPacket(tic_t tic); +void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf); void CL_SendNetCommands(void); void SendKick(UINT8 playernum, UINT8 msg); void SendKicksForNode(SINT8 node, UINT8 msg); diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index 9866e4c5a..a992e3b69 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,6 +72,8 @@ typedef enum PT_ASKLUAFILE, // Client telling the server they don't have the file PT_HASLUAFILE, // Client telling the server they have the file + PT_BASICKEEPALIVE, // Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called + // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL @@ -143,6 +145,7 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; + UINT8 usedCheats; char server_context[8]; // Unique context id, generated at server startup. } ATTRPACK serverconfig_pak; diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index f8ec3c7bd..2164f411a 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -39,10 +39,10 @@ char playeraddress[MAXPLAYERS][64]; consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_OnOff, NULL); static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, maxplayers_cons_t, NULL); static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); @@ -52,9 +52,9 @@ consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "2", CV_SAVE|CV_NETVAR| static INT32 FindRejoinerNum(SINT8 node) { - char strippednodeaddress[64]; + char addressbuffer[64]; const char *nodeaddress; - char *port; + const char *strippednodeaddress; // Make sure there is no dead dress before proceeding to the stripping if (!I_GetNodeAddress) @@ -64,10 +64,8 @@ static INT32 FindRejoinerNum(SINT8 node) return -1; // Strip the address of its port - strcpy(strippednodeaddress, nodeaddress); - port = strchr(strippednodeaddress, ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, nodeaddress); + strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL); // Check if any player matches the stripped address for (INT32 i = 0; i < MAXPLAYERS; i++) @@ -110,8 +108,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); - netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); - netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; + // Exclude bots from both counts + netbuffer->u.serverinfo.numberofplayer = (UINT8)(D_NumPlayers() - D_NumBots()); + netbuffer->u.serverinfo.maxplayer = (UINT8)(cv_maxplayers.value - D_NumBots()); netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); @@ -237,6 +236,7 @@ static boolean SV_SendServerConfig(INT32 node) netbuffer->u.servercfg.gamestate = (UINT8)gamestate; netbuffer->u.servercfg.gametype = (UINT8)gametype; netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; + netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats; memcpy(netbuffer->u.servercfg.server_context, server_context, 8); diff --git a/src/netcode/server_connection.h b/src/netcode/server_connection.h index 7481d0eb5..14ac5913c 100644 --- a/src/netcode/server_connection.h +++ b/src/netcode/server_connection.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/netcode/tic_command.c b/src/netcode/tic_command.c index 620a10f7a..7721bc3f1 100644 --- a/src/netcode/tic_command.c +++ b/src/netcode/tic_command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -100,9 +100,9 @@ void D_ResetTiccmds(void) } // Check ticcmd for "speed hacks" -static void CheckTiccmdHacks(INT32 playernum) +static void CheckTiccmdHacks(INT32 playernum, tic_t tic) { - ticcmd_t *cmd = &netcmds[maketic%BACKUPTICS][playernum]; + ticcmd_t *cmd = &netcmds[tic%BACKUPTICS][playernum]; if (cmd->forwardmove > MAXPLMOVE || cmd->forwardmove < -MAXPLMOVE || cmd->sidemove > MAXPLMOVE || cmd->sidemove < -MAXPLMOVE) { @@ -177,31 +177,43 @@ void PT_ClientCmd(SINT8 nodenum, INT32 netconsole) // Update the nettics node->tic = realend; - // Don't do anything for packets of type NODEKEEPALIVE? - if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + // This should probably still timeout though, as the node should always have a player 1 number + if (netconsole == -1) return; // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? node->freezetimeout = I_GetTime() + connectiontimeout; + // Don't do anything for packets of type NODEKEEPALIVE? + // Sryder 2018/07/01: Update the freezetimeout still! + if (netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + return; + + // If we've alredy received a ticcmd for this tic, just submit it for the next one. + tic_t faketic = maketic; + if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) + && (maketic - firstticstosend < BACKUPTICS - 1)) + faketic++; + // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) && node->player2 >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)node->player2], + G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][(UINT8)node->player2], &netbuffer->u.client2pak.cmd2, 1); - CheckTiccmdHacks(netconsole); + CheckTiccmdHacks(netconsole, faketic); CheckConsistancy(nodenum, realstart); } void PT_ServerTics(SINT8 node, INT32 netconsole) { tic_t realend, realstart; + servertics_pak *packet = &netbuffer->u.serverpak; if (!netnodes[node].ingame) { @@ -223,15 +235,16 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) return; } - realstart = netbuffer->u.serverpak.starttic; - realend = realstart + netbuffer->u.serverpak.numtics; + realstart = packet->starttic; + realend = realstart + packet->numtics; realend = min(realend, gametic + CLIENTBACKUPTICS); cl_packetmissed = realstart > neededtic; if (realstart <= neededtic && realend > neededtic) { - UINT8 *pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + UINT8 *pak = (UINT8 *)&packet->cmds; + UINT8 *txtpak = (UINT8 *)&packet->cmds[packet->numslots * packet->numtics]; for (tic_t i = realstart; i < realend; i++) { @@ -240,9 +253,9 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) // copy the tics pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + packet->numslots*sizeof (ticcmd_t)); - CL_CopyNetCommandsFromServerPacket(i); + CL_CopyNetCommandsFromServerPacket(i, &txtpak); } neededtic = realend; @@ -257,35 +270,39 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) void CL_SendClientCmd(void) { size_t packetsize = 0; + boolean mis = false; netbuffer->packettype = PT_CLIENTCMD; if (cl_packetmissed) - netbuffer->packettype++; + { + netbuffer->packettype = PT_CLIENTMIS; + mis = true; + } + netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX); netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX); if (gamestate == GS_WAITINGPLAYERS) { // Send PT_NODEKEEPALIVE packet - netbuffer->packettype += 4; + netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE); packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); } else if (gamestate != GS_NULL && (addedtogame || dedicated)) { + packetsize = sizeof (clientcmd_pak); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); // Send a special packet with 2 cmd for splitscreen if (splitscreen || botingame) { - netbuffer->packettype += 2; - G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD); packetsize = sizeof (client2cmd_pak); + G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); } - else - packetsize = sizeof (clientcmd_pak); HSendPacket(servernode, false, 0, packetsize); } @@ -346,7 +363,7 @@ void SV_SendTics(void) for (INT32 n = 1; n < MAXNETNODES; n++) if (netnodes[n].ingame) { - netnode_t *node = netnodes[n]; + netnode_t *node = &netnodes[n]; // assert node->supposedtic>=node->tic realfirsttic = node->supposedtic; @@ -408,7 +425,7 @@ void Local_Maketic(INT32 realtics) // and G_MapEventsToControls if (!dedicated) rendergametic = gametic; - // translate inputs (keyboard/mouse/gamepad) into game controls + // translate inputs (keyboard/mouse/joystick) into game controls G_BuildTiccmd(&localcmds, realtics, 1); if (splitscreen || botingame) G_BuildTiccmd(&localcmds2, realtics, 2); diff --git a/src/netcode/tic_command.h b/src/netcode/tic_command.h index 289750fb3..725037216 100644 --- a/src/netcode/tic_command.h +++ b/src/netcode/tic_command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2022 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/snake.c b/src/snake.c index 21e79401d..6482759ed 100644 --- a/src/snake.c +++ b/src/snake.c @@ -11,6 +11,8 @@ #include "snake.h" #include "g_input.h" +#include "g_game.h" +#include "i_joy.h" #include "m_random.h" #include "s_sound.h" #include "screen.h" @@ -67,6 +69,9 @@ typedef struct snake_s enum bonustype_s bonustype; UINT8 bonusx; UINT8 bonusy; + + event_t *joyevents[MAXEVENTS]; + UINT16 joyeventcount; } snake_t; static const char *bonuspatches[] = { @@ -113,6 +118,8 @@ static void Initialise(snake_t *snake) snake->appley = M_RandomKey(NUM_BLOCKS_Y); snake->bonustype = BONUS_NONE; + + snake->joyeventcount = 0; } static UINT8 GetOppositeDir(UINT8 dir) @@ -160,18 +167,19 @@ void Snake_Update(void *opaque) UINT8 oldx, oldy; UINT16 i; UINT16 joystate = 0; + static INT32 pjoyx = 0, pjoyy = 0; snake_t *snake = opaque; // Handle retry - if (snake->gameover && (G_PlayerInputDown(0, GC_JUMP) || gamekeydown[KEY_ENTER])) + if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER])) { Initialise(snake); snake->pausepressed = true; // Avoid accidental pause on respawn } // Handle pause - if (G_PlayerInputDown(0, GC_PAUSE) || gamekeydown[KEY_ENTER]) + if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER]) { if (!snake->pausepressed) snake->paused = !snake->paused; @@ -190,23 +198,58 @@ void Snake_Update(void *opaque) oldx = snake->snakex[1]; oldy = snake->snakey[1]; + // Process the input events in here dear lord + for (UINT16 j = 0; j < snake->joyeventcount; j++) + { + event_t *ev = snake->joyevents[j]; + const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT; + if (ev->y != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone) + { + if (ev->y < 0 && pjoyy >= 0) + joystate = 1; + else if (ev->y > 0 && pjoyy <= 0) + joystate = 2; + pjoyy = ev->y; + } + else + pjoyy = 0; + } + + if (ev->x != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone) + { + if (ev->x < 0 && pjoyx >= 0) + joystate = 3; + else if (ev->x > 0 && pjoyx <= 0) + joystate = 4; + pjoyx = ev->x; + } + else + pjoyx = 0; + } + } + snake->joyeventcount = 0; + // Update direction - if (G_PlayerInputDown(0, GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) + if (PLAYER1INPUTDOWN(GC_STRAFELEFT) || gamekeydown[KEY_LEFTARROW] || joystate == 3) { if (snake->snakelength < 2 || x <= oldx) snake->snakedir[0] = 1; } - else if (G_PlayerInputDown(0, GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) + else if (PLAYER1INPUTDOWN(GC_STRAFERIGHT) || gamekeydown[KEY_RIGHTARROW] || joystate == 4) { if (snake->snakelength < 2 || x >= oldx) snake->snakedir[0] = 2; } - else if (G_PlayerInputDown(0, GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) + else if (PLAYER1INPUTDOWN(GC_FORWARD) || gamekeydown[KEY_UPARROW] || joystate == 1) { if (snake->snakelength < 2 || y <= oldy) snake->snakedir[0] = 3; } - else if (G_PlayerInputDown(0, GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) + else if (PLAYER1INPUTDOWN(GC_BACKWARD) || gamekeydown[KEY_DOWNARROW] || joystate == 2) { if (snake->snakelength < 2 || y >= oldy) snake->snakedir[0] = 4; @@ -533,3 +576,18 @@ void Snake_Free(void **opaque) *opaque = NULL; } } + +// I'm screaming the hack is clean - ashi +boolean Snake_JoyGrabber(void *opaque, event_t *ev) +{ + snake_t *snake = opaque; + + if (ev->type == ev_joystick && ev->key == 0) + { + snake->joyevents[snake->joyeventcount] = ev; + snake->joyeventcount++; + return true; + } + else + return false; +} diff --git a/src/snake.h b/src/snake.h index a3106bb0f..6bca338e9 100644 --- a/src/snake.h +++ b/src/snake.h @@ -12,9 +12,12 @@ #ifndef __SNAKE__ #define __SNAKE__ +#include "d_event.h" + void Snake_Allocate(void **opaque); void Snake_Update(void *opaque); void Snake_Draw(void *opaque); void Snake_Free(void **opaque); +boolean Snake_JoyGrabber(void *opaque, event_t *ev); #endif From 3377fa986a19c91dca3488b774f60039a7638624 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 7 Aug 2023 13:30:32 -0300 Subject: [PATCH 67/93] Remember the player's color after a team gametype --- src/am_map.c | 1 - src/d_netcmd.c | 41 +---------------------------------------- src/g_game.c | 19 ------------------- src/p_enemy.c | 4 ++-- src/p_inter.c | 6 +++--- src/p_local.h | 1 + src/p_mobj.c | 11 +---------- src/p_user.c | 21 +++++++++++++++++---- src/st_stuff.c | 9 ++++++--- 9 files changed, 31 insertions(+), 82 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 331d1a5e0..df3a45cff 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1071,7 +1071,6 @@ static inline void AM_drawPlayers(void) return; } - // multiplayer (how??) for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 77a271825..a42fc1932 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1233,15 +1233,6 @@ static void SendNameAndColor(void) p = buf; - // normal player colors - if (G_GametypeHasTeams()) - { - if (players[consoleplayer].ctfteam == 1 && cv_playercolor.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor, skincolor_redteam); - else if (players[consoleplayer].ctfteam == 2 && cv_playercolor.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor, skincolor_blueteam); - } - // don't allow inaccessible colors if (!skincolors[cv_playercolor.value].accessible) { @@ -1367,16 +1358,6 @@ static void SendNameAndColor2(void) else // HACK secondplaya = 1; - // normal player colors - if (G_GametypeHasTeams()) - { - if (players[secondplaya].ctfteam == 1 && cv_playercolor2.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor2, skincolor_redteam); - else if (players[secondplaya].ctfteam == 2 && cv_playercolor2.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam); - } - - // don't allow inaccessible colors if (!skincolors[cv_playercolor2.value].accessible) { if (players[secondplaya].skincolor && skincolors[players[secondplaya].skincolor].accessible) @@ -1498,7 +1479,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) // set color p->skincolor = color % numskincolors; if (p->mo) - p->mo->color = (UINT16)p->skincolor; + p->mo->color = P_GetPlayerColor(p); // normal player colors if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer])) @@ -1507,15 +1488,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) UINT32 unlockShift = 0; UINT32 i; - // team colors - if (G_GametypeHasTeams()) - { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) - kick = true; - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) - kick = true; - } - // don't allow inaccessible colors if (skincolors[p->skincolor].accessible == false) kick = true; @@ -2904,17 +2876,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) displayplayer = consoleplayer; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam) - { - if (playernum == consoleplayer) //CTF and Team Match colors. - CV_SetValue(&cv_playercolor, NetPacket.packet.newteam + 5); - else if (playernum == secondarydisplayplayer) - CV_SetValue(&cv_playercolor2, NetPacket.packet.newteam + 5); - } - } - // In tag, check to see if you still have a game. if (G_TagGametype()) P_CheckSurvivors(); diff --git a/src/g_game.c b/src/g_game.c index 04b1ffe4d..c49b202ad 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2748,25 +2748,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent - // Check to make sure their color didn't change somehow... - if (G_GametypeHasTeams()) - { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_redteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_redteam); - } - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_blueteam); - else if (p == &players[secondarydisplayplayer]) - CV_SetValue(&cv_playercolor2, skincolor_blueteam); - } - } - if (betweenmaps) return; diff --git a/src/p_enemy.c b/src/p_enemy.c index eebb65f3c..93c828fbe 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5248,7 +5248,7 @@ void A_SignPlayer(mobj_t *actor) return; skin = &skins[actor->target->player->skin]; - facecolor = actor->target->player->skincolor; + facecolor = P_GetPlayerColor(actor->target->player); if (signcolor) ; @@ -9059,7 +9059,7 @@ void A_Dye(mobj_t *actor) if (!color) { target->colorized = false; - target->color = target->player ? target->player->skincolor : SKINCOLOR_NONE; + target->color = target->player ? P_GetPlayerColor(target->player) : SKINCOLOR_NONE; } else if (!(target->player)) { diff --git a/src/p_inter.c b/src/p_inter.c index 4d22ba343..2d132b684 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2630,7 +2630,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } - target->color = target->player->skincolor; + target->color = P_GetPlayerColor(target->player); target->colorized = false; G_GhostAddColor(GHC_NORMAL); @@ -3323,7 +3323,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) // Get rid of shield player->powers[pw_shield] = SH_NONE; - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); // Get rid of emeralds player->powers[pw_emeralds] = 0; @@ -3440,7 +3440,7 @@ void P_RemoveShield(player_t *player) { // Second layer shields if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability]))) { - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_NORMAL); } player->powers[pw_shield] = SH_NONE; diff --git a/src/p_local.h b/src/p_local.h index 563e257d8..4b330184b 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -146,6 +146,7 @@ void P_ForceLocalAngle(player_t *player, angle_t angle); boolean P_PlayerFullbright(player_t *player); boolean P_PlayerCanEnterSpinGaps(player_t *player); boolean P_PlayerShouldUseSpinHeight(player_t *player); +UINT16 P_GetPlayerColor(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); diff --git a/src/p_mobj.c b/src/p_mobj.c index 2a40175dc..ff5e5006e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11564,8 +11564,6 @@ void P_SpawnPlayer(INT32 playernum) // Spawn as a spectator, // yes even in splitscreen mode p->spectator = true; - if (playernum&1) p->skincolor = skincolor_redteam; - else p->skincolor = skincolor_blueteam; // but immediately send a team change packet. NetPacket.packet.playernum = playernum; @@ -11585,13 +11583,6 @@ void P_SpawnPlayer(INT32 playernum) // Fix stupid non spectator spectators. if (!p->spectator && !p->ctfteam) p->spectator = true; - - // Fix team colors. - // This code isn't being done right somewhere else. Oh well. - if (p->ctfteam == 1) - p->skincolor = skincolor_redteam; - else if (p->ctfteam == 2) - p->skincolor = skincolor_blueteam; } if ((netgame || multiplayer) && ((gametyperules & GTR_SPAWNINVUL) || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) @@ -11603,7 +11594,7 @@ void P_SpawnPlayer(INT32 playernum) mobj->angle = 0; // set color translations for player sprites - mobj->color = p->skincolor; + mobj->color = P_GetPlayerColor(p); // set 'spritedef' override in mobj for player skins.. (see ProjectSprite) // (usefulness: when body mobj is detached from player (who respawns), diff --git a/src/p_user.c b/src/p_user.c index cf4818298..39626b5e2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -686,7 +686,7 @@ static void P_DeNightserizePlayer(player_t *player) player->mo->skin = &skins[player->skin]; player->followitem = skins[player->skin].followitem; - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_RETURNSKIN); // Restore aiming angle @@ -3029,7 +3029,7 @@ static void P_CheckInvincibilityTimer(player_t *player) } else { - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_NORMAL); } } @@ -4302,7 +4302,7 @@ static void P_DoSuperStuff(player_t *player) } else { - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_NORMAL); } @@ -4352,7 +4352,7 @@ static void P_DoSuperStuff(player_t *player) } else { - player->mo->color = player->skincolor; + player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_NORMAL); } @@ -13113,3 +13113,16 @@ boolean P_PlayerShouldUseSpinHeight(player_t *player) && player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) || JUMPCURLED(player)); } + +UINT16 P_GetPlayerColor(player_t *player) +{ + if (G_GametypeHasTeams() && player->ctfteam) + { + if (player->ctfteam == 1) + return skincolor_redteam; + else if (player->ctfteam == 2) + return skincolor_blueteam; + } + + return player->skincolor; +} diff --git a/src/st_stuff.c b/src/st_stuff.c index c6e6befc6..1a6e944c8 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -827,6 +827,8 @@ static void ST_drawLivesArea(void) V_DrawSmallScaledPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, livesback); + UINT16 facecolor = P_GetPlayerColor(stplyr); + // face if (stplyr->spectator) { @@ -856,10 +858,10 @@ static void ST_drawLivesArea(void) } } } - else if (stplyr->skincolor) + else if (facecolor) { // skincolor face - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, facecolor, GTC_CACHE); V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap); } @@ -1030,7 +1032,8 @@ static void ST_drawLivesArea(void) static void ST_drawInput(void) { - const INT32 accent = V_SNAPTOLEFT|V_SNAPTOBOTTOM|(stplyr->skincolor ? skincolors[stplyr->skincolor].ramp[4] : 0); + UINT16 color = P_GetPlayerColor(stplyr); + const INT32 accent = V_SNAPTOLEFT|V_SNAPTOBOTTOM|(color ? skincolors[color].ramp[4] : 0); INT32 col; UINT8 offs; From 9dc244755940795b0d3fdf1df9095aaa80d77a7e Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 03:46:55 -0300 Subject: [PATCH 68/93] Ensure the correct color is set for the player object in splitscreen --- src/d_netcmd.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a42fc1932..d022514c6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1271,7 +1271,7 @@ static void SendNameAndColor(void) players[consoleplayer].skincolor = cv_playercolor.value; if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye]) - players[consoleplayer].mo->color = players[consoleplayer].skincolor; + players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]); if (metalrecording) { // Starring Metal Sonic as themselves, obviously. @@ -1280,24 +1280,10 @@ static void SendNameAndColor(void) } else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { - //boolean notsame; - cv_skin.value = foundskin; - //notsame = (cv_skin.value != players[consoleplayer].skin); - SetPlayerSkin(consoleplayer, cv_skin.string); CV_StealthSet(&cv_skin, skins[cv_skin.value].name); - - /*if (notsame) - { - CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor); - - players[consoleplayer].skincolor = cv_playercolor.value % numskincolors; - - if (players[consoleplayer].mo) - players[consoleplayer].mo->color = (UINT16)players[consoleplayer].skincolor; - }*/ } else { @@ -1399,7 +1385,7 @@ static void SendNameAndColor2(void) // don't use secondarydisplayplayer: the second player must be 1 players[secondplaya].skincolor = cv_playercolor2.value; if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye]) - players[secondplaya].mo->color = players[secondplaya].skincolor; + players[secondplaya].mo->color = P_GetPlayerColor(&players[secondplaya]); if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player { @@ -1410,24 +1396,10 @@ static void SendNameAndColor2(void) } else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin)) { - //boolean notsame; - cv_skin2.value = foundskin; - //notsame = (cv_skin2.value != players[secondplaya].skin); - SetPlayerSkin(secondplaya, cv_skin2.string); CV_StealthSet(&cv_skin2, skins[cv_skin2.value].name); - - /*if (notsame) - { - CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); - - players[secondplaya].skincolor = cv_playercolor2.value % numskincolors; - - if (players[secondplaya].mo) - players[secondplaya].mo->color = players[secondplaya].skincolor; - }*/ } else { From 0bb65166c9bda1038c1175269ceddf4e9c8a6e41 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 03:49:31 -0300 Subject: [PATCH 69/93] Always allow changing color in multiplayer player setup menu --- src/m_menu.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3451b90d6..63cb1e1c6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12523,11 +12523,7 @@ static void M_SetupMultiPlayer(INT32 choice) else MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER|IT_STRING); - // ditto with colour - if (Playing() && G_GametypeHasTeams()) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); + MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); @@ -12568,11 +12564,7 @@ static void M_SetupMultiPlayer2(INT32 choice) else MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER | IT_STRING); - // ditto with colour - if (Playing() && G_GametypeHasTeams()) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); + MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); From 062af20628fabac5c150a92b7d853aa174a36ac6 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 04:29:50 -0300 Subject: [PATCH 70/93] Don't change cv_skin or cv_playercolor if there is no need to --- src/d_main.c | 8 ++++++++ src/d_netcmd.c | 43 ++++++++++++++++--------------------------- src/g_demo.c | 9 ++++++--- src/g_game.c | 14 +++++--------- src/g_game.h | 3 +-- src/g_state.h | 4 +++- src/p_setup.c | 6 ------ src/r_skins.c | 4 ---- 8 files changed, 39 insertions(+), 52 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 22a676255..a48e94e7a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1626,6 +1626,14 @@ void D_SRB2Main(void) autostart = true; } + // Set default singleplayer skin + if (!dedicated) + { + pickedchar = R_SkinAvailable(cv_defaultskin.string); + if (pickedchar == -1) + pickedchar = 0; + } + // user settings come before "+" parameters. if (dedicated) COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d022514c6..369118dcc 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1274,25 +1274,22 @@ static void SendNameAndColor(void) players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]); if (metalrecording) - { // Starring Metal Sonic as themselves, obviously. - SetPlayerSkinByNum(consoleplayer, 5); - CV_StealthSet(&cv_skin, skins[5].name); - } - else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { - cv_skin.value = foundskin; - - SetPlayerSkin(consoleplayer, cv_skin.string); - CV_StealthSet(&cv_skin, skins[cv_skin.value].name); + // Starring Metal Sonic as themselves, obviously. + SetPlayerSkinByNum(consoleplayer, 5); + } + else if (splitscreen) + { + if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) + SetPlayerSkin(consoleplayer, cv_skin.string); + else + { + // will always be same as current + SetPlayerSkin(consoleplayer, cv_skin.string); + } } else - { - cv_skin.value = players[consoleplayer].skin; - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); - // will always be same as current - SetPlayerSkin(consoleplayer, cv_skin.string); - } - + SetPlayerSkinByNum(consoleplayer, pickedchar); return; } @@ -1365,7 +1362,6 @@ static void SendNameAndColor2(void) if (!Playing()) return; - // If you're not in a netgame, merely update the skin, color, and name. if (botingame) { players[secondplaya].skincolor = botcolor; @@ -1377,6 +1373,7 @@ static void SendNameAndColor2(void) } else if (!netgame) { + // If you're not in a netgame, merely update the skin, color, and name. INT32 foundskin; CleanupPlayerName(secondplaya, cv_playername2.zstring); @@ -1387,7 +1384,7 @@ static void SendNameAndColor2(void) if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye]) players[secondplaya].mo->color = P_GetPlayerColor(&players[secondplaya]); - if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player + if (cv_forceskin.value >= 0 && multiplayer) // Server wants everyone to use the same player { const INT32 forcedskin = cv_forceskin.value; @@ -1395,16 +1392,9 @@ static void SendNameAndColor2(void) CV_StealthSet(&cv_skin2, skins[forcedskin].name); } else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin)) - { - cv_skin2.value = foundskin; - SetPlayerSkin(secondplaya, cv_skin2.string); - CV_StealthSet(&cv_skin2, skins[cv_skin2.value].name); - } - else + else if (splitscreen) { - cv_skin2.value = players[secondplaya].skin; - CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name); // will always be same as current SetPlayerSkin(secondplaya, cv_skin2.string); } @@ -2094,7 +2084,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) { SetPlayerSkinByNum(0, cv_chooseskin.value-1); players[0].skincolor = skins[players[0].skin].prefcolor; - CV_StealthSetValue(&cv_playercolor, players[0].skincolor); } mapnumber = M_MapNumber(mapname[3], mapname[4]); diff --git a/src/g_demo.c b/src/g_demo.c index 4b9ff56e8..e3377ab13 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1500,8 +1500,12 @@ void G_BeginRecording(void) demo_p += 16; // Color - for (i = 0; i < MAXCOLORNAME && cv_playercolor.string[i]; i++) - name[i] = cv_playercolor.string[i]; + UINT16 skincolor = players[0].skincolor; + if (skincolor >= numskincolors) + skincolor = SKINCOLOR_NONE; + const char *skincolor_name = skincolors[skincolor].name; + for (i = 0; i < MAXCOLORNAME && skincolor_name[i]; i++) + name[i] = skincolor_name[i]; for (; i < MAXCOLORNAME; i++) name[i] = '\0'; M_Memcpy(demo_p,name,MAXCOLORNAME); @@ -2263,7 +2267,6 @@ void G_DoPlayDemo(char *defdemoname) players[0].skincolor = i; break; } - CV_StealthSetValue(&cv_playercolor, players[0].skincolor); if (players[0].mo) { players[0].mo->color = players[0].skincolor; diff --git a/src/g_game.c b/src/g_game.c index c49b202ad..70ff31f30 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -55,6 +55,8 @@ gameaction_t gameaction; gamestate_t gamestate = GS_NULL; UINT8 ultimatemode = false; +INT32 pickedchar; + boolean botingame; UINT8 botskin; UINT16 botcolor; @@ -4770,12 +4772,9 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) Z_Free(savebuffer); save_p = savebuffer = NULL; -// gameaction = ga_nothing; -// G_SetGamestate(GS_LEVEL); displayplayer = consoleplayer; multiplayer = splitscreen = false; -// G_DeferedInitNew(sk_medium, G_BuildMapName(1), 0, 0, 1); if (setsizeneeded) R_ExecuteSetViewSize(); @@ -4968,9 +4967,9 @@ cleanup: // Can be called by the startup code or the menu task, // consoleplayer, displayplayer, playeringame[] should be set. // -void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS) +void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS) { - UINT16 color = skins[pickedchar].prefcolor; + pickedchar = character; paused = false; if (demoplayback) @@ -4991,10 +4990,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b SplitScreen_OnChange(); } - color = skins[pickedchar].prefcolor; - SetPlayerSkinByNum(consoleplayer, pickedchar); - CV_StealthSet(&cv_skin, skins[pickedchar].name); - CV_StealthSetValue(&cv_playercolor, color); + SetPlayerSkinByNum(consoleplayer, character); if (mapname) D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pultmode, true, 1, false, FLS); diff --git a/src/g_game.h b/src/g_game.h index a8c285f79..cb38fc1d5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -174,8 +174,7 @@ void G_SpawnPlayer(INT32 playernum); // Can be called by the startup code or M_Responder. // A normal game starts at map 1, but a warp test can start elsewhere -void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, - boolean SSSG, boolean FLS); +void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS); void G_DoLoadLevel(boolean resetplayer); void G_StartTitleCard(void); void G_PreLevelTitleCard(void); diff --git a/src/g_state.h b/src/g_state.h index 8f97930bb..4b07f3d90 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -53,9 +53,11 @@ typedef enum extern gamestate_t gamestate; extern UINT8 titlemapinaction; -extern UINT8 ultimatemode; // was sk_insane +extern UINT8 ultimatemode; extern gameaction_t gameaction; +extern INT32 pickedchar; + extern boolean botingame; extern UINT8 botskin; extern UINT16 botcolor; diff --git a/src/p_setup.c b/src/p_setup.c index 0c8ea656e..747cf6d7f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7179,19 +7179,13 @@ static void P_ForceCharacter(const char *forcecharskin) { SetPlayerSkin(secondarydisplayplayer, forcecharskin); if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor) - { - CV_StealthSetValue(&cv_playercolor2, skins[players[secondarydisplayplayer].skin].prefcolor); players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor; - } } SetPlayerSkin(consoleplayer, forcecharskin); // normal player colors in single player if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin].prefcolor) - { - CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor); players[consoleplayer].skincolor = skins[players[consoleplayer].skin].prefcolor; - } } } diff --git a/src/r_skins.c b/src/r_skins.c index 9443ad49b..8bd75e35b 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -346,10 +346,6 @@ static void SetSkin(player_t *player, INT32 skinnum) if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) { - if (player == &players[consoleplayer]) - CV_StealthSetValue(&cv_playercolor, skin->prefcolor); - else if (player == &players[secondarydisplayplayer]) - CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); player->skincolor = newcolor = skin->prefcolor; if (player->bot && botingame) { From e106b56b53e289af3d85868ddec6dc5764ccc67d Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 04:45:50 -0300 Subject: [PATCH 71/93] Only set the picked character once --- src/d_netcmd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 369118dcc..bce1a28ef 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1288,8 +1288,13 @@ static void SendNameAndColor(void) SetPlayerSkin(consoleplayer, cv_skin.string); } } - else + else if (pickedchar != -1) + { SetPlayerSkinByNum(consoleplayer, pickedchar); + pickedchar = -1; + } + else + SetPlayerSkin(consoleplayer, cv_skin.string); return; } From a7459972435646a41f48ff95ab425ff125bc7308 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 12:27:38 -0300 Subject: [PATCH 72/93] Better handling of cv_skin/cv_playercolor in singleplayer --- src/d_main.c | 8 ----- src/d_netcmd.c | 80 ++++++++++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index a48e94e7a..22a676255 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1626,14 +1626,6 @@ void D_SRB2Main(void) autostart = true; } - // Set default singleplayer skin - if (!dedicated) - { - pickedchar = R_SkinAvailable(cv_defaultskin.string); - if (pickedchar == -1) - pickedchar = 0; - } - // user settings come before "+" parameters. if (dedicated) COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index bce1a28ef..9ad0b0ab0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1224,6 +1224,33 @@ static void ForceAllSkins(INT32 forcedskin) static INT32 snacpending = 0, snac2pending = 0, chmappending = 0; +static void SetSkinLocal(INT32 skinnum) +{ + if (metalrecording) + { + // Starring Metal Sonic as themselves, obviously. + SetPlayerSkinByNum(consoleplayer, 5); + } + else if (splitscreen) + { + INT32 foundskin = R_SkinAvailable(cv_skin.string); + if (foundskin != -1 && R_SkinUsable(consoleplayer, foundskin)) + SetPlayerSkinByNum(consoleplayer, foundskin); + else + SetPlayerSkinByNum(consoleplayer, GetPlayerDefaultSkin(consoleplayer)); + } + else + SetPlayerSkinByNum(consoleplayer, skinnum); +} + +static void SetColorLocal(void) +{ + players[consoleplayer].skincolor = cv_playercolor.value; + + if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye]) + players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]); +} + // name, color, or skin has changed // static void SendNameAndColor(void) @@ -1263,38 +1290,11 @@ static void SendNameAndColor(void) // If you're not in a netgame, merely update the skin, color, and name. if (!netgame) { - INT32 foundskin; - CleanupPlayerName(consoleplayer, cv_playername.zstring); strcpy(player_names[consoleplayer], cv_playername.zstring); - players[consoleplayer].skincolor = cv_playercolor.value; - - if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye]) - players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]); - - if (metalrecording) - { - // Starring Metal Sonic as themselves, obviously. - SetPlayerSkinByNum(consoleplayer, 5); - } - else if (splitscreen) - { - if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) - SetPlayerSkin(consoleplayer, cv_skin.string); - else - { - // will always be same as current - SetPlayerSkin(consoleplayer, cv_skin.string); - } - } - else if (pickedchar != -1) - { - SetPlayerSkinByNum(consoleplayer, pickedchar); - pickedchar = -1; - } - else - SetPlayerSkin(consoleplayer, cv_skin.string); + SetColorLocal(); + SetSkinLocal(pickedchar); return; } @@ -4747,10 +4747,17 @@ static void Skin_OnChange(void) if (!Playing()) return; // do whatever you want - if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. - && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y + if (!(multiplayer || netgame)) // In single player. { - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + if (!(cv_debug || devparm) + && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y + { + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + return; + } + + // Just do this here if devmode is enabled + SetSkinLocal(R_SkinAvailable(cv_skin.string)); return; } @@ -4788,15 +4795,18 @@ static void Skin2_OnChange(void) */ static void Color_OnChange(void) { - if (!Playing()) { + if (!Playing()) + { if (!cv_playercolor.value || !skincolors[cv_playercolor.value].accessible) CV_StealthSetValue(&cv_playercolor, lastgoodcolor); } else { - if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. + if (!(multiplayer || netgame)) // In single player. { - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + // Just do it here if devmode is enabled + if (cv_debug || devparm) + SetColorLocal(); return; } From 8d56a4d32ec84a9d68f6a52519c9e07da5ee266b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 12:37:18 -0300 Subject: [PATCH 73/93] Move splitscreen code path out of SetSkinLocal and into SendNameAndColor --- src/d_main.c | 3 +++ src/d_netcmd.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 22a676255..5c6db2e29 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -981,6 +981,7 @@ void D_StartTitle(void) emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); lastmaploaded = 0; + pickedchar = R_SkinAvailable(cv_defaultskin.string); // In case someone exits out at the same time they start a time attack run, // reset modeattacking @@ -1626,6 +1627,8 @@ void D_SRB2Main(void) autostart = true; } + pickedchar = R_SkinAvailable(cv_defaultskin.string); + // user settings come before "+" parameters. if (dedicated) COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home)); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9ad0b0ab0..8fdb73af4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1230,17 +1230,13 @@ static void SetSkinLocal(INT32 skinnum) { // Starring Metal Sonic as themselves, obviously. SetPlayerSkinByNum(consoleplayer, 5); + return; } - else if (splitscreen) - { - INT32 foundskin = R_SkinAvailable(cv_skin.string); - if (foundskin != -1 && R_SkinUsable(consoleplayer, foundskin)) - SetPlayerSkinByNum(consoleplayer, foundskin); - else - SetPlayerSkinByNum(consoleplayer, GetPlayerDefaultSkin(consoleplayer)); - } - else + + if (skinnum != -1 && R_SkinUsable(consoleplayer, skinnum)) SetPlayerSkinByNum(consoleplayer, skinnum); + else + SetPlayerSkinByNum(consoleplayer, GetPlayerDefaultSkin(consoleplayer)); } static void SetColorLocal(void) @@ -1294,7 +1290,11 @@ static void SendNameAndColor(void) strcpy(player_names[consoleplayer], cv_playername.zstring); SetColorLocal(); - SetSkinLocal(pickedchar); + + if (splitscreen) + SetSkinLocal(R_SkinAvailable(cv_skin.string)); + else + SetSkinLocal(pickedchar); return; } From dd4deaa5e9403d4b39b96a27aab5daca338a3fd6 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 12:43:31 -0300 Subject: [PATCH 74/93] Reduce code duplication --- src/d_netcmd.c | 61 +++++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8fdb73af4..486fa1dbe 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1224,27 +1224,27 @@ static void ForceAllSkins(INT32 forcedskin) static INT32 snacpending = 0, snac2pending = 0, chmappending = 0; -static void SetSkinLocal(INT32 skinnum) +static void SetSkinLocal(INT32 playernum, INT32 skinnum) { - if (metalrecording) + if (metalrecording && playernum == consoleplayer) { // Starring Metal Sonic as themselves, obviously. - SetPlayerSkinByNum(consoleplayer, 5); + SetPlayerSkinByNum(playernum, 5); return; } - if (skinnum != -1 && R_SkinUsable(consoleplayer, skinnum)) - SetPlayerSkinByNum(consoleplayer, skinnum); + if (skinnum != -1 && R_SkinUsable(playernum, skinnum)) + SetPlayerSkinByNum(playernum, skinnum); else - SetPlayerSkinByNum(consoleplayer, GetPlayerDefaultSkin(consoleplayer)); + SetPlayerSkinByNum(playernum, GetPlayerDefaultSkin(playernum)); } -static void SetColorLocal(void) +static void SetColorLocal(INT32 playernum, UINT16 color) { - players[consoleplayer].skincolor = cv_playercolor.value; + players[playernum].skincolor = color; - if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye]) - players[consoleplayer].mo->color = P_GetPlayerColor(&players[consoleplayer]); + if (players[playernum].mo && !players[playernum].powers[pw_dye]) + players[playernum].mo->color = P_GetPlayerColor(&players[playernum]); } // name, color, or skin has changed @@ -1289,12 +1289,12 @@ static void SendNameAndColor(void) CleanupPlayerName(consoleplayer, cv_playername.zstring); strcpy(player_names[consoleplayer], cv_playername.zstring); - SetColorLocal(); + SetColorLocal(consoleplayer, cv_playercolor.value); if (splitscreen) - SetSkinLocal(R_SkinAvailable(cv_skin.string)); + SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string)); else - SetSkinLocal(pickedchar); + SetSkinLocal(consoleplayer, pickedchar); return; } @@ -1369,40 +1369,25 @@ static void SendNameAndColor2(void) if (botingame) { - players[secondplaya].skincolor = botcolor; - if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye]) - players[secondplaya].mo->color = players[secondplaya].skincolor; - + SetColorLocal(secondplaya, botcolor); SetPlayerSkinByNum(secondplaya, botskin-1); return; } else if (!netgame) { // If you're not in a netgame, merely update the skin, color, and name. - INT32 foundskin; - CleanupPlayerName(secondplaya, cv_playername2.zstring); strcpy(player_names[secondplaya], cv_playername2.zstring); - // don't use secondarydisplayplayer: the second player must be 1 - players[secondplaya].skincolor = cv_playercolor2.value; - if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye]) - players[secondplaya].mo->color = P_GetPlayerColor(&players[secondplaya]); + SetColorLocal(secondplaya, cv_playercolor2.value); - if (cv_forceskin.value >= 0 && multiplayer) // Server wants everyone to use the same player + if (cv_forceskin.value >= 0) { - const INT32 forcedskin = cv_forceskin.value; - - SetPlayerSkinByNum(secondplaya, forcedskin); - CV_StealthSet(&cv_skin2, skins[forcedskin].name); - } - else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin)) - SetPlayerSkin(secondplaya, cv_skin2.string); - else if (splitscreen) - { - // will always be same as current - SetPlayerSkin(secondplaya, cv_skin2.string); + SetSkinLocal(secondplaya, cv_forceskin.value); + CV_StealthSet(&cv_skin2, skins[cv_forceskin.value].name); } + else + SetSkinLocal(secondplaya, R_SkinAvailable(cv_skin2.string)); return; } @@ -4756,8 +4741,8 @@ static void Skin_OnChange(void) return; } - // Just do this here if devmode is enabled - SetSkinLocal(R_SkinAvailable(cv_skin.string)); + // Just do it here if devmode is enabled + SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string)); return; } @@ -4806,7 +4791,7 @@ static void Color_OnChange(void) { // Just do it here if devmode is enabled if (cv_debug || devparm) - SetColorLocal(); + SetColorLocal(consoleplayer, cv_playercolor.value); return; } From 976b9b862dc43e264591e3c4896770a97ebb561b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 15 Aug 2023 13:51:12 -0300 Subject: [PATCH 75/93] Restore player skins if forced skin restrictions are lifted --- src/d_netcmd.c | 59 +++++++++++++++++++++----------------------------- src/g_game.c | 7 ++++++ src/p_setup.c | 36 ++++++++++++------------------ src/r_skins.c | 15 +++++++++++++ src/r_skins.h | 1 + 5 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 486fa1dbe..60013b5c5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -225,6 +225,7 @@ consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE|CV_ALLOWLUA, consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); // names +static char *lastskinnames[2]; consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange); // player colors @@ -1203,22 +1204,10 @@ UINT8 CanChangeSkin(INT32 playernum) static void ForceAllSkins(INT32 forcedskin) { - INT32 i; - for (i = 0; i < MAXPLAYERS; ++i) + for (INT32 i = 0; i < MAXPLAYERS; ++i) { - if (!playeringame[i]) - continue; - - SetPlayerSkinByNum(i, forcedskin); - - // If it's me (or my brother), set appropriate skin value in cv_skin/cv_skin2 - if (!dedicated) // But don't do this for dedicated servers, of course. - { - if (i == consoleplayer) - CV_StealthSet(&cv_skin, skins[forcedskin].name); - else if (i == secondarydisplayplayer) - CV_StealthSet(&cv_skin2, skins[forcedskin].name); - } + if (playeringame[i]) + SetPlayerSkinByNum(i, forcedskin); } } @@ -1311,10 +1300,6 @@ static void SendNameAndColor(void) else // Cleanup name if changing it CleanupPlayerName(consoleplayer, cv_playername.zstring); - // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(consoleplayer)) - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); - // check if player has the skin loaded (cv_skin may have // the name of a skin that was available in the previous game) cv_skin.value = R_SkinAvailable(cv_skin.string); @@ -1382,10 +1367,7 @@ static void SendNameAndColor2(void) SetColorLocal(secondplaya, cv_playercolor2.value); if (cv_forceskin.value >= 0) - { SetSkinLocal(secondplaya, cv_forceskin.value); - CV_StealthSet(&cv_skin2, skins[cv_forceskin.value].name); - } else SetSkinLocal(secondplaya, R_SkinAvailable(cv_skin2.string)); return; @@ -1480,16 +1462,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) } // set skin - if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player - { - const INT32 forcedskin = cv_forceskin.value; + INT32 forcedskin = R_GetForcedSkin(playernum); + if (forcedskin != -1 && (netgame || multiplayer)) // Server wants everyone to use the same player (or the level is forcing one.) SetPlayerSkinByNum(playernum, forcedskin); - - if (playernum == consoleplayer) - CV_StealthSet(&cv_skin, skins[forcedskin].name); - else if (playernum == secondarydisplayplayer) - CV_StealthSet(&cv_skin2, skins[forcedskin].name); - } else SetPlayerSkinByNum(playernum, skin); } @@ -4691,7 +4666,10 @@ static void ForceSkin_OnChange(void) return; if (cv_forceskin.value < 0) + { CONS_Printf("The server has lifted the forced skin restrictions.\n"); + D_SendPlayerConfig(); + } else { CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name); @@ -4709,7 +4687,6 @@ static void Name_OnChange(void) } else SendNameAndColor(); - } static void Name2_OnChange(void) @@ -4732,6 +4709,9 @@ static void Skin_OnChange(void) if (!Playing()) return; // do whatever you want + if (lastskinnames[0] == NULL) + lastskinnames[0] = Z_StrDup(cv_skin.string); + if (!(multiplayer || netgame)) // In single player. { if (!(cv_debug || devparm) @@ -4747,11 +4727,15 @@ static void Skin_OnChange(void) } if (CanChangeSkin(consoleplayer) && !P_PlayerMoving(consoleplayer)) + { SendNameAndColor(); + Z_Free(lastskinnames[0]); + lastskinnames[0] = Z_StrDup(cv_skin.string); + } else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, lastskinnames[0]); } } @@ -4765,12 +4749,19 @@ static void Skin2_OnChange(void) if (!Playing() || !splitscreen) return; // do whatever you want + if (lastskinnames[1] == NULL) + lastskinnames[1] = Z_StrDup(cv_skin2.string); + if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer)) + { SendNameAndColor2(); + Z_Free(lastskinnames[1]); + lastskinnames[1] = Z_StrDup(cv_skin.string); + } else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); - CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name); + CV_StealthSet(&cv_skin2, lastskinnames[1]); } } diff --git a/src/g_game.c b/src/g_game.c index 70ff31f30..eac5b29e5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5070,6 +5070,10 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean CV_StealthSetValue(&cv_itemfinder, 0); } + // Restore each player's skin if it was previously forced to be a specific one + // (Looks a bit silly, but it works.) + boolean reset_skin = netgame && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'; + // internal game map // well this check is useless because it is done before (d_netcmd.c::command_map_f) // but in case of for demos.... @@ -5097,6 +5101,9 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean automapactive = false; imcontinuing = false; + if (reset_skin) + D_SendPlayerConfig(); + // fetch saved data if available if (savedata.lives > 0) { diff --git a/src/p_setup.c b/src/p_setup.c index 747cf6d7f..d14d91fa5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7161,31 +7161,23 @@ static void P_RunLevelScript(const char *scriptname) static void P_ForceCharacter(const char *forcecharskin) { - if (netgame) - { - char skincmd[33]; - if (splitscreen) - { - sprintf(skincmd, "skin2 %s\n", forcecharskin); - CV_Set(&cv_skin2, forcecharskin); - } + // Don't do anything if the server is forcing a skin already. + if (netgame && cv_forceskin.value >= 0) + return; - sprintf(skincmd, "skin %s\n", forcecharskin); - COM_BufAddText(skincmd); - } - else + for (unsigned i = 0; i < MAXPLAYERS; i++) { - if (splitscreen) - { - SetPlayerSkin(secondarydisplayplayer, forcecharskin); - if ((unsigned)cv_playercolor2.value != skins[players[secondarydisplayplayer].skin].prefcolor) - players[secondarydisplayplayer].skincolor = skins[players[secondarydisplayplayer].skin].prefcolor; - } + if (!playeringame[i]) + continue; - SetPlayerSkin(consoleplayer, forcecharskin); - // normal player colors in single player - if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin].prefcolor) - players[consoleplayer].skincolor = skins[players[consoleplayer].skin].prefcolor; + INT32 skinnum = R_SkinAvailable(forcecharskin); + if (skinnum == -1 || !R_SkinUsable(i, skinnum)) + continue; + + SetPlayerSkinByNum(i, skinnum); + + if (!netgame) + players[i].skincolor = skins[skinnum].prefcolor; } } diff --git a/src/r_skins.c b/src/r_skins.c index 8bd75e35b..4b72d9a27 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -305,6 +305,21 @@ INT32 R_SkinAvailable(const char *name) return -1; } +INT32 R_GetForcedSkin(INT32 playernum) +{ + if (netgame && cv_forceskin.value >= 0 && R_SkinUsable(playernum, cv_forceskin.value)) + return cv_forceskin.value; + + if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0') + { + INT32 skinnum = R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter); + if (skinnum != -1 && R_SkinUsable(playernum, skinnum)) + return skinnum; + } + + return -1; +} + // Auxillary function that actually sets the skin static void SetSkin(player_t *player, INT32 skinnum) { diff --git a/src/r_skins.h b/src/r_skins.h index 082b690dd..70164ff7a 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -95,6 +95,7 @@ void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); +INT32 R_GetForcedSkin(INT32 playernum); void R_AddSkins(UINT16 wadnum, boolean mainfile); void R_PatchSkins(UINT16 wadnum, boolean mainfile); From 9b5cfe856c38846c965c535a07c8810f4fb0f3bf Mon Sep 17 00:00:00 2001 From: MIDIMan Date: Fri, 8 Sep 2023 22:03:25 -0400 Subject: [PATCH 76/93] Add a mapheader check to M_CampaignWarpIsCheat --- src/m_cond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_cond.c b/src/m_cond.c index 6c87ebf6e..706a1b510 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -509,7 +509,7 @@ UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data) return true; } - if (mapheaderinfo[mapnum-1]->menuflags & LF2_HIDEINMENU) + if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->menuflags & LF2_HIDEINMENU) { // You're never allowed to warp to this level. return true; From 06d4d71b4146209609ee40d9fa16377c7fdfd3de Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Tue, 12 Sep 2023 19:52:24 +0200 Subject: [PATCH 77/93] Fix missing includes for Linux platforms --- src/netcode/client_connection.c | 3 +++ src/netcode/gamestate.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 8155d1b33..a81ac7e97 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -32,6 +32,9 @@ #include "../z_zone.h" #include "../doomtype.h" #include "../doomstat.h" +#if defined (__GNUC__) || defined (__unix__) +#include +#endif cl_mode_t cl_mode = CL_SEARCHING; static UINT16 cl_lastcheckedfilecount = 0; // used for full file list diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index 9c243ea73..005e81ba9 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -34,6 +34,9 @@ #include "../r_main.h" #include "../tables.h" #include "../z_zone.h" +#if defined (__GNUC__) || defined (__unix__) +#include +#endif #define SAVEGAMESIZE (768*1024) From ebca345a44834cc845df21b20a8ebbd5ba487362 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Tue, 12 Sep 2023 19:32:15 -0300 Subject: [PATCH 78/93] Check if in a game --- src/d_netcmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5c93601ed..d0f6e1a75 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4709,12 +4709,14 @@ static void ForceSkin_OnChange(void) if (cv_forceskin.value < 0) { CONS_Printf("The server has lifted the forced skin restrictions.\n"); - D_SendPlayerConfig(); + if (Playing()) + D_SendPlayerConfig(); } else { CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name); - ForceAllSkins(cv_forceskin.value); + if (Playing()) + ForceAllSkins(cv_forceskin.value); } } From 65547ae036def724c6ba8c5390dba6abefe2cba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Thu, 14 Sep 2023 18:20:00 +0200 Subject: [PATCH 79/93] Fix memory leak when other players are riding a minecart --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index a443b7323..2e95a8197 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11159,7 +11159,7 @@ static void P_MinecartThink(player_t *player) detright->drawonlyforplayer = player; } else - P_RemoveMobj(detleft); + P_RemoveMobj(detright); } } else From 8f1618018e4fbd6a0ec5f3ce5c6246c3e5e0f3b4 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 15 Sep 2023 19:12:55 +0200 Subject: [PATCH 80/93] Fix free --- src/snake.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snake.c b/src/snake.c index 6482759ed..2349d5fdb 100644 --- a/src/snake.c +++ b/src/snake.c @@ -572,7 +572,7 @@ void Snake_Free(void **opaque) { if (*opaque) { - free(opaque); + free(*opaque); *opaque = NULL; } } From b53b2df7eeae7f3fe4f01418962495de6541a506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 17 Sep 2023 22:44:47 +0200 Subject: [PATCH 81/93] Fix saturation option not being applied on OpenGL --- src/v_video.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 3f958b286..25da6af40 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1336,32 +1336,33 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) // This is now a function since it's otherwise repeated 2 times and honestly looks retarded: static UINT32 V_GetHWConsBackColor(void) { - UINT32 hwcolor; + UINT8 r, g, b; switch (cons_backcolor.value) { - case 0: hwcolor = 0xffffff00; break; // White - case 1: hwcolor = 0x80808000; break; // Black - case 2: hwcolor = 0xdeb88700; break; // Sepia - case 3: hwcolor = 0x40201000; break; // Brown - case 4: hwcolor = 0xfa807200; break; // Pink - case 5: hwcolor = 0xff69b400; break; // Raspberry - case 6: hwcolor = 0xff000000; break; // Red - case 7: hwcolor = 0xffd68300; break; // Creamsicle - case 8: hwcolor = 0xff800000; break; // Orange - case 9: hwcolor = 0xdaa52000; break; // Gold - case 10: hwcolor = 0x80800000; break; // Yellow - case 11: hwcolor = 0x00ff0000; break; // Emerald - case 12: hwcolor = 0x00800000; break; // Green - case 13: hwcolor = 0x4080ff00; break; // Cyan - case 14: hwcolor = 0x4682b400; break; // Steel - case 15: hwcolor = 0x1e90ff00; break; // Periwinkle - case 16: hwcolor = 0x0000ff00; break; // Blue - case 17: hwcolor = 0xff00ff00; break; // Purple - case 18: hwcolor = 0xee82ee00; break; // Lavender + case 0: r = 0xff; g = 0xff; b = 0xff; break; // White + case 1: r = 0x80; g = 0x80; b = 0x80; break; // Black + case 2: r = 0xde; g = 0xb8; b = 0x87; break; // Sepia + case 3: r = 0x40; g = 0x20; b = 0x10; break; // Brown + case 4: r = 0xfa; g = 0x80; b = 0x72; break; // Pink + case 5: r = 0xff; g = 0x69; b = 0xb4; break; // Raspberry + case 6: r = 0xff; g = 0x00; b = 0x00; break; // Red + case 7: r = 0xff; g = 0xd6; b = 0x83; break; // Creamsicle + case 8: r = 0xff; g = 0x80; b = 0x00; break; // Orange + case 9: r = 0xda; g = 0xa5; b = 0x20; break; // Gold + case 10: r = 0x80; g = 0x80; b = 0x00; break; // Yellow + case 11: r = 0x00; g = 0xff; b = 0x00; break; // Emerald + case 12: r = 0x00; g = 0x80; b = 0x00; break; // Green + case 13: r = 0x40; g = 0x80; b = 0xff; break; // Cyan + case 14: r = 0x46; g = 0x82; b = 0xb4; break; // Steel + case 15: r = 0x1e; g = 0x90; b = 0xff; break; // Periwinkle + case 16: r = 0x00; g = 0x00; b = 0xff; break; // Blue + case 17: r = 0xff; g = 0x00; b = 0xff; break; // Purple + case 18: r = 0xee; g = 0x82; b = 0xee; break; // Lavender // Default green - default: hwcolor = 0x00800000; break; + default: r = 0x00; g = 0x80; b = 0x00; break; } - return hwcolor; + V_CubeApply(&r, &g, &b); + return (r << 24) | (g << 16) | (b << 8); } #endif From fc205082956990dcfc40381976c4724ce8902e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 18 Sep 2023 18:16:10 +0200 Subject: [PATCH 82/93] Fix saturation not being applied on colormaps in OpenGL --- src/hardware/hw_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f2022bcea..78c0b1dab 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -229,6 +229,8 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col // Clamp the light level, since it can sometimes go out of the 0-255 range from animations light_level = min(max(light_level, 0), 255); + V_CubeApply(&tint_color.s.red, &tint_color.s.green, &tint_color.s.blue); + V_CubeApply(&fade_color.s.red, &fade_color.s.green, &fade_color.s.blue); Surface->PolyColor.rgba = poly_color.rgba; Surface->TintColor.rgba = tint_color.rgba; Surface->FadeColor.rgba = fade_color.rgba; From 68e25737c05818eb14f522b326973268806a1e84 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 18 Sep 2023 18:51:11 -0300 Subject: [PATCH 83/93] Fix minor spelling mistake --- src/netcode/client_connection.c | 2 +- src/netcode/gamestate.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index a81ac7e97..907021e7d 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -572,7 +572,7 @@ static boolean CL_FinishedFileList(void) CL_Reset(); D_StartTitle(); M_StartMessage(M_GetText( - "An error occured when trying to\n" + "An error occurred when trying to\n" "download missing addons.\n" "(This is almost always a problem\n" "with the server, not your game.)\n\n" diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index 005e81ba9..f36347c6d 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -284,7 +284,7 @@ void Command_ResendGamestate(void) netbuffer->packettype = PT_WILLRESENDGAMESTATE; if (!HSendPacket(playernode[playernum], true, 0, 0)) { - CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); + CONS_Alert(CONS_ERROR, M_GetText("A problem occurred, please try again.\n")); return; } } From cfedee9dc986faee3a70e374988a84feb921fb9b Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Tue, 19 Sep 2023 16:08:06 +0200 Subject: [PATCH 84/93] Fix CMake compiling --- src/Android.mk | 7 +- src/CMakeLists.txt | 9 +- src/netcode/CMakeLists.txt | 15 +++ src/sdl/Srb2SDL-vc10.vcxproj | 44 ++++++--- src/sdl/Srb2SDL-vc10.vcxproj.filters | 138 +++++++++++++++++++-------- 5 files changed, 147 insertions(+), 66 deletions(-) create mode 100644 src/netcode/CMakeLists.txt diff --git a/src/Android.mk b/src/Android.mk index 035d48887..235c4b81e 100644 --- a/src/Android.mk +++ b/src/Android.mk @@ -8,11 +8,7 @@ LOCAL_SRC_FILES := am_map.c \ command.c \ comptime.c \ console.c \ - d_clisrv.c \ d_main.c \ - d_net.c \ - d_netcmd.c \ - d_netfil.c \ dehacked.c \ f_finale.c \ f_wipe.c \ @@ -20,7 +16,6 @@ LOCAL_SRC_FILES := am_map.c \ g_game.c \ g_input.c \ hu_stuff.c \ - i_tcp.c \ info.c \ lzf.c \ m_argv.c \ @@ -32,7 +27,6 @@ LOCAL_SRC_FILES := am_map.c \ m_queue.c \ m_random.c \ md5.c \ - mserv.c \ p_ceilng.c \ p_enemy.c \ p_fab.c \ @@ -61,6 +55,7 @@ LOCAL_SRC_FILES := am_map.c \ r_things.c \ s_sound.c \ screen.c \ + snake.c \ sounds.c \ st_stuff.c \ string.c \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b926b3b7a..22c1def27 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,10 +6,6 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 config.h.in string.c d_main.c - d_clisrv.c - d_net.c - d_netfil.c - d_netcmd.c dehacked.c deh_soc.c deh_lua.c @@ -83,12 +79,10 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 sounds.c w_wad.c filesrch.c - mserv.c - http-mserv.c - i_tcp.c lzf.c b_bot.c u_list.c + snake.c lua_script.c lua_baselib.c lua_mathlib.c @@ -149,6 +143,7 @@ set(SRB2_CONFIG_DEV_BUILD OFF CACHE BOOL "Compile a development build of SRB2.") add_subdirectory(blua) +add_subdirectory(netcode) # OS macros if (UNIX) diff --git a/src/netcode/CMakeLists.txt b/src/netcode/CMakeLists.txt new file mode 100644 index 000000000..69b976d17 --- /dev/null +++ b/src/netcode/CMakeLists.txt @@ -0,0 +1,15 @@ +target_sources(SRB2SDL2 PRIVATE + d_clisrv.c + server_connection.c + client_connection.c + tic_command.c + net_command.c + gamestate.c + commands.c + d_net.c + d_netcmd.c + d_netfil.c + http-mserv.c + i_tcp.c + mserv.c +) diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 0b95cd0b2..9b51cfb80 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -262,7 +262,6 @@ - @@ -297,6 +296,21 @@ + + + + + + + + + + + + + + + @@ -329,6 +343,7 @@ + @@ -400,11 +415,7 @@ - - - - @@ -427,10 +438,6 @@ - - true - - @@ -451,8 +458,6 @@ - - @@ -466,6 +471,22 @@ + + + + + + + + + + true + + + + + + @@ -510,6 +531,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index eb37ce9da..96501b216 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -156,24 +156,12 @@ D_Doom - - D_Doom - D_Doom D_Doom - - D_Doom - - - D_Doom - - - D_Doom - D_Doom @@ -279,9 +267,6 @@ I_Interface - - I_Interface - I_Interface @@ -306,12 +291,6 @@ I_Interface - - I_Interface - - - I_Interface - LUA @@ -372,6 +351,54 @@ M_Misc + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + I_Interface + + + I_Interface + + + I_Interface + + + I_Interface + + + I_Interface + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + O_Other @@ -465,6 +492,9 @@ R_Rend + + M_Misc + S_Sounds @@ -639,21 +669,9 @@ D_Doom - - D_Doom - D_Doom - - D_Doom - - - D_Doom - - - D_Doom - D_Doom @@ -732,18 +750,9 @@ I_Interface - - I_Interface - I_Interface - - I_Interface - - - I_Interface - LUA @@ -831,6 +840,48 @@ M_Misc + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + D_Doom + + + I_Interface + + + I_Interface + + + I_Interface + + + I_Interface + + + D_Doom + + + D_Doom + + + D_Doom + M_Misc @@ -954,6 +1005,9 @@ R_Rend + + M_Misc + S_Sounds From fb9e6c9c6d34cdb4b3750969bdae81095db327f4 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Fri, 22 Sep 2023 18:16:54 +0200 Subject: [PATCH 85/93] Use if-range instead of switch for demo versions --- src/g_demo.c | 89 +++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 67 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 4e959bcf3..cb168dfd9 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1891,16 +1891,9 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p++; // VERSION p++; // SUBVERSION oldversion = READUINT16(p); - switch(oldversion) // demoversion + if (oldversion < 0x000c || oldversion > DEMOVERSION) { - case DEMOVERSION: // latest always supported - case 0x000f: // The previous demoversions also supported - case 0x000e: - case 0x000d: // all that changed between then and now was longer color name - case 0x000c: - break; - // too old, cannot support. - default: + // too old (or new), cannot support CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); Z_Free(buffer); return UINT8_MAX; @@ -1973,14 +1966,11 @@ void G_DoPlayDemo(char *defdemoname) UINT8 i; lumpnum_t l; char skin[17],color[MAXCOLORNAME+1],*n,*pdemoname; - UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration,cnamelen; + UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration; pflags_t pflags; UINT32 randseed, followitem; fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight; char msg[1024]; -#ifdef OLD22DEMOCOMPAT - boolean use_old_demo_vars = false; -#endif skin[16] = '\0'; color[MAXCOLORNAME] = '\0'; @@ -2039,23 +2029,13 @@ void G_DoPlayDemo(char *defdemoname) subversion = READUINT8(demo_p); demoversion = READUINT16(demo_p); demo_forwardmove_rng = (demoversion < 0x0010); - switch(demoversion) - { - case 0x000f: - case 0x000d: - case 0x000e: - case DEMOVERSION: // latest always supported - cnamelen = MAXCOLORNAME; - break; #ifdef OLD22DEMOCOMPAT - // all that changed between then and now was longer color name - case 0x000c: - cnamelen = 16; - use_old_demo_vars = true; - break; + if (demoversion < 0x000c || demoversion > DEMOVERSION) +#else + if (demoversion < 0x000d || demoversion > DEMOVERSION) #endif - // too old, cannot support. - default: + { + // too old (or new), cannot support snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); @@ -2182,8 +2162,8 @@ void G_DoPlayDemo(char *defdemoname) demo_p += 16; // Color - M_Memcpy(color,demo_p,cnamelen); - demo_p += cnamelen; + M_Memcpy(color, demo_p, (demoversion < 0x000d) ? 16 : MAXCOLORNAME); + demo_p += (demoversion < 0x000d) ? 16 : MAXCOLORNAME; charability = READUINT8(demo_p); charability2 = READUINT8(demo_p); @@ -2219,7 +2199,7 @@ void G_DoPlayDemo(char *defdemoname) // net var data #ifdef OLD22DEMOCOMPAT - if (use_old_demo_vars) + if (demoversion < 0x000d) CV_LoadOldDemoVars(&demo_p); else #endif @@ -2352,19 +2332,13 @@ UINT8 G_CheckDemoForError(char *defdemoname) demo_p++; // version demo_p++; // subversion our_demo_version = READUINT16(demo_p); - switch(our_demo_version) - { - case 0x000d: - case 0x000e: - case 0x000f: - case DEMOVERSION: // latest always supported - break; #ifdef OLD22DEMOCOMPAT - case 0x000c: - break; + if (our_demo_version < 0x000c || our_demo_version > DEMOVERSION) +#else + if (our_demo_version < 0x000d || our_demo_version > DEMOVERSION) #endif - // too old, cannot support. - default: + { + // too old (or new), cannot support return DFILE_ERROR_NOTDEMO; } demo_p += 16; // demo checksum @@ -2386,7 +2360,6 @@ void G_AddGhost(char *defdemoname) INT32 i; lumpnum_t l; char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; - UINT8 cnamelen; demoghost *gh; UINT8 flags, subversion; UINT8 *buffer,*p; @@ -2438,20 +2411,9 @@ void G_AddGhost(char *defdemoname) p++; // VERSION subversion = READUINT8(p); // SUBVERSION ghostversion = READUINT16(p); - switch(ghostversion) + if (ghostversion < 0x000c || ghostversion > DEMOVERSION) { - case 0x000f: - case 0x000d: - case 0x000e: - case DEMOVERSION: // latest always supported - cnamelen = MAXCOLORNAME; - break; - // all that changed between then and now was longer color name - case 0x000c: - cnamelen = 16; - break; - // too old, cannot support. - default: + // too old (or new), cannot support CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); Z_Free(pdemoname); Z_Free(buffer); @@ -2514,8 +2476,8 @@ void G_AddGhost(char *defdemoname) p += 16; // Color - M_Memcpy(color, p,cnamelen); - p += cnamelen; + M_Memcpy(color, p, (ghostversion < 0x000d) ? 16 : MAXCOLORNAME); + p += (ghostversion < 0x000d) ? 16 : MAXCOLORNAME; // Ghosts do not have a player structure to put this in. p++; // charability @@ -2698,16 +2660,9 @@ void G_DoPlayMetal(void) metal_p++; // VERSION metal_p++; // SUBVERSION metalversion = READUINT16(metal_p); - switch(metalversion) + if (metalversion < 0x000c || metalversion > DEMOVERSION) { - case DEMOVERSION: // latest always supported - case 0x000f: - case 0x000e: // There are checks wheter the momentum is from older demo versions or not - case 0x000d: // all that changed between then and now was longer color name - case 0x000c: - break; - // too old, cannot support. - default: + // too old (or new), cannot support CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n")); Z_Free(metalbuffer); return; From 12d595399ec20b30dfcb99ff3358cd309fafc980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 1 Oct 2023 17:34:13 +0200 Subject: [PATCH 86/93] Avoid branch prediction slowdowns in R_PointOnSide --- src/r_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 54f7d7639..0655bd06f 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -249,7 +249,7 @@ static void FlipCam2_OnChange(void) // // killough 5/2/98: reformatted // -INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node) +INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *restrict node) { if (!node->dx) return x <= node->x ? node->dy > 0 : node->dy < 0; @@ -261,9 +261,10 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node) fixed_t dy = (y >> 1) - (node->y >> 1); // Try to quickly decide by looking at sign bits. - if ((node->dy ^ node->dx ^ dx ^ dy) < 0) - return (node->dy ^ dx) < 0; // (left is negative) - return FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx); + // also use a mask to avoid branch prediction + INT32 mask = (node->dy ^ node->dx ^ dx ^ dy) >> 31; + return (mask & ((node->dy ^ dx) < 0)) | // (left is negative) + (~mask & (FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx))); } // killough 5/2/98: reformatted From 33f6deb7f02e4f7f88a6e4903af24fe42473e89a Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 15 Oct 2023 23:57:00 -0400 Subject: [PATCH 87/93] Update sc/netcode/commands.c 'i' variable is set but unused in Ban_Load_File() --- src/netcode/commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netcode/commands.c b/src/netcode/commands.c index 4228027d2..4b67198ba 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -96,7 +96,7 @@ void Ban_Load_File(boolean warning) Ban_Clear(); - for (size_t i=0; fgets(buffer, (int)sizeof(buffer), f); i++) + for (; fgets(buffer, (int)sizeof(buffer), f);) { address = strtok(buffer, " \t\r\n"); mask = strtok(NULL, " \t\r\n"); From f705e53826d80b7c46a10712a55294b290de6c17 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 28 Oct 2023 11:49:26 -0400 Subject: [PATCH 88/93] GitLab CI: try compiling with dummy interface with musl --- .gitlab-ci.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b292bfc06..19391e80c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -419,6 +419,43 @@ Debian stable Clang: # make echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" +Debian stable musl: + stage: build + + allow_failure: true + + artifacts: + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-musl" + + variables: + CC: musl-gcc + LDD: musl-ldd + + script: + - - | + # apt_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apt-get install gcc + - | + # apt_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install musl-tools + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 SDL=0 NOHW=1 NOZLIB=1 NOCURL=1 NOGME=1 NOOPENMPT=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 SDL=0 NOHW=1 NOZLIB=1 NOCURL=1 NOGME=1 NOOPENMPT=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + Debian testing Clang: extends: Debian stable Clang From 86d7c9862c053acf7ab7f6b81108b568f53aa041 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sat, 28 Oct 2023 16:20:49 +0000 Subject: [PATCH 89/93] Update .gitlab-ci.yml file Now, try compiling with musl on Debian testing --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 19391e80c..3de507d61 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -469,3 +469,16 @@ Debian testing Clang: WFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype LDFLAGS: -Wl,-fuse-ld=gold + +Debian testing musl: + extends: Debian stable musl + + image: debian:testing-slim + + artifacts: + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-musl" + + variables: + CC: musl-gcc + LDD: musl-ldd + LDFLAGS: -Wl,-fuse-ld=gold From b658a9629ebd4799bb971fd4ba8c05fdee04f101 Mon Sep 17 00:00:00 2001 From: katsy Date: Sat, 28 Oct 2023 16:16:17 -0500 Subject: [PATCH 90/93] Revert "Merge branch 'master' into next" This reverts commit b26cf5248feef9bee90fd889e2c086667e5f69fd, reversing changes made to a68440c4dba18990e92c836cd01e4caa0abcde3a. --- src/Makefile.d/features.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk index 887e511fa..8b713718c 100644 --- a/src/Makefile.d/features.mk +++ b/src/Makefile.d/features.mk @@ -18,10 +18,6 @@ opts+=-DHWRENDER sources+=$(call List,hardware/Sourcefile) endif -ifdef NONET -NOCURL=1 -endif - ifndef NOMD5 sources+=md5.c endif From 18f61ab90cf5003c38dfc8bcdcaeb50a25849811 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 29 Oct 2023 05:14:48 +0000 Subject: [PATCH 91/93] Update .gitlab-ci.yml file Add ARM64=1 for arm build --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3de507d61..c61e181a5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -345,7 +345,7 @@ Debian stable:arm64: - - | # make echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" - - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 + - make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 ERRORMODE=1 NONX86=1C || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 ARM64=1 - | # make echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" From 340d515754197d2f54570760440740b25b25e12b Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Sun, 29 Oct 2023 17:43:40 +0000 Subject: [PATCH 92/93] Fix for "Leader of the Chaotix" name change bug (credit Zwip Zwap Zapony) --- src/netcode/d_netcmd.c | 2 +- src/p_saveg.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 5afa95561..52df53b5a 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1241,7 +1241,7 @@ static void SetColorLocal(INT32 playernum, UINT16 color) // static void SendNameAndColor(void) { - char buf[MAXPLAYERNAME+6]; + char buf[MAXPLAYERNAME+7]; char *p; p = buf; diff --git a/src/p_saveg.c b/src/p_saveg.c index faecd1377..4aa2318fd 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -175,7 +175,7 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].flashpal); WRITEUINT16(save_p, players[i].flashcount); - WRITEUINT8(save_p, players[i].skincolor); + WRITEUINT16(save_p, players[i].skincolor); WRITEINT32(save_p, players[i].skin); WRITEUINT32(save_p, players[i].availabilities); WRITEUINT32(save_p, players[i].score); @@ -404,7 +404,7 @@ static void P_NetUnArchivePlayers(void) players[i].flashpal = READUINT16(save_p); players[i].flashcount = READUINT16(save_p); - players[i].skincolor = READUINT8(save_p); + players[i].skincolor = READUINT16(save_p); players[i].skin = READINT32(save_p); players[i].availabilities = READUINT32(save_p); players[i].score = READUINT32(save_p); From cd6cd5395930a51ae5b62e4737480b9219a769ae Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Mon, 30 Oct 2023 04:38:51 +0000 Subject: [PATCH 93/93] Combine vid.dupx and vid.dupy --- src/console.c | 12 +- src/f_finale.c | 23 +- src/hardware/hw_draw.c | 218 ++++++++---------- src/lua_hudlib.c | 18 +- src/m_anigif.c | 2 +- src/m_menu.c | 61 +++-- src/m_misc.c | 4 +- src/r_sky.c | 4 +- src/screen.c | 10 +- src/screen.h | 12 +- src/st_stuff.c | 4 +- src/v_video.c | 507 +++++++++++++++++++---------------------- src/v_video.h | 2 +- src/y_inter.c | 6 +- 14 files changed, 408 insertions(+), 475 deletions(-) diff --git a/src/console.c b/src/console.c index 21b608ce4..dbd7c938a 100644 --- a/src/console.c +++ b/src/console.c @@ -543,13 +543,13 @@ static void CON_RecalcSize(void) con_scalefactor = 1; break; case V_SMALLSCALEPATCH: - con_scalefactor = vid.smalldupx; + con_scalefactor = vid.smalldup; break; case V_MEDSCALEPATCH: - con_scalefactor = vid.meddupx; + con_scalefactor = vid.meddup; break; default: // Full scaling - con_scalefactor = vid.dupx; + con_scalefactor = vid.dup; break; } @@ -667,7 +667,7 @@ static void CON_MoveConsole(void) } // Not instant - Increment fracmovement fractionally - fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics); + fracmovement += FixedMul(cons_speed.value*vid.fdup, renderdeltatics); if (con_curlines < con_destlines) // Move the console downwards { @@ -1764,9 +1764,9 @@ static void CON_DrawBackpic(void) con_backpic = W_CachePatchNum(piclump, PU_PATCH); // Center the backpic, and draw a vertically cropped patch. - w = (con_backpic->width * vid.dupx); + w = con_backpic->width * vid.dup; x = (vid.width / 2) - (w / 2); - h = con_curlines/vid.dupy; + h = con_curlines/vid.dup; // If the patch doesn't fill the entire screen, // then fill the sides with a solid color. diff --git a/src/f_finale.c b/src/f_finale.c index 7afed27d0..68e9c3216 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1327,7 +1327,7 @@ void F_CreditDrawer(void) y += 12< vid.height) + if (FixedMul(y,vid.dup) > vid.height) break; } } @@ -1362,7 +1362,7 @@ void F_CreditTicker(void) case 1: y += 30< vid.height) + if (FixedMul(y,vid.dup) > vid.height) break; } @@ -2082,7 +2082,7 @@ void F_EndingDrawer(void) if (goodending && finalecount >= TICRATE && finalecount < INFLECTIONPOINT) { INT32 workingtime = finalecount - TICRATE; - fixed_t radius = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); + fixed_t radius = ((vid.width/vid.dup)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); angle_t fa; INT32 eemeralds_cur[4]; char patchname[7] = "CEMGx0"; @@ -2287,7 +2287,6 @@ void F_InitMenuPresValues(void) void F_SkyScroll(const char *patchname) { INT32 x, basey = 0; - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); patch_t *pat; if (rendermode == render_none) @@ -2315,17 +2314,17 @@ void F_SkyScroll(const char *patchname) curbgy %= pat->height * 16; // Ooh, fancy frame interpolation - x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16; - basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16; + x = ((curbgx*vid.dup) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*vid.dup)) / 16; + basey = ((curbgy*vid.dup) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*vid.dup)) / 16; if (x > 0) // Make sure that we don't leave the left or top sides empty - x -= pat->width * dupz; + x -= pat->width * vid.dup; if (basey > 0) - basey -= pat->height * dupz; + basey -= pat->height * vid.dup; - for (; x < vid.width; x += pat->width * dupz) + for (; x < vid.width; x += pat->width * vid.dup) { - for (INT32 y = basey; y < vid.height; y += pat->height * dupz) + for (INT32 y = basey; y < vid.height; y += pat->height * vid.dup) V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); } @@ -2603,7 +2602,7 @@ static void F_LoadAlacroixGraphics(SINT8 newttscale) static void F_FigureActiveTtScale(void) { - SINT8 newttscale = max(1, min(6, vid.dupx)); + SINT8 newttscale = max(1, min(6, vid.dup)); SINT8 oldttscale = activettscale; if (newttscale == testttscale) @@ -4095,7 +4094,7 @@ static fixed_t F_GetPromptHideHudBound(void) F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr); // calc boxheight (see V_DrawPromptBack) - boxh *= vid.dupy; + boxh *= vid.dup; boxh = (boxh * 4) + (boxh/2)*5; // 4 lines of space plus gaps between and some leeway // return a coordinate to check diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index eb0b9e332..ec9dc7613 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -78,10 +78,8 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) // | /| // |/ | // 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; + float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; + float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; // make patch ready in hardware cache HWR_GetPatch(gpatch); @@ -90,25 +88,23 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; + pdup = 2.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + pdup = 2.0f * FIXED_TO_FLOAT(vid.fsmalldup); break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + pdup = 2.0f * FIXED_TO_FLOAT(vid.fmeddup); break; } if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + sdup = 2.0f; - v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; + v[0].x = v[3].x = (x*sdup-(gpatch->leftoffset)*pdup)/vid.width - 1; + v[2].x = v[1].x = (x*sdup+(gpatch->width-gpatch->leftoffset)*pdup)/vid.width - 1; + v[0].y = v[1].y = 1-(y*sdup-(gpatch->topoffset)*pdup)/vid.height; + v[2].y = v[3].y = 1-(y*sdup+(gpatch->height-gpatch->topoffset)*pdup)/vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; @@ -137,7 +133,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p // | /| // |/ | // 0--1 - float dupx, dupy, fscalew, fscaleh, fwidth, fheight; + float dup, fscalew, fscaleh, fwidth, fheight; UINT8 perplayershuffle = 0; @@ -149,25 +145,21 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p hwrPatch = ((GLPatch_t *)gpatch->hardware); - dupx = (float)vid.dupx; - dupy = (float)vid.dupy; + dup = (float)vid.dup; switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - dupx = dupy = 1.0f; + dup = 1.0f; break; case V_SMALLSCALEPATCH: - dupx = (float)vid.smalldupx; - dupy = (float)vid.smalldupy; + dup = (float)vid.smalldup; break; case V_MEDSCALEPATCH: - dupx = (float)vid.meddupx; - dupy = (float)vid.meddupy; + dup = (float)vid.meddup; break; } - dupx = dupy = (dupx < dupy ? dupx : dupy); fscalew = fscaleh = FIXED_TO_FLOAT(pscale); if (vscale != pscale) fscaleh = FIXED_TO_FLOAT(vscale); @@ -261,8 +253,8 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if (!(option & V_NOSCALESTART)) { - cx = cx * dupx; - cy = cy * dupy; + cx = cx * dup; + cy = cy * dup; if (!(option & V_SCALEPATCHMASK)) { @@ -279,40 +271,40 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p } } // centre screen - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f) { if (option & V_SNAPTORIGHT) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)); else if (!(option & V_SNAPTOLEFT)) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/2; if (perplayershuffle & 4) - cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4; + cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4; else if (perplayershuffle & 8) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4; + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4; } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f) { if (option & V_SNAPTOBOTTOM) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)); else if (!(option & V_SNAPTOTOP)) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/2; if (perplayershuffle & 1) - cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4; + cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4; else if (perplayershuffle & 2) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4; + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4; } } } if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) { - fwidth = (float)(gpatch->width) * fscalew * dupx; - fheight = (float)(gpatch->height) * fscaleh * dupy; + fwidth = (float)(gpatch->width) * fscalew * dup; + fheight = (float)(gpatch->height) * fscaleh * dup; } else { - fwidth = (float)(gpatch->width) * dupx; - fheight = (float)(gpatch->height) * dupy; + fwidth = (float)(gpatch->width) * dup; + fheight = (float)(gpatch->height) * dup; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 @@ -379,7 +371,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // | /| // |/ | // 0--1 - float dupx, dupy, fscalew, fscaleh, fwidth, fheight; + float dup, fscalew, fscaleh, fwidth, fheight; UINT8 perplayershuffle = 0; @@ -391,25 +383,21 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, hwrPatch = ((GLPatch_t *)gpatch->hardware); - dupx = (float)vid.dupx; - dupy = (float)vid.dupy; + dup = (float)vid.dup; switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - dupx = dupy = 1.0f; + dup = 1.0f; break; case V_SMALLSCALEPATCH: - dupx = (float)vid.smalldupx; - dupy = (float)vid.smalldupy; + dup = (float)vid.smalldup; break; case V_MEDSCALEPATCH: - dupx = (float)vid.meddupx; - dupy = (float)vid.meddupy; + dup = (float)vid.meddup; break; } - dupx = dupy = (dupx < dupy ? dupx : dupy); fscalew = fscaleh = FIXED_TO_FLOAT(pscale); if (vscale != pscale) fscaleh = FIXED_TO_FLOAT(vscale); @@ -487,8 +475,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (!(option & V_NOSCALESTART)) { - cx = cx * dupx; - cy = cy * dupy; + cx = cx * dup; + cy = cy * dup; if (!(option & V_SCALEPATCHMASK)) { @@ -496,27 +484,27 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // no the patch is cropped do not do this ever // centre screen - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f) { if (option & V_SNAPTORIGHT) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)); else if (!(option & V_SNAPTOLEFT)) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/2; if (perplayershuffle & 4) - cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4; + cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4; else if (perplayershuffle & 8) - cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4; + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4; } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f) { if (option & V_SNAPTOBOTTOM) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)); else if (!(option & V_SNAPTOTOP)) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/2; if (perplayershuffle & 1) - cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4; + cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4; else if (perplayershuffle & 2) - cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4; + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4; } } } @@ -532,13 +520,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) { - fwidth *= fscalew * dupx; - fheight *= fscaleh * dupy; + fwidth *= fscalew * dup; + fheight *= fscaleh * dup; } else { - fwidth *= dupx; - fheight *= dupy; + fwidth *= dup; + fheight *= dup; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 @@ -674,9 +662,9 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // 0--1 v[0].x = v[3].x = 2.0f * (float)x/vid.width - 1; - v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdupx))/vid.width - 1; + v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdup))/vid.width - 1; v[0].y = v[1].y = 1.0f - 2.0f * (float)y/vid.height; - v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdupy))/vid.height; + v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdup))/vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; @@ -866,35 +854,33 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac if (!(color & V_NOSCALESTART)) { - float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + fx *= vid.dup; + fy *= vid.dup; + fw *= vid.dup; + fh *= vid.dup; - fx *= dupx; - fy *= dupy; - fw *= dupx; - fh *= dupy; - - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f) { if (color & V_SNAPTORIGHT) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)); else if (!(color & V_SNAPTOLEFT)) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2; if (perplayershuffle & 4) - fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx -= ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4; else if (perplayershuffle & 8) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4; } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f) { // same thing here if (color & V_SNAPTOBOTTOM) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)); else if (!(color & V_SNAPTOTOP)) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2; if (perplayershuffle & 1) - fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4; else if (perplayershuffle & 2) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4; } } @@ -1032,10 +1018,10 @@ void HWR_DrawViewBorder(INT32 clearlines) clearlines = BASEVIDHEIGHT; // refresh all // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdupx)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdupy)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdupy)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdupx)); + baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; + baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup)); + top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup)); + side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdup)); // top HWR_DrawFlatFill(0, 0, @@ -1250,35 +1236,35 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 if (!(color & V_NOSCALESTART)) { - float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + float dup = (float)vid.dup; - fx *= dupx; - fy *= dupy; - fw *= dupx; - fh *= dupy; + fx *= dup; + fy *= dup; + fw *= dup; + fh *= dup; - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f) { if (color & V_SNAPTORIGHT) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)); else if (!(color & V_SNAPTOLEFT)) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 2; if (perplayershuffle & 4) - fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 4; else if (perplayershuffle & 8) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 4; } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f) { // same thing here if (color & V_SNAPTOBOTTOM) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)); else if (!(color & V_SNAPTOTOP)) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 2; if (perplayershuffle & 1) - fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 4; else if (perplayershuffle & 2) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 4; } } @@ -1416,8 +1402,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) if (!(color & V_NOSCALESTART)) { - float dupx = (float)vid.dupx, dupy = (float)vid.dupy; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { RGBA_t rgbaColour = V_GetColor(color); @@ -1430,33 +1414,33 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) return; } - fx *= dupx; - fy *= dupy; - fw *= dupx; - fh *= dupy; + fx *= vid.dup; + fy *= vid.dup; + fw *= vid.dup; + fh *= vid.dup; - if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f) { if (color & V_SNAPTORIGHT) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)); else if (!(color & V_SNAPTOLEFT)) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2; if (perplayershuffle & 4) - fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx -= ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4; else if (perplayershuffle & 8) - fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4; } - if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f) { // same thing here if (color & V_SNAPTOBOTTOM) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)); else if (!(color & V_SNAPTOTOP)) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2; if (perplayershuffle & 1) - fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4; else if (perplayershuffle & 2) - fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4; } } diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 6eec91273..159344faa 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1206,19 +1206,11 @@ static int libd_height(lua_State *L) return 1; } -static int libd_dupx(lua_State *L) +static int libd_dup(lua_State *L) { HUDONLY - lua_pushinteger(L, vid.dupx); // push integral scale (patch scale) - lua_pushfixed(L, vid.fdupx); // push fixed point scale (position scale) - return 2; -} - -static int libd_dupy(lua_State *L) -{ - HUDONLY - lua_pushinteger(L, vid.dupy); // push integral scale (patch scale) - lua_pushfixed(L, vid.fdupy); // push fixed point scale (position scale) + lua_pushinteger(L, vid.dup); // push integral scale (patch scale) + lua_pushfixed(L, vid.fdup); // push fixed point scale (position scale) return 2; } @@ -1338,8 +1330,8 @@ static luaL_Reg lib_draw[] = { // properties {"width", libd_width}, {"height", libd_height}, - {"dupx", libd_dupx}, - {"dupy", libd_dupy}, + {"dupx", libd_dup}, + {"dupy", libd_dup}, {"renderer", libd_renderer}, {"localTransFlag", libd_getlocaltransflag}, {"userTransFlag", libd_getusertransflag}, diff --git a/src/m_anigif.c b/src/m_anigif.c index 90e4c69ce..5bc7717e0 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -462,7 +462,7 @@ static void GIF_headwrite(void) // Image width/height if (gif_downscale) { - scrbuf_downscaleamt = vid.dupx; + scrbuf_downscaleamt = vid.dup; rwidth = (vid.width / scrbuf_downscaleamt); rheight = (vid.height / scrbuf_downscaleamt); } diff --git a/src/m_menu.c b/src/m_menu.c index 523430ed8..629f53d24 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -214,7 +214,7 @@ static fixed_t lsoffs[2]; #define lshli levelselectselect[2] #define lshseperation 101 -#define lsbasevseperation ((62*vid.height)/(BASEVIDHEIGHT*vid.dupy)) //62 +#define lsbasevseperation ((62*vid.height)/(BASEVIDHEIGHT*vid.dup)) //62 #define lsheadingheight 16 #define getheadingoffset(row) (levelselect.rows[row].header[0] ? lsheadingheight : 0) #define lsvseperation(row) (lsbasevseperation + getheadingoffset(row)) @@ -3574,16 +3574,16 @@ void M_Drawer(void) { if (customversionstring[0] != '\0') { - V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:"); - V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring); + V_DrawThinString(vid.dup, vid.height - 17*vid.dup, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:"); + V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring); } else { #ifdef DEVELOP // Development -- show revision / branch info - V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch); - V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); + V_DrawThinString(vid.dup, vid.height - 17*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch); + V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); #else // Regular build - V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING)); + V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING)); #endif } } @@ -5757,16 +5757,15 @@ static void M_DrawRecordAttackForeground(void) INT32 i; INT32 height = (fg->height / 2); - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) { INT32 y = ((i*height) - (height - ((FixedInt(recatkdrawtimer*2))%height))); // don't draw above the screen { - INT32 sy = FixedMul(y, dupz<> FRACBITS; - if (vid.height != BASEVIDHEIGHT * dupz) - sy += (vid.height - (BASEVIDHEIGHT * dupz)) / 2; + INT32 sy = FixedMul(y, vid.dup<> FRACBITS; + if (vid.height != BASEVIDHEIGHT * vid.dup) + sy += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2; if ((sy+height) < 0) continue; } @@ -5790,13 +5789,12 @@ static void M_DrawRecordAttackForeground(void) static void M_DrawNightsAttackMountains(void) { static fixed_t bgscrollx; - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); patch_t *background = W_CachePatchName(curbgname, PU_PATCH); INT16 w = background->width; INT32 x = FixedInt(-bgscrollx) % w; INT32 y = BASEVIDHEIGHT - (background->height * 2); - if (vid.height != BASEVIDHEIGHT * dupz) + if (vid.height != BASEVIDHEIGHT * vid.dup) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31); @@ -5952,7 +5950,7 @@ static void M_DrawLevelPlatterMenu(void) } // draw from top to bottom - while (y < (vid.height/vid.dupy)) + while (y < (vid.height/vid.dup)) { M_DrawLevelPlatterRow(iter, y); y += lsvseperation(iter); @@ -7799,9 +7797,9 @@ static void M_DrawSoundTest(void) } } - y = (BASEVIDWIDTH-(vid.width/vid.dupx))/2; + y = (BASEVIDWIDTH-(vid.width/vid.dup))/2; - V_DrawFill(y, 20, vid.width/vid.dupx, 24, 159); + V_DrawFill(y, 20, vid.width/vid.dup, 24, 159); { static fixed_t st_scroll = -FRACUNIT; const char* titl; @@ -8371,8 +8369,8 @@ static void M_DrawLoadGameData(void) INT32 i, prev_i = 1, savetodraw, x, y, hsep = 90; skin_t *charskin = NULL; - if (vid.width != BASEVIDWIDTH*vid.dupx) - hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx); + if (vid.width != BASEVIDWIDTH*vid.dup) + hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dup); for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0 { @@ -9357,7 +9355,7 @@ static void M_DrawSetupChoosePlayerMenu(void) INT16 bgwidth = charbg->width; INT16 fgwidth = charfg->width; INT32 x, y; - INT32 w = (vid.width/vid.dupx); + INT32 w = (vid.width/vid.dup); if (abs(char_scroll) > FRACUNIT/4) char_scroll -= FixedMul((char_scroll>>2), renderdeltatics); @@ -9393,7 +9391,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Background and borders V_DrawFill(0, 0, bgwidth, vid.height, V_SNAPTOTOP|colormap[101]); { - INT32 sw = (BASEVIDWIDTH * vid.dupx); + INT32 sw = (BASEVIDWIDTH * vid.dup); INT32 bw = (vid.width - sw) / 2; col = colormap[106]; if (bw) @@ -10815,7 +10813,7 @@ void M_DrawMarathon(void) const char *cvstring; char *work; angle_t fa; - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; + INT32 xspan = (vid.width/vid.dup), yspan = (vid.height/vid.dup), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; curbgxspeed = 0; curbgyspeed = 18; @@ -10888,16 +10886,17 @@ void M_DrawMarathon(void) INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2)); INT32 height = fg->height / 2; char patchname[7] = "CEMGx0"; + INT32 dup; - dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain. - dupz = ((dupz>>FRACBITS) % height); + dup = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain. + dup = ((dup>>FRACBITS) % height); y = height/2; - while (y+dupz >= -diffy) + while (y+dup >= -diffy) y -= height; - while (y-2-dupz < maxy) + while (y-2-dup < maxy) { - V_DrawFixedPatch(((BASEVIDWIDTH-190)<<(FRACBITS-1)), (y-2-dupz)<>FRACBITS) % height); - y = dupz+(height/4); - x = 105+dupz; + //dup = (w*height)/18; + dup = ((w>>FRACBITS) % height); + y = dup+(height/4); + x = 105+dup; while (y >= -diffy) { x -= height; y -= height; } - while (y-dupz < maxy && x < (xspan/2)) + while (y-dup < maxy && x < (xspan/2)) { V_DrawFill((BASEVIDWIDTH/2)-x-height, -diffy, height, diffy+y+height, 153); V_DrawFill((BASEVIDWIDTH/2)+x, (maxy-y)-height, height, height+y, 153); diff --git a/src/m_misc.c b/src/m_misc.c index f547f5c41..d4b272f1d 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -989,7 +989,7 @@ static inline boolean M_PNGLib(void) static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf) { - png_uint_16 downscale = apng_downscale ? vid.dupx : 1; + png_uint_16 downscale = apng_downscale ? vid.dup : 1; png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr); PNG_CONST png_uint_32 width = vid.width / downscale; @@ -1055,7 +1055,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) apng_downscale = (!!cv_apng_downscale.value); - downscale = apng_downscale ? vid.dupx : 1; + downscale = apng_downscale ? vid.dup : 1; apng_FILE = fopen(filename,"wb+"); // + mode for reading if (!apng_FILE) diff --git a/src/r_sky.c b/src/r_sky.c index c47029f0b..edde4c218 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -75,6 +75,6 @@ void R_SetupSkyDraw(void) */ void R_SetSkyScale(void) { - fixed_t difference = vid.fdupx-(vid.dupx<> V_BLENDSHIFT); fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; - INT32 dupx, dupy; + INT32 dup; const column_t *column; UINT8 *desttop, *dest, *deststart, *destend; const UINT8 *source, *deststop; @@ -555,30 +555,23 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw; } - dupx = vid.dupx; - dupy = vid.dupy; - if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT) + dup = vid.dup; + if (scrn & V_SCALEPATCHMASK) switch (scrn & V_SCALEPATCHMASK) { - case 1: // V_NOSCALEPATCH - dupx = dupy = 1; + case V_NOSCALEPATCH: + dup = 1; break; - case 2: // V_SMALLSCALEPATCH - dupx = vid.smalldupx; - dupy = vid.smalldupy; + case V_SMALLSCALEPATCH: + dup = vid.smalldup; break; - case 3: // V_MEDSCALEPATCH - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: + case V_MEDSCALEPATCH: + dup = vid.meddup; break; } - // only use one dup, to avoid stretching (har har) - dupx = dupy = (dupx < dupy ? dupx : dupy); - fdup = vdup = FixedMul(dupx<>= FRACBITS; y >>= FRACBITS; @@ -703,30 +696,30 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca } } - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen if (scrn & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * dup)); else if (!(scrn & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * dup)) / 2; if (perplayershuffle & 4) - x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x -= (vid.width - (BASEVIDWIDTH * dup)) / 4; else if (perplayershuffle & 8) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x += (vid.width - (BASEVIDWIDTH * dup)) / 4; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * dup) { // same thing here if (scrn & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); + y += (vid.height - (BASEVIDHEIGHT * dup)); else if (!(scrn & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y += (vid.height - (BASEVIDHEIGHT * dup)) / 2; if (perplayershuffle & 1) - y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y -= (vid.height - (BASEVIDHEIGHT * dup)) / 4; else if (perplayershuffle & 2) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y += (vid.height - (BASEVIDHEIGHT * dup)) / 4; } } @@ -737,11 +730,11 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { pwidth = patch->width<>= FRACBITS; } else - pwidth = patch->width * dupx; + pwidth = patch->width * dup; deststart = desttop; destend = desttop + pwidth; @@ -797,7 +790,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN // boolean flip = false; fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; - INT32 dupx, dupy; + INT32 dup; const column_t *column; UINT8 *desttop, *dest; const UINT8 *source, *deststop; @@ -845,30 +838,23 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw; } - dupx = vid.dupx; - dupy = vid.dupy; - if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT) + dup = vid.dup; + if (scrn & V_SCALEPATCHMASK) switch (scrn & V_SCALEPATCHMASK) { - case 1: // V_NOSCALEPATCH - dupx = dupy = 1; + case V_NOSCALEPATCH: + dup = 1; break; - case 2: // V_SMALLSCALEPATCH - dupx = vid.smalldupx; - dupy = vid.smalldupy; + case V_SMALLSCALEPATCH: + dup = vid.smalldup; break; - case 3: // V_MEDSCALEPATCH - dupx = vid.meddupx; - dupy = vid.meddupy; - break; - default: + case V_MEDSCALEPATCH: + dup = vid.meddup; break; } - // only use one dup, to avoid stretching (har har) - dupx = dupy = (dupx < dupy ? dupx : dupy); - fdup = vdup = FixedMul(dupx<>= FRACBITS; y >>= FRACBITS; @@ -971,30 +957,30 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN // if it's meant to cover the whole screen, black out the rest // no the patch is cropped do not do this ever - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen if (scrn & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * dup)); else if (!(scrn & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * dup)) / 2; if (perplayershuffle & 4) - x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x -= (vid.width - (BASEVIDWIDTH * dup)) / 4; else if (perplayershuffle & 8) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x += (vid.width - (BASEVIDWIDTH * dup)) / 4; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * dup) { // same thing here if (scrn & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); + y += (vid.height - (BASEVIDHEIGHT * dup)); else if (!(scrn & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y += (vid.height - (BASEVIDHEIGHT * dup)) / 2; if (perplayershuffle & 1) - y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y -= (vid.height - (BASEVIDHEIGHT * dup)) / 4; else if (perplayershuffle & 2) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y += (vid.height - (BASEVIDHEIGHT * dup)) / 4; } } @@ -1150,22 +1136,22 @@ static void V_BlitScaledPic(INT32 rx1, INT32 ry1, INT32 scrn, pic_t * pic) dest = screens[scrn] + max(0, ry1 * vid.width) + max(0, rx1); // y cliping to the screen - if (ry1 + height * vid.dupy >= vid.width) - height = (vid.width - ry1) / vid.dupy - 1; + if (ry1 + height * vid.dup >= vid.width) + height = (vid.width - ry1) / vid.dup - 1; // WARNING no x clipping (not needed for the moment) - for (y = max(0, -ry1 / vid.dupy); y < height; y++) + for (y = max(0, -ry1 / vid.dup); y < height; y++) { - for (dupy = vid.dupy; dupy; dupy--) + for (dupy = vid.dup; dupy; dupy--) { src = pic->data + y * width; for (x = 0; x < width; x++) { - for (dupx = vid.dupx; dupx; dupx--) + for (dupx = vid.dup; dupx; dupx--) *dest++ = *src; src++; } - dest += vid.width - vid.dupx * width; + dest += vid.width - vid.dup * width; } } } @@ -1262,44 +1248,42 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (!(c & V_NOSCALESTART)) { - INT32 dupx = vid.dupx, dupy = vid.dupy; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { // Clear the entire screen, from dest to deststop. Yes, this really works. memset(screens[0], (c&255), vid.width * vid.height * vid.bpp); return; } - x *= dupx; - y *= dupy; - w *= dupx; - h *= dupy; + x *= vid.dup; + y *= vid.dup; + w *= vid.dup; + h *= vid.dup; // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * vid.dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen if (c & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * vid.dup)); else if (!(c & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2; if (perplayershuffle & 4) - x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; else if (perplayershuffle & 8) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * vid.dup) { // same thing here if (c & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); + y += (vid.height - (BASEVIDHEIGHT * vid.dup)); else if (!(c & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2; if (perplayershuffle & 1) - y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; else if (perplayershuffle & 2) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; } } @@ -1474,38 +1458,36 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (!(c & V_NOSCALESTART)) { - INT32 dupx = vid.dupx, dupy = vid.dupy; - - x *= dupx; - y *= dupy; - w *= dupx; - h *= dupy; + x *= vid.dup; + y *= vid.dup; + w *= vid.dup; + h *= vid.dup; // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * vid.dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen if (c & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * vid.dup)); else if (!(c & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2; if (perplayershuffle & 4) - x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; else if (perplayershuffle & 8) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * vid.dup) { // same thing here if (c & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); + y += (vid.height - (BASEVIDHEIGHT * vid.dup)); else if (!(c & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2; if (perplayershuffle & 1) - y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; else if (perplayershuffle & 2) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; } } @@ -1658,38 +1640,36 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U if (!(c & V_NOSCALESTART)) { - INT32 dupx = vid.dupx, dupy = vid.dupy; - - x *= dupx; - y *= dupy; - w *= dupx; - h *= dupy; + x *= vid.dup; + y *= vid.dup; + w *= vid.dup; + h *= vid.dup; // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * vid.dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen if (c & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); + x += (vid.width - (BASEVIDWIDTH * vid.dup)); else if (!(c & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2; if (perplayershuffle & 4) - x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; else if (perplayershuffle & 8) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * vid.dup) { // same thing here if (c & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); + y += (vid.height - (BASEVIDHEIGHT * vid.dup)); else if (!(c & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2; if (perplayershuffle & 1) - y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; else if (perplayershuffle & 2) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4; } } @@ -1735,7 +1715,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U // void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) { - INT32 u, v, dupx, dupy; + INT32 u, v; fixed_t dx, dy, xfrac, yfrac; const UINT8 *src, *deststop; UINT8 *flat, *dest; @@ -1754,29 +1734,27 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) flat = W_CacheLumpNum(flatnum, PU_CACHE); - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - - dest = screens[0] + y*dupy*vid.width + x*dupx; + dest = screens[0] + y*vid.dup*vid.width + x*vid.dup; deststop = screens[0] + vid.rowbytes * vid.height; // from V_DrawScaledPatch - if (vid.width != BASEVIDWIDTH * dupx) + if (vid.width != BASEVIDWIDTH * vid.dup) { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // dup adjustments pretend that screen width is BASEVIDWIDTH * dup, // so center this imaginary screen - dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + dest += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2; } - if (vid.height != BASEVIDHEIGHT * dupy) + if (vid.height != BASEVIDHEIGHT * vid.dup) { // same thing here - dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; + dest += (vid.height - (BASEVIDHEIGHT * vid.dup)) * vid.width / 2; } - w *= dupx; - h *= dupy; + w *= vid.dup; + h *= vid.dup; - dx = FixedDiv(FRACUNIT, dupx<<(FRACBITS-2)); - dy = FixedDiv(FRACUNIT, dupy<<(FRACBITS-2)); + dx = FixedDiv(FRACUNIT, vid.dup<<(FRACBITS-2)); + dy = FixedDiv(FRACUNIT, vid.dup<<(FRACBITS-2)); yfrac = 0; for (v = 0; v < h; v++, dest += vid.width) @@ -1799,8 +1777,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) // void V_DrawPatchFill(patch_t *pat) { - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT32 x, y, pw = pat->width * dupz, ph = pat->height * dupz; + INT32 x, y, pw = pat->width * vid.dup, ph = pat->height * vid.dup; for (x = 0; x < vid.width; x += pw) { @@ -1876,11 +1853,11 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) boxheight = -boxheight; else // 4 lines of space plus gaps between and some leeway boxheight = ((boxheight * 4) + (boxheight/2)*5); - V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM); + V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dup))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dup),boxheight, (color-256)|V_SNAPTOBOTTOM); return; } - boxheight *= vid.dupy; + boxheight *= vid.dup; if (color == INT32_MAX) color = cons_backcolor.value; @@ -2099,7 +2076,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, cx = x, cy = y, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = (option & V_CHARCOLORMASK); const UINT8 *colormap = NULL; @@ -2110,20 +2087,19 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; switch (option & V_SPACINGMASK) { @@ -2155,9 +2131,9 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) cx = x; if (option & V_RETURN8) - cy += 8*dupy; + cy += 8*dup; else - cy += 12*dupy; + cy += 12*dup; continue; } @@ -2170,17 +2146,17 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) // character does not exist or is a space if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) { - cx += spacewidth * dupx; + cx += spacewidth * dup; continue; } if (charwidth) { - w = charwidth * dupx; - center = w/2 - hu_font[c]->width*dupx/2; + w = charwidth * dup; + center = w/2 - hu_font[c]->width*dup/2; } else - w = hu_font[c]->width * dupx; + w = hu_font[c]->width * dup; if (cx > scrwidth) continue; @@ -2215,7 +2191,7 @@ void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string // void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, cx = x, cy = y, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2226,20 +2202,19 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; charflags = (option & V_CHARCOLORMASK); @@ -2273,9 +2248,9 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) cx = x; if (option & V_RETURN8) - cy += 4*dupy; + cy += 4*dup; else - cy += 6*dupy; + cy += 6*dup; continue; } @@ -2287,17 +2262,17 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) { - cx += spacewidth * dupx; + cx += spacewidth * dup; continue; } if (charwidth) { - w = charwidth * dupx; - center = w/2 - hu_font[c]->width*dupx/4; + w = charwidth * dup; + center = w/2 - hu_font[c]->width*dup/4; } else - w = hu_font[c]->width * dupx / 2; + w = hu_font[c]->width * dup / 2; if (cx > scrwidth) continue; @@ -2333,7 +2308,7 @@ void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *s // void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + INT32 w, c, cx = x, cy = y, dup, scrwidth, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2344,20 +2319,19 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; charflags = (option & V_CHARCOLORMASK); @@ -2391,9 +2365,9 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) cx = x; if (option & V_RETURN8) - cy += 8*dupy; + cy += 8*dup; else - cy += 12*dupy; + cy += 12*dup; continue; } @@ -2405,14 +2379,14 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) { - cx += spacewidth * dupx; + cx += spacewidth * dup; continue; } if (charwidth) - w = charwidth * dupx; + w = charwidth * dup; else - w = tny_font[c]->width * dupx; + w = tny_font[c]->width * dup; if (cx > scrwidth) continue; @@ -2471,7 +2445,7 @@ void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const cha void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { fixed_t cx = x, cy = y; - INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2482,20 +2456,19 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; charflags = (option & V_CHARCOLORMASK); @@ -2529,9 +2502,9 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) cx = x; if (option & V_RETURN8) - cy += (8*dupy)<= HU_FONTSIZE || !hu_font[c]) { - cx += (spacewidth * dupx)<width*(dupx/2); + w = charwidth * dup; + center = w/2 - hu_font[c]->width*(dup/2); } else - w = hu_font[c]->width * dupx; + w = hu_font[c]->width * dup; if ((cx>>FRACBITS) > scrwidth) continue; @@ -2587,7 +2560,7 @@ void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const c void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { fixed_t cx = x, cy = y; - INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2598,20 +2571,19 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; charflags = (option & V_CHARCOLORMASK); @@ -2645,9 +2617,9 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st cx = x; if (option & V_RETURN8) - cy += (4*dupy)<= HU_FONTSIZE || !hu_font[c]) { - cx += (spacewidth * dupx)<width*(dupx/4); + w = charwidth * dup; + center = w/2 - hu_font[c]->width*(dup/4); } else - w = hu_font[c]->width * dupx / 2; + w = hu_font[c]->width * dup / 2; if ((cx>>FRACBITS) > scrwidth) break; @@ -2704,7 +2676,7 @@ void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, co void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { fixed_t cx = x, cy = y; - INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2715,20 +2687,19 @@ void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *str if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; charflags = (option & V_CHARCOLORMASK); @@ -2762,9 +2733,9 @@ void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *str cx = x; if (option & V_RETURN8) - cy += (8*dupy)<= HU_FONTSIZE || !tny_font[c]) { - cx += (spacewidth * dupx)<width*(dupx/2); + w = charwidth * dup; + center = w/2 - tny_font[c]->width*(dup/2); } else - w = tny_font[c]->width * dupx; + w = tny_font[c]->width * dup; if ((cx>>FRACBITS) > scrwidth) break; @@ -2821,7 +2792,7 @@ void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, con void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { fixed_t cx = x, cy = y; - INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; + INT32 w, c, dup, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = 0; const UINT8 *colormap = NULL; @@ -2832,20 +2803,19 @@ void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char if (option & V_NOSCALESTART) { - dupx = vid.dupx<= HU_FONTSIZE || !tny_font[c]) { - cx += FixedMul(spacewidth, dupx); + cx += FixedMul(spacewidth, dup); continue; } if (charwidth) { - w = FixedMul(charwidth, dupx); - center = w/2 - tny_font[c]->width*(dupx/4); + w = FixedMul(charwidth, dup); + center = w/2 - tny_font[c]->width*(dup/4); } else - w = tny_font[c]->width * dupx / 2; + w = tny_font[c]->width * dup / 2; if (cx > scrwidth) break; @@ -2941,7 +2911,7 @@ void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num) boolean neg; if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) - w *= vid.dupx; + w *= vid.dup; if ((neg = num < 0)) num = -num; @@ -2966,7 +2936,7 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits) INT32 w = tallnum[0]->width; if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) - w *= vid.dupx; + w *= vid.dup; if (num < 0) num = -num; @@ -3001,7 +2971,7 @@ void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num) // void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) { - INT32 w, c, dupx, dupy, scrwidth = BASEVIDWIDTH; + INT32 w, c, dup, scrwidth = BASEVIDWIDTH; fixed_t cx = x, cy = y; const char *ch = string; @@ -3011,15 +2981,14 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else - dupx = dupy = 1; + dup = 1; if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; for (;;) { @@ -3029,18 +2998,18 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) if (c == '\n') { cx = x; - cy += (12*dupy)<= CRED_FONTSIZE) { - cx += (16*dupx)<width * dupx; + w = cred_font[c]->width * dup; if ((cx>>FRACBITS) > scrwidth) continue; @@ -3054,7 +3023,7 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { fixed_t cx, cy, w; - INT32 c, dupx, dupy, scrwidth, left = 0; + INT32 c, dup, scrwidth, left = 0; const char *ch = string; if (option & V_CENTERNAMETAG) @@ -3066,20 +3035,19 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; for (;;ch++) { @@ -3088,7 +3056,7 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN if (*ch == '\n') { cx = x<= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) { - cx += FixedMul((4 * dupx)*FRACUNIT, scale); + cx += FixedMul((4 * dup)*FRACUNIT, scale); continue; } - w = FixedMul(((ntb_font[c]->width)+2 * dupx) * FRACUNIT, scale); + w = FixedMul(((ntb_font[c]->width)+2 * dup) * FRACUNIT, scale); if (FixedInt(cx) > scrwidth) continue; @@ -3277,27 +3245,26 @@ INT32 V_CreditStringWidth(const char *string) // void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + INT32 w, c, cx = x, cy = y, dup, scrwidth, left = 0; const char *ch = string; INT32 charflags = (option & V_CHARCOLORMASK); const UINT8 *colormap = NULL; if (option & V_NOSCALESTART) { - dupx = vid.dupx; - dupy = vid.dupy; + dup = vid.dup; scrwidth = vid.width; } else { - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; + dup = 1; + scrwidth = vid.width/vid.dup; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) - scrwidth *= vid.dupx; + scrwidth *= vid.dup; for (;;ch++) { @@ -3313,18 +3280,18 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) if (*ch == '\n') { cx = x; - cy += 12*dupy; + cy += 12*dup; continue; } c = *ch - LT_FONTSTART; if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) { - cx += 16*dupx; + cx += 16*dup; continue; } - w = lt_font[c]->width * dupx; + w = lt_font[c]->width * dup; if (cx > scrwidth) continue; @@ -3435,7 +3402,7 @@ INT32 V_StringWidth(const char *string, INT32 option) } if (option & (V_NOSCALESTART|V_NOSCALEPATCH)) - w *= vid.dupx; + w *= vid.dup; return w; } @@ -3682,7 +3649,7 @@ Unoptimized version { // Shift this row of pixels to the right by 2 tmpscr[y*vid.width] = srcscr[y*vid.width]; - M_Memcpy(&tmpscr[y*vid.width+vid.dupx], &srcscr[y*vid.width], vid.width-vid.dupx); + M_Memcpy(&tmpscr[y*vid.width+vid.dup], &srcscr[y*vid.width], vid.width-vid.dup); } else M_Memcpy(&tmpscr[y*vid.width], &srcscr[y*vid.width], vid.width); @@ -3783,31 +3750,23 @@ void V_Recalc(void) { // scale 1,2,3 times in x and y the patches for the menus and overlays... // calculated once and for all, used by routines in v_video.c and v_draw.c - vid.dupx = vid.width / BASEVIDWIDTH; - vid.dupy = vid.height / BASEVIDHEIGHT; - vid.dupx = vid.dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - vid.fdupx = FixedDiv(vid.width*FRACUNIT, BASEVIDWIDTH*FRACUNIT); - vid.fdupy = FixedDiv(vid.height*FRACUNIT, BASEVIDHEIGHT*FRACUNIT); -#ifdef HWRENDER - //if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl - // 13/11/18: - // The above is no longer necessary, since we want OpenGL to be just like software now - // -- Monster Iestyn -#endif - vid.fdupx = vid.fdupy = (vid.fdupx < vid.fdupy ? vid.fdupx : vid.fdupy); + // Set dup based on width or height, whichever is less + if (((vid.width*FRACUNIT) / BASEVIDWIDTH) < ((vid.height*FRACUNIT) / BASEVIDHEIGHT)) + { + vid.dup = vid.width / BASEVIDWIDTH; + vid.fdup = (vid.width*FRACUNIT) / BASEVIDWIDTH; + } + else + { + vid.dup = vid.height / BASEVIDHEIGHT; + vid.fdup = (vid.height*FRACUNIT) / BASEVIDHEIGHT; + } - vid.meddupx = (UINT8)(vid.dupx >> 1) + 1; - vid.meddupy = (UINT8)(vid.dupy >> 1) + 1; + vid.meddup = (UINT8)(vid.dup >> 1) + 1; + vid.smalldup = (UINT8)(vid.dup / 3) + 1; #ifdef HWRENDER - vid.fmeddupx = vid.meddupx*FRACUNIT; - vid.fmeddupy = vid.meddupy*FRACUNIT; -#endif - - vid.smalldupx = (UINT8)(vid.dupx / 3) + 1; - vid.smalldupy = (UINT8)(vid.dupy / 3) + 1; -#ifdef HWRENDER - vid.fsmalldupx = vid.smalldupx*FRACUNIT; - vid.fsmalldupy = vid.smalldupy*FRACUNIT; + vid.fmeddup = vid.meddup*FRACUNIT; + vid.fsmalldup = vid.smalldup*FRACUNIT; #endif } diff --git a/src/v_video.h b/src/v_video.h index ff03836b5..80936f3ee 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -36,7 +36,7 @@ cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, // Allocates buffer screens, call before R_Init. void V_Init(void); -// Recalculates the viddef (dupx, dupy, etc.) according to the current screen resolution. +// Recalculates the viddef (dup, fdup, etc.) according to the current screen resolution. void V_Recalc(void); // Color look-up table diff --git a/src/y_inter.c b/src/y_inter.c index 69dc931ba..369ec3904 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -536,7 +536,7 @@ void Y_IntermissionDrawer(void) if (animatetic && (tic_t)intertic >= animatetic) { - const INT32 scradjust = (vid.width/vid.dupx)>>3; // 40 for BASEVIDWIDTH + const INT32 scradjust = (vid.width/vid.dup)>>3; // 40 for BASEVIDWIDTH INT32 animatetimer = (intertic - animatetic); if (animatetimer <= 16) { @@ -687,7 +687,7 @@ void Y_IntermissionDrawer(void) if (intertic > 1) { - if (stagefailed && data.spec.emeraldy < (vid.height/vid.dupy)+16) + if (stagefailed && data.spec.emeraldy < (vid.height/vid.dup)+16) { emeraldx += intertic - 6; } @@ -1163,7 +1163,7 @@ void Y_Ticker(void) } else { - if (data.spec.emeraldy < (vid.height/vid.dupy)+16) + if (data.spec.emeraldy < (vid.height/vid.dup)+16) { data.spec.emeraldy += (++data.spec.emeraldmomy); }