Revert "Merge branch 'netcode-refactor' into merging"

This reverts merge request !1920
This commit is contained in:
LJ Sonic 2023-01-15 17:57:23 +00:00
parent 41fb0c8943
commit 379cc4207a
81 changed files with 6349 additions and 6278 deletions

View file

@ -64,6 +64,7 @@
# #
# Netplay incompatible # Netplay incompatible
# -------------------- # --------------------
# NONET=1 - Disable online capability.
# NOMD5=1 - Disable MD5 checksum (validation tool). # NOMD5=1 - Disable MD5 checksum (validation tool).
# NOPOSTPROCESSING=1 - ? # NOPOSTPROCESSING=1 - ?
# MOBJCONSISTANCY=1 - ?? # MOBJCONSISTANCY=1 - ??
@ -207,7 +208,6 @@ objdir:=$(makedir)/objs
sources+=\ sources+=\
$(call List,Sourcefile)\ $(call List,Sourcefile)\
$(call List,blua/Sourcefile)\ $(call List,blua/Sourcefile)\
$(call List,netcode/Sourcefile)\
depends:=$(basename $(filter %.c %.s,$(sources))) depends:=$(basename $(filter %.c %.s,$(sources)))
objects:=$(basename $(filter %.c %.s %.nas,$(sources))) objects:=$(basename $(filter %.c %.s %.nas,$(sources)))

View file

@ -3,7 +3,7 @@
# #
passthru_opts+=\ passthru_opts+=\
NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\ NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\ MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\ HAVE_MINIUPNPC\
@ -46,11 +46,13 @@ sources+=apng.c
endif endif
endif endif
ifndef NONET
ifndef NOCURL ifndef NOCURL
CURLCONFIG?=curl-config CURLCONFIG?=curl-config
$(eval $(call Configure,CURL,$(CURLCONFIG))) $(eval $(call Configure,CURL,$(CURLCONFIG)))
opts+=-DHAVE_CURL opts+=-DHAVE_CURL
endif endif
endif
ifdef HAVE_MINIUPNPC ifdef HAVE_MINIUPNPC
libs+=-lminiupnpc libs+=-lminiupnpc

View file

@ -35,10 +35,12 @@ libs+=-lws2_32
endif endif
endif endif
ifndef NONET
ifndef MINGW64 # miniupnc is broken with MINGW64 ifndef MINGW64 # miniupnc is broken with MINGW64
opts+=-I../libs -DSTATIC_MINIUPNPC opts+=-I../libs -DSTATIC_MINIUPNPC
libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi
endif endif
endif
ifndef MINGW64 ifndef MINGW64
32=32 32=32

View file

@ -1,5 +1,9 @@
string.c string.c
d_main.c d_main.c
d_clisrv.c
d_net.c
d_netfil.c
d_netcmd.c
dehacked.c dehacked.c
deh_soc.c deh_soc.c
deh_lua.c deh_lua.c
@ -73,10 +77,12 @@ s_sound.c
sounds.c sounds.c
w_wad.c w_wad.c
filesrch.c filesrch.c
mserv.c
http-mserv.c
i_tcp.c
lzf.c lzf.c
vid_copy.s vid_copy.s
b_bot.c b_bot.c
snake.c
lua_script.c lua_script.c
lua_baselib.c lua_baselib.c
lua_mathlib.c lua_mathlib.c

View file

@ -1,4 +1,4 @@
#include "../netcode/i_net.h" #include "../i_net.h"
boolean I_InitNetwork(void) boolean I_InitNetwork(void)
{ {

View file

@ -19,8 +19,7 @@
#include "lualib.h" #include "lualib.h"
#include "../i_system.h" #include "../i_system.h"
#include "../g_game.h" #include "../g_game.h"
#include "../netcode/d_netfil.h" #include "../d_netfil.h"
#include "../netcode/net_command.h"
#include "../lua_libs.h" #include "../lua_libs.h"
#include "../byteptr.h" #include "../byteptr.h"
#include "../lua_script.h" #include "../lua_script.h"

View file

@ -28,12 +28,11 @@
#include "byteptr.h" #include "byteptr.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "g_game.h" // for player_names #include "g_game.h" // for player_names
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "netcode/net_command.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "p_setup.h" #include "p_setup.h"
#include "lua_script.h" #include "lua_script.h"
#include "netcode/d_netfil.h" // findfile #include "d_netfil.h" // findfile
#include "r_data.h" // Color_cons_t #include "r_data.h" // Color_cons_t
//======== //========

5590
src/d_clisrv.c Executable file

File diff suppressed because it is too large Load diff

View file

@ -7,15 +7,19 @@
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details. // See the 'LICENSE' file for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file protocol.h /// \file d_clisrv.h
/// \brief Data exchanged through the network /// \brief high level networking stuff
#ifndef __PROTOCOL__ #ifndef __D_CLISRV__
#define __PROTOCOL__ #define __D_CLISRV__
#include "d_ticcmd.h"
#include "d_net.h" #include "d_net.h"
#include "../d_ticcmd.h" #include "d_netcmd.h"
#include "../doomdef.h" #include "d_net.h"
#include "tables.h"
#include "d_player.h"
#include "mserv.h"
/* /*
The 'packet version' is used to distinguish packet The 'packet version' is used to distinguish packet
@ -34,9 +38,10 @@ therein, increment this number.
// one that defines the actual packets to // one that defines the actual packets to
// be transmitted. // be transmitted.
// Networking and tick handling related.
#define BACKUPTICS 1024 #define BACKUPTICS 1024
#define CLIENTBACKUPTICS 32
#define MAXTEXTCMD 256 #define MAXTEXTCMD 256
// //
// Packet structure // Packet structure
// //
@ -85,6 +90,7 @@ typedef enum
PT_TEXTCMD, // Extra text commands from the client. PT_TEXTCMD, // Extra text commands from the client.
PT_TEXTCMD2, // Splitscreen text commands. PT_TEXTCMD2, // Splitscreen text commands.
PT_CLIENTJOIN, // Client wants to join; used in start game. 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_LOGIN, // Login attempt from the client.
@ -95,6 +101,14 @@ typedef enum
NUMPACKETTYPE NUMPACKETTYPE
} packettype_t; } packettype_t;
#ifdef PACKETDROP
void Command_Drop(void);
void Command_Droprate(void);
#endif
#ifdef _DEBUG
void Command_Numnodes(void);
#endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif #endif
@ -123,12 +137,13 @@ typedef struct
#endif #endif
// Server to client packet // Server to client packet
// this packet is too large
typedef struct typedef struct
{ {
tic_t starttic; tic_t starttic;
UINT8 numtics; UINT8 numtics;
UINT8 numslots; // "Slots filled": Highest player number in use plus one. UINT8 numslots; // "Slots filled": Highest player number in use plus one.
ticcmd_t cmds[45]; ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
} ATTRPACK servertics_pak; } ATTRPACK servertics_pak;
typedef struct typedef struct
@ -197,7 +212,6 @@ enum {
#define MAXSERVERNAME 32 #define MAXSERVERNAME 32
#define MAXFILENEEDED 915 #define MAXFILENEEDED 915
// This packet is too large // This packet is too large
typedef struct typedef struct
{ {
@ -258,7 +272,7 @@ typedef struct
UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused. UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused.
UINT32 score; UINT32 score;
UINT16 timeinserver; // In seconds. UINT16 timeinserver; // In seconds.
} ATTRPACK plrinfo_pak; } ATTRPACK plrinfo;
// Shortest player information for join during intermission. // Shortest player information for join during intermission.
typedef struct typedef struct
@ -269,7 +283,7 @@ typedef struct
UINT32 pflags; UINT32 pflags;
UINT32 score; UINT32 score;
UINT8 ctfteam; UINT8 ctfteam;
} ATTRPACK plrconfig_pak; } ATTRPACK plrconfig;
typedef struct typedef struct
{ {
@ -292,25 +306,25 @@ typedef struct
UINT8 reserved; // Padding UINT8 reserved; // Padding
union union
{ {
clientcmd_pak clientpak; clientcmd_pak clientpak; // 144 bytes
client2cmd_pak client2pak; client2cmd_pak client2pak; // 200 bytes
servertics_pak serverpak; servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; serverconfig_pak servercfg; // 773 bytes
UINT8 textcmd[MAXTEXTCMD+1]; UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; filetx_pak filetxpak; // 139 bytes
fileack_pak fileack; fileack_pak fileack;
UINT8 filereceived; UINT8 filereceived;
clientconfig_pak clientcfg; clientconfig_pak clientcfg; // 136 bytes
UINT8 md5sum[16]; UINT8 md5sum[16];
serverinfo_pak serverinfo; serverinfo_pak serverinfo; // 1024 bytes
serverrefuse_pak serverrefuse; serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; msaskinfo_pak msaskinfo; // 22 bytes
plrinfo_pak playerinfo[MAXPLAYERS]; plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrconfig_pak playerconfig[MAXPLAYERS]; plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
INT32 filesneedednum; INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; filesneededconfig_pak filesneededcfg; // ??? bytes
UINT32 pingtable[MAXPLAYERS+1]; UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
} u; // This is needed to pack diff packet types data together } u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t; } ATTRPACK doomdata_t;
@ -318,7 +332,26 @@ typedef struct
#pragma pack() #pragma pack()
#endif #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
extern doomdata_t *netbuffer;
extern consvar_t cv_showjoinaddress;
extern consvar_t cv_playbackspeed;
#define BASEPACKETSIZE offsetof(doomdata_t, u)
#define FILETXHEADER offsetof(filetx_pak, data) #define FILETXHEADER offsetof(filetx_pak, data)
#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
#define KICK_MSG_GO_AWAY 1 #define KICK_MSG_GO_AWAY 1
#define KICK_MSG_CON_FAIL 2 #define KICK_MSG_CON_FAIL 2
@ -330,4 +363,102 @@ typedef struct
#define KICK_MSG_CUSTOM_BAN 8 #define KICK_MSG_CUSTOM_BAN 8
#define KICK_MSG_KEEP_BODY 0x80 #define KICK_MSG_KEEP_BODY 0x80
typedef enum
{
KR_KICK = 1, //Kicked by server
KR_PINGLIMIT = 2, //Broke Ping Limit
KR_SYNCH = 3, //Synch Failure
KR_TIMEOUT = 4, //Connection Timeout
KR_BAN = 5, //Banned by server
KR_LEAVE = 6, //Quit the game
} kickreason_t;
/* the max number of name changes in some time period */
#define MAXNAMECHANGES (5)
#define NAMECHANGERATE (60*TICRATE)
extern boolean server;
extern boolean serverrunning;
#define client (!server)
extern boolean dedicated; // For dedicated server
extern UINT16 software_MAXPACKETLENGTH;
extern boolean acceptnewnode;
extern SINT8 servernode;
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
extern UINT16 pingmeasurecount;
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_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 SV_StartSinglePlayerServer(void);
boolean SV_SpawnServer(void);
void SV_StopServer(void);
void SV_ResetServer(void);
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);
// Is there a game running
boolean Playing(void);
// Broadcasts special packets to other players
// to notify of game exit
void D_QuitNetGame(void);
//? How many ticks to run?
boolean TryRunTics(tic_t realtic);
// extra data for lmps
// these functions scare me. they contain magic.
/*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];
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);
extern UINT8 hu_redownloadinggamestate;
extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset;
extern boolean hu_stopped;
#endif #endif

View file

@ -34,7 +34,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "am_map.h" #include "am_map.h"
#include "console.h" #include "console.h"
#include "netcode/d_net.h" #include "d_net.h"
#include "f_finale.h" #include "f_finale.h"
#include "g_game.h" #include "g_game.h"
#include "hu_stuff.h" #include "hu_stuff.h"
@ -57,11 +57,11 @@
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
#include "d_main.h" #include "d_main.h"
#include "netcode/d_netfil.h" #include "d_netfil.h"
#include "m_cheat.h" #include "m_cheat.h"
#include "y_inter.h" #include "y_inter.h"
#include "p_local.h" // chasecam #include "p_local.h" // chasecam
#include "netcode/mserv.h" // ms_RoomId #include "mserv.h" // ms_RoomId
#include "m_misc.h" // screenshot functionality #include "m_misc.h" // screenshot functionality
#include "deh_tables.h" // Dehacked list test #include "deh_tables.h" // Dehacked list test
#include "m_cond.h" // condition initialization #include "m_cond.h" // condition initialization

View file

@ -16,21 +16,19 @@
/// This protocol uses a mix of "goback n" and "selective repeat" implementation /// This protocol uses a mix of "goback n" and "selective repeat" implementation
/// The NOTHING packet is sent when connection is idle to acknowledge packets /// The NOTHING packet is sent when connection is idle to acknowledge packets
#include "../doomdef.h" #include "doomdef.h"
#include "../g_game.h" #include "g_game.h"
#include "../i_time.h" #include "i_time.h"
#include "i_net.h" #include "i_net.h"
#include "../i_system.h" #include "i_system.h"
#include "../m_argv.h" #include "m_argv.h"
#include "d_net.h" #include "d_net.h"
#include "../w_wad.h" #include "w_wad.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "tic_command.h" #include "z_zone.h"
#include "net_command.h"
#include "../z_zone.h"
#include "i_tcp.h" #include "i_tcp.h"
#include "../d_main.h" // srb2home #include "d_main.h" // srb2home
// //
// NETWORKING // NETWORKING
@ -140,6 +138,7 @@ boolean Net_GetNetStat(void)
#define URGENTFREESLOTNUM 10 #define URGENTFREESLOTNUM 10
#define ACKTOSENDTIMEOUT (TICRATE/11) #define ACKTOSENDTIMEOUT (TICRATE/11)
#ifndef NONET
typedef struct typedef struct
{ {
UINT8 acknum; UINT8 acknum;
@ -153,6 +152,7 @@ typedef struct
doomdata_t data; doomdata_t data;
} pak; } pak;
} ackpak_t; } ackpak_t;
#endif
typedef enum typedef enum
{ {
@ -160,8 +160,10 @@ typedef enum
NF_TIMEOUT = 2, // Flag is set when the node got a timeout NF_TIMEOUT = 2, // Flag is set when the node got a timeout
} node_flags_t; } node_flags_t;
#ifndef NONET
// Table of packets that were not acknowleged can be resent (the sender window) // Table of packets that were not acknowleged can be resent (the sender window)
static ackpak_t ackpak[MAXACKPACKETS]; static ackpak_t ackpak[MAXACKPACKETS];
#endif
typedef struct typedef struct
{ {
@ -189,6 +191,7 @@ typedef struct
static node_t nodes[MAXNETNODES]; static node_t nodes[MAXNETNODES];
#define NODETIMEOUT 14 #define NODETIMEOUT 14
#ifndef NONET
// return <0 if a < b (mod 256) // return <0 if a < b (mod 256)
// 0 if a = n (mod 256) // 0 if a = n (mod 256)
// >0 if a > b (mod 256) // >0 if a > b (mod 256)
@ -211,7 +214,7 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
{ {
node_t *node = &nodes[doomcom->remotenode]; node_t *node = &nodes[doomcom->remotenode];
INT32 numfreeslot = 0; INT32 i, numfreeslot = 0;
if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0) if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
{ {
@ -219,7 +222,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
return false; return false;
} }
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
if (!ackpak[i].acknum) if (!ackpak[i].acknum)
{ {
// For low priority packets, make sure to let freeslots so urgent packets can be sent // For low priority packets, make sure to let freeslots so urgent packets can be sent
@ -276,10 +279,10 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
*/ */
INT32 Net_GetFreeAcks(boolean urgent) INT32 Net_GetFreeAcks(boolean urgent)
{ {
INT32 numfreeslot = 0; INT32 i, numfreeslot = 0;
INT32 n = 0; // Number of free acks found INT32 n = 0; // Number of free acks found
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
if (!ackpak[i].acknum) if (!ackpak[i].acknum)
{ {
// For low priority packets, make sure to let freeslots so urgent packets can be sent // For low priority packets, make sure to let freeslots so urgent packets can be sent
@ -315,6 +318,7 @@ static void RemoveAck(INT32 i)
// We have got a packet, proceed the ack request and ack return // We have got a packet, proceed the ack request and ack return
static boolean Processackpak(void) static boolean Processackpak(void)
{ {
INT32 i;
boolean goodpacket = true; boolean goodpacket = true;
node_t *node = &nodes[doomcom->remotenode]; node_t *node = &nodes[doomcom->remotenode];
@ -323,7 +327,7 @@ static boolean Processackpak(void)
{ {
node->remotefirstack = netbuffer->ackreturn; node->remotefirstack = netbuffer->ackreturn;
// Search the ackbuffer and free it // Search the ackbuffer and free it
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0) && cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
{ {
@ -345,7 +349,7 @@ static boolean Processackpak(void)
else else
{ {
// Check if it is not already in the queue // Check if it is not already in the queue
for (INT32 i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND) for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
if (node->acktosend[i] == ack) if (node->acktosend[i] == ack)
{ {
DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack)); DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
@ -373,7 +377,7 @@ static boolean Processackpak(void)
while (change) while (change)
{ {
change = false; change = false;
for (INT32 i = node->acktosend_tail; i != node->acktosend_head; for (i = node->acktosend_tail; i != node->acktosend_head;
i = (i+1) % MAXACKTOSEND) i = (i+1) % MAXACKTOSEND)
{ {
if (cmpack(node->acktosend[i], nextfirstack) <= 0) if (cmpack(node->acktosend[i], nextfirstack) <= 0)
@ -422,20 +426,28 @@ static boolean Processackpak(void)
} }
return goodpacket; return goodpacket;
} }
#endif
// send special packet with only ack on it // send special packet with only ack on it
void Net_SendAcks(INT32 node) void Net_SendAcks(INT32 node)
{ {
#ifdef NONET
(void)node;
#else
netbuffer->packettype = PT_NOTHING; netbuffer->packettype = PT_NOTHING;
M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND); M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND);
HSendPacket(node, false, 0, MAXACKTOSEND); HSendPacket(node, false, 0, MAXACKTOSEND);
#endif
} }
#ifndef NONET
static void GotAcks(void) static void GotAcks(void)
{ {
for (INT32 j = 0; j < MAXACKTOSEND; j++) INT32 i, j;
for (j = 0; j < MAXACKTOSEND; j++)
if (netbuffer->u.textcmd[j]) if (netbuffer->u.textcmd[j])
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode) if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
{ {
if (ackpak[i].acknum == netbuffer->u.textcmd[j]) if (ackpak[i].acknum == netbuffer->u.textcmd[j])
@ -451,6 +463,7 @@ static void GotAcks(void)
} }
} }
} }
#endif
void Net_ConnectionTimeout(INT32 node) void Net_ConnectionTimeout(INT32 node)
{ {
@ -459,10 +472,14 @@ void Net_ConnectionTimeout(INT32 node)
return; return;
nodes[node].flags |= NF_TIMEOUT; nodes[node].flags |= NF_TIMEOUT;
if (server) // Send a very special packet to self (hack the reboundstore queue)
SendKicksForNode(node, KICK_MSG_TIMEOUT | KICK_MSG_KEEP_BODY); // Main code will handle it
else reboundstore[rebound_head].packettype = PT_NODETIMEOUT;
CL_HandleTimeout(); 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;
// Do not redo it quickly (if we do not close connection it is // Do not redo it quickly (if we do not close connection it is
// for a good reason!) // for a good reason!)
@ -472,8 +489,10 @@ void Net_ConnectionTimeout(INT32 node)
// Resend the data if needed // Resend the data if needed
void Net_AckTicker(void) void Net_AckTicker(void)
{ {
#ifndef NONET
INT32 i;
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
{ {
const INT32 nodei = ackpak[i].destinationnode; const INT32 nodei = ackpak[i].destinationnode;
node_t *node = &nodes[nodei]; node_t *node = &nodes[nodei];
@ -500,7 +519,7 @@ void Net_AckTicker(void)
} }
} }
for (INT32 i = 1; i < MAXNETNODES; i++) for (i = 1; i < MAXNETNODES; i++)
{ {
// This is something like node open flag // This is something like node open flag
if (nodes[i].firstacktosend) if (nodes[i].firstacktosend)
@ -517,12 +536,16 @@ void Net_AckTicker(void)
} }
} }
} }
#endif
} }
// Remove last packet received ack before resending the ackreturn // Remove last packet received ack before resending the ackreturn
// (the higher layer doesn't have room, or something else ....) // (the higher layer doesn't have room, or something else ....)
void Net_UnAcknowledgePacket(INT32 node) void Net_UnAcknowledgePacket(INT32 node)
{ {
#ifdef NONET
(void)node;
#else
INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND; INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND;
DEBFILE(va("UnAcknowledge node %d\n", node)); DEBFILE(va("UnAcknowledge node %d\n", node));
if (!node) if (!node)
@ -554,8 +577,10 @@ void Net_UnAcknowledgePacket(INT32 node)
if (!nodes[node].firstacktosend) if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = 1; nodes[node].firstacktosend = 1;
} }
#endif
} }
#ifndef NONET
/** Checks if all acks have been received /** Checks if all acks have been received
* *
* \return True if all acks have been received * \return True if all acks have been received
@ -563,12 +588,15 @@ void Net_UnAcknowledgePacket(INT32 node)
*/ */
static boolean Net_AllAcksReceived(void) static boolean Net_AllAcksReceived(void)
{ {
for (INT32 i = 0; i < MAXACKPACKETS; i++) INT32 i;
for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum) if (ackpak[i].acknum)
return false; return false;
return true; return true;
} }
#endif
/** Waits for all ackreturns /** Waits for all ackreturns
* *
@ -577,6 +605,9 @@ static boolean Net_AllAcksReceived(void)
*/ */
void Net_WaitAllAckReceived(UINT32 timeout) void Net_WaitAllAckReceived(UINT32 timeout)
{ {
#ifdef NONET
(void)timeout;
#else
tic_t tictac = I_GetTime(); tic_t tictac = I_GetTime();
timeout = tictac + timeout*NEWTICRATE; timeout = tictac + timeout*NEWTICRATE;
@ -592,6 +623,7 @@ void Net_WaitAllAckReceived(UINT32 timeout)
HGetPacket(); HGetPacket();
Net_AckTicker(); Net_AckTicker();
} }
#endif
} }
static void InitNode(node_t *node) static void InitNode(node_t *node)
@ -605,10 +637,14 @@ static void InitNode(node_t *node)
static void InitAck(void) static void InitAck(void)
{ {
for (INT32 i = 0; i < MAXACKPACKETS; i++) INT32 i;
ackpak[i].acknum = 0;
for (INT32 i = 0; i < MAXNETNODES; i++) #ifndef NONET
for (i = 0; i < MAXACKPACKETS; i++)
ackpak[i].acknum = 0;
#endif
for (i = 0; i < MAXNETNODES; i++)
InitNode(&nodes[i]); InitNode(&nodes[i]);
} }
@ -619,12 +655,17 @@ static void InitAck(void)
*/ */
void Net_AbortPacketType(UINT8 packettype) void Net_AbortPacketType(UINT8 packettype)
{ {
for (INT32 i = 0; i < MAXACKPACKETS; i++) #ifdef NONET
(void)packettype;
#else
INT32 i;
for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype
|| packettype == UINT8_MAX)) || packettype == UINT8_MAX))
{ {
ackpak[i].acknum = 0; ackpak[i].acknum = 0;
} }
#endif
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@ -634,6 +675,10 @@ void Net_AbortPacketType(UINT8 packettype)
// remove a node, clear all ack from this node and reset askret // remove a node, clear all ack from this node and reset askret
void Net_CloseConnection(INT32 node) void Net_CloseConnection(INT32 node)
{ {
#ifdef NONET
(void)node;
#else
INT32 i;
boolean forceclose = (node & FORCECLOSE) != 0; boolean forceclose = (node & FORCECLOSE) != 0;
if (node == -1) if (node == -1)
@ -663,7 +708,7 @@ void Net_CloseConnection(INT32 node)
} }
// check if we are waiting for an ack from this node // check if we are waiting for an ack from this node
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && ackpak[i].destinationnode == node) if (ackpak[i].acknum && ackpak[i].destinationnode == node)
{ {
if (!forceclose) if (!forceclose)
@ -677,8 +722,10 @@ void Net_CloseConnection(INT32 node)
if (server) if (server)
SV_AbortLuaFileTransfer(node); SV_AbortLuaFileTransfer(node);
I_NetFreeNodenum(node); I_NetFreeNodenum(node);
#endif
} }
#ifndef NONET
// //
// Checksum // Checksum
// //
@ -687,20 +734,23 @@ static UINT32 NetbufferChecksum(void)
UINT32 c = 0x1234567; UINT32 c = 0x1234567;
const INT32 l = doomcom->datalength - 4; const INT32 l = doomcom->datalength - 4;
const UINT8 *buf = (UINT8 *)netbuffer + 4; const UINT8 *buf = (UINT8 *)netbuffer + 4;
INT32 i;
for (INT32 i = 0; i < l; i++, buf++) for (i = 0; i < l; i++, buf++)
c += (*buf) * (i+1); c += (*buf) * (i+1);
return LONG(c); return LONG(c);
} }
#endif
#ifdef DEBUGFILE #ifdef DEBUGFILE
static void fprintfstring(char *s, size_t len) static void fprintfstring(char *s, size_t len)
{ {
INT32 mode = 0; INT32 mode = 0;
size_t i;
for (size_t i = 0; i < len; i++) for (i = 0; i < len; i++)
if (s[i] < 32) if (s[i] < 32)
{ {
if (!mode) if (!mode)
@ -767,6 +817,7 @@ static const char *packettypename[NUMPACKETTYPE] =
"TEXTCMD", "TEXTCMD",
"TEXTCMD2", "TEXTCMD2",
"CLIENTJOIN", "CLIENTJOIN",
"NODETIMEOUT",
"LOGIN", "LOGIN",
"TELLFILESNEEDED", "TELLFILESNEEDED",
"MOREFILESNEEDED", "MOREFILESNEEDED",
@ -867,6 +918,7 @@ void Command_Drop(void)
{ {
INT32 packetquantity; INT32 packetquantity;
const char *packetname; const char *packetname;
size_t i;
if (COM_Argc() < 2) if (COM_Argc() < 2)
{ {
@ -896,11 +948,11 @@ void Command_Drop(void)
packetname = COM_Argv(1); packetname = COM_Argv(1);
if (!(stricmp(packetname, "all") && stricmp(packetname, "any"))) if (!(stricmp(packetname, "all") && stricmp(packetname, "any")))
for (size_t i = 0; i < NUMPACKETTYPE; i++) for (i = 0; i < NUMPACKETTYPE; i++)
packetdropquantity[i] = packetquantity; packetdropquantity[i] = packetquantity;
else else
{ {
for (size_t i = 0; i < NUMPACKETTYPE; i++) for (i = 0; i < NUMPACKETTYPE; i++)
if (!stricmp(packetname, packettypename[i])) if (!stricmp(packetname, packettypename[i]))
{ {
packetdropquantity[i] = packetquantity; packetdropquantity[i] = packetquantity;
@ -931,12 +983,14 @@ void Command_Droprate(void)
packetdroprate = droprate; packetdroprate = droprate;
} }
#ifndef NONET
static boolean ShouldDropPacket(void) static boolean ShouldDropPacket(void)
{ {
return (packetdropquantity[netbuffer->packettype]) return (packetdropquantity[netbuffer->packettype])
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
} }
#endif #endif
#endif
// //
// HSendPacket // HSendPacket
@ -971,6 +1025,11 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
if (!netgame) if (!netgame)
I_Error("Tried to transmit to another node"); 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 // do this before GetFreeAcknum because this function backups
// the current packet // the current packet
doomcom->remotenode = (INT16)node; doomcom->remotenode = (INT16)node;
@ -1031,6 +1090,8 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
} }
#endif #endif
#endif // ndef NONET
return true; return true;
} }
@ -1048,6 +1109,9 @@ boolean HGetPacket(void)
{ {
M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]); M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]);
doomcom->datalength = 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; rebound_tail = (rebound_tail+1) % MAXREBOUND;
@ -1061,6 +1125,8 @@ boolean HGetPacket(void)
if (!netgame) if (!netgame)
return false; return false;
#ifndef NONET
while(true) while(true)
{ {
//nodejustjoined = I_NetGet(); //nodejustjoined = I_NetGet();
@ -1120,6 +1186,7 @@ boolean HGetPacket(void)
} }
break; break;
} }
#endif // ndef NONET
return true; return true;
} }
@ -1323,12 +1390,13 @@ void Command_Ping_f(void)
int name_width = 0; int name_width = 0;
int ms_width = 0; int ms_width = 0;
int n;
INT32 i;
pingc = 0; pingc = 0;
for (INT32 i = 1; i < MAXPLAYERS; ++i) for (i = 1; i < MAXPLAYERS; ++i)
if (playeringame[i]) if (playeringame[i])
{ {
int n;
n = strlen(player_names[i]); n = strlen(player_names[i]);
if (n > name_width) if (n > name_width)
name_width = n; name_width = n;
@ -1348,7 +1416,7 @@ void Command_Ping_f(void)
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp); qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
for (INT32 i = 0; i < pingc; ++i) for (i = 0; i < pingc; ++i)
{ {
CONS_Printf("%02d : %-*s %*d ms\n", CONS_Printf("%02d : %-*s %*d ms\n",
pingv[i].num, pingv[i].num,
@ -1364,13 +1432,15 @@ void Command_Ping_f(void)
void D_CloseConnection(void) void D_CloseConnection(void)
{ {
INT32 i;
if (netgame) if (netgame)
{ {
// wait the ackreturn with timout of 5 Sec // wait the ackreturn with timout of 5 Sec
Net_WaitAllAckReceived(5); Net_WaitAllAckReceived(5);
// close all connection // close all connection
for (INT32 i = 0; i < MAXNETNODES; i++) for (i = 0; i < MAXNETNODES; i++)
Net_CloseConnection(i|FORCECLOSE); Net_CloseConnection(i|FORCECLOSE);
InitAck(); InitAck();

View file

@ -18,8 +18,6 @@
#ifndef __D_NET__ #ifndef __D_NET__
#define __D_NET__ #define __D_NET__
#include "../doomtype.h"
// Max computers in a game // Max computers in a game
// 127 is probably as high as this can go, because // 127 is probably as high as this can go, because
// SINT8 is used for nodes sometimes >:( // SINT8 is used for nodes sometimes >:(
@ -39,24 +37,10 @@ boolean Net_GetNetStat(void);
extern INT32 getbytes; extern INT32 getbytes;
extern INT64 sendbytes; // Realtime updated extern INT64 sendbytes; // Realtime updated
typedef struct netnode_s extern SINT8 nodetoplayer[MAXNETNODES];
{ extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen)
boolean ingame; // set false as nodes leave game extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
tic_t freezetimeout; // Until when can this node freeze the server before getting a timeout? extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
SINT8 player;
SINT8 player2; // say the numplayer for this node if any (splitscreen)
UINT8 numplayers; // used specialy for scplitscreen
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; extern boolean serverrunning;
@ -68,6 +52,9 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum,
size_t packetlength); size_t packetlength);
boolean HGetPacket(void); boolean HGetPacket(void);
void D_SetDoomcom(void); void D_SetDoomcom(void);
#ifndef NONET
void D_SaveBan(void);
#endif
boolean D_CheckNetGame(void); boolean D_CheckNetGame(void);
void D_CloseConnection(void); void D_CloseConnection(void);
void Net_UnAcknowledgePacket(INT32 node); void Net_UnAcknowledgePacket(INT32 node);

View file

@ -12,47 +12,45 @@
/// commands are executed through the command buffer /// commands are executed through the command buffer
/// like console commands, other miscellaneous commands (at the end) /// like console commands, other miscellaneous commands (at the end)
#include "../doomdef.h" #include "doomdef.h"
#include "../console.h" #include "console.h"
#include "../command.h" #include "command.h"
#include "../i_time.h" #include "i_time.h"
#include "../i_system.h" #include "i_system.h"
#include "../g_game.h" #include "g_game.h"
#include "../hu_stuff.h" #include "hu_stuff.h"
#include "../g_input.h" #include "g_input.h"
#include "../i_gamepad.h" #include "i_gamepad.h"
#include "../m_menu.h" #include "m_menu.h"
#include "../r_local.h" #include "r_local.h"
#include "../r_skins.h" #include "r_skins.h"
#include "../p_local.h" #include "p_local.h"
#include "../p_setup.h" #include "p_setup.h"
#include "../s_sound.h" #include "s_sound.h"
#include "../i_sound.h" #include "i_sound.h"
#include "../m_misc.h" #include "m_misc.h"
#include "../am_map.h" #include "am_map.h"
#include "../byteptr.h" #include "byteptr.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "../p_spec.h" #include "p_spec.h"
#include "../m_cheat.h" #include "m_cheat.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "server_connection.h"
#include "net_command.h"
#include "d_net.h" #include "d_net.h"
#include "../v_video.h" #include "v_video.h"
#include "../d_main.h" #include "d_main.h"
#include "../m_random.h" #include "m_random.h"
#include "../f_finale.h" #include "f_finale.h"
#include "../filesrch.h" #include "filesrch.h"
#include "mserv.h" #include "mserv.h"
#include "../z_zone.h" #include "z_zone.h"
#include "../lua_script.h" #include "lua_script.h"
#include "../lua_hook.h" #include "lua_hook.h"
#include "../m_cond.h" #include "m_cond.h"
#include "../m_anigif.h" #include "m_anigif.h"
#include "../md5.h" #include "md5.h"
#include "../m_perfstats.h" #include "m_perfstats.h"
#include "../hardware/u_list.h" // TODO: this should be a standard utility class #include "hardware/u_list.h" // TODO: this should be a standard utility class
#ifdef NETGAME_DEVMODE #ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR #define CV_RESTRICT CV_NETVAR
@ -631,9 +629,12 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed); CV_RegisterVar(&cv_downloadspeed);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer); CV_RegisterVar(&cv_allownewplayer);
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_blamecfail);
#endif
COM_AddCommand("ping", Command_Ping_f); COM_AddCommand("ping", Command_Ping_f);
CV_RegisterVar(&cv_nettimeout); CV_RegisterVar(&cv_nettimeout);
@ -1841,7 +1842,8 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
// reset players if there is a new one // reset players if there is a new one
if (!IsPlayerAdmin(consoleplayer)) if (!IsPlayerAdmin(consoleplayer))
{ {
SV_SpawnServer(); if (SV_SpawnServer())
buf[0] &= ~(1<<1);
if (!Playing()) // you failed to start a server somehow, so cancel the map change if (!Playing()) // you failed to start a server somehow, so cancel the map change
return; return;
} }

View file

@ -15,7 +15,7 @@
#ifndef __D_NETCMD__ #ifndef __D_NETCMD__
#define __D_NETCMD__ #define __D_NETCMD__
#include "../command.h" #include "command.h"
// console vars // console vars
extern consvar_t cv_playername; extern consvar_t cv_playername;

View file

@ -31,25 +31,24 @@
#include <sys/utime.h> #include <sys/utime.h>
#endif #endif
#include "../doomdef.h" #include "doomdef.h"
#include "../doomstat.h" #include "doomstat.h"
#include "../d_main.h" #include "d_main.h"
#include "../g_game.h" #include "g_game.h"
#include "../i_time.h" #include "i_time.h"
#include "i_net.h" #include "i_net.h"
#include "../i_system.h" #include "i_system.h"
#include "../m_argv.h" #include "m_argv.h"
#include "d_net.h" #include "d_net.h"
#include "../w_wad.h" #include "w_wad.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "net_command.h" #include "z_zone.h"
#include "../z_zone.h" #include "byteptr.h"
#include "../byteptr.h" #include "p_setup.h"
#include "../p_setup.h" #include "m_misc.h"
#include "../m_misc.h" #include "m_menu.h"
#include "../m_menu.h" #include "md5.h"
#include "../md5.h" #include "filesrch.h"
#include "../filesrch.h"
#include <errno.h> #include <errno.h>
@ -104,31 +103,26 @@ typedef struct
} pauseddownload_t; } pauseddownload_t;
static pauseddownload_t *pauseddownload = NULL; static pauseddownload_t *pauseddownload = NULL;
#ifndef NONET
// for cl loading screen // for cl loading screen
INT32 lastfilenum = -1; INT32 lastfilenum = -1;
INT32 downloadcompletednum = 0; INT32 downloadcompletednum = 0;
UINT32 downloadcompletedsize = 0; UINT32 downloadcompletedsize = 0;
INT32 totalfilesrequestednum = 0; INT32 totalfilesrequestednum = 0;
UINT32 totalfilesrequestedsize = 0; UINT32 totalfilesrequestedsize = 0;
#endif
luafiletransfer_t *luafiletransfers = NULL; luafiletransfer_t *luafiletransfers = NULL;
boolean waitingforluafiletransfer = false; boolean waitingforluafiletransfer = false;
boolean waitingforluafilecommand = false; boolean waitingforluafilecommand = false;
char luafiledir[256 + 16] = "luafiles"; 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) static UINT16 GetWadNumFromFileNeededId(UINT8 id)
{ {
for (UINT16 wadnum = mainwads; wadnum < numwadfiles; wadnum++) UINT16 wadnum;
for (wadnum = mainwads; wadnum < numwadfiles; wadnum++)
{ {
if (!wadfiles[wadnum]->important) if (!wadfiles[wadnum]->important)
continue; continue;
@ -148,13 +142,14 @@ static UINT16 GetWadNumFromFileNeededId(UINT8 id)
*/ */
UINT8 *PutFileNeeded(UINT16 firstfile) UINT8 *PutFileNeeded(UINT16 firstfile)
{ {
size_t i;
UINT8 count = 0; UINT8 count = 0;
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded; UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
UINT8 *p = p_start; UINT8 *p = p_start;
char wadfilename[MAX_WADPATH] = ""; char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus, folder; UINT8 filestatus, folder;
for (size_t i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad for (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 it has only music/sound lumps, don't put it in the list
if (!wadfiles[i]->important) if (!wadfiles[i]->important)
@ -229,6 +224,7 @@ void FreeFileNeeded(void)
*/ */
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile) void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile)
{ {
INT32 i;
UINT8 *p; UINT8 *p;
UINT8 filestatus; UINT8 filestatus;
@ -237,7 +233,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
AllocFileNeeded(fileneedednum); AllocFileNeeded(fileneedednum);
for (INT32 i = firstfile; i < fileneedednum; i++) for (i = firstfile; i < fileneedednum; i++)
{ {
fileneeded[i].type = FILENEEDED_WAD; fileneeded[i].type = FILENEEDED_WAD;
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
@ -254,7 +250,9 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
void CL_PrepareDownloadSaveGame(const char *tmpsave) void CL_PrepareDownloadSaveGame(const char *tmpsave)
{ {
#ifndef NONET
lastfilenum = -1; lastfilenum = -1;
#endif
FreeFileNeeded(); FreeFileNeeded();
AllocFileNeeded(1); AllocFileNeeded(1);
@ -277,9 +275,9 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
*/ */
boolean CL_CheckDownloadable(void) boolean CL_CheckDownloadable(void)
{ {
UINT8 dlstatus = 0; UINT8 i,dlstatus = 0;
for (UINT8 i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{ {
if (fileneeded[i].willsend == 1) if (fileneeded[i].willsend == 1)
@ -300,7 +298,7 @@ boolean CL_CheckDownloadable(void)
// not downloadable, put reason in console // not downloadable, put reason in console
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
for (UINT8 i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{ {
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
@ -370,13 +368,14 @@ void CL_AbortDownloadResume(void)
boolean CL_SendFileRequest(void) boolean CL_SendFileRequest(void)
{ {
char *p; char *p;
INT32 i;
INT64 totalfreespaceneeded = 0, availablefreespace; INT64 totalfreespaceneeded = 0, availablefreespace;
#ifdef PARANOIA #ifdef PARANOIA
if (M_CheckParm("-nodownload")) if (M_CheckParm("-nodownload"))
I_Error("Attempted to download files in -nodownload mode"); I_Error("Attempted to download files in -nodownload mode");
for (INT32 i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
{ {
@ -386,7 +385,7 @@ boolean CL_SendFileRequest(void)
netbuffer->packettype = PT_REQUESTFILE; netbuffer->packettype = PT_REQUESTFILE;
p = (char *)netbuffer->u.textcmd; p = (char *)netbuffer->u.textcmd;
for (INT32 i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
{ {
totalfreespaceneeded += fileneeded[i].totalsize; totalfreespaceneeded += fileneeded[i].totalsize;
@ -414,31 +413,26 @@ boolean CL_SendFileRequest(void)
} }
// get request filepak and put it on the send queue // get request filepak and put it on the send queue
void PT_RequestFile(SINT8 node) // returns false if a requested file was not found or cannot be sent
boolean PT_RequestFile(INT32 node)
{ {
UINT8 *p = netbuffer->u.textcmd; 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 while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow
{ {
UINT8 id = READUINT8(p); id = READUINT8(p);
if (id == 0xFF) if (id == 0xFF)
break; break;
if (!AddFileToSendQueue(node, id)) if (!AddFileToSendQueue(node, id))
{ {
SV_AbortSendFiles(node); SV_AbortSendFiles(node);
Net_CloseConnection(node); // close connection if one of the requested files could not be sent return false; // don't read the rest of the files
return; // don't read the rest of the files
} }
} }
return; // no problems with any files return true; // no problems with any files
} }
/** Checks if the files needed aren't already loaded or on the disk /** Checks if the files needed aren't already loaded or on the disk
@ -537,7 +531,9 @@ INT32 CL_CheckFiles(void)
// Load it now // Load it now
boolean CL_LoadServerFiles(void) boolean CL_LoadServerFiles(void)
{ {
for (INT32 i = 0; i < fileneedednum; i++) INT32 i;
for (i = 0; i < fileneedednum; i++)
{ {
if (fileneeded[i].status == FS_OPEN) if (fileneeded[i].status == FS_OPEN)
continue; // Already loaded continue; // Already loaded
@ -633,10 +629,11 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
static void SV_PrepareSendLuaFileToNextNode(void) static void SV_PrepareSendLuaFileToNextNode(void)
{ {
INT32 i;
UINT8 success = 1; UINT8 success = 1;
// Find a client to send the file to // Find a client to send the file to
for (INT32 i = 1; i < MAXNETNODES; i++) for (i = 1; i < MAXNETNODES; i++)
if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting
{ {
// Tell the client we're about to send them the file // Tell the client we're about to send them the file
@ -658,12 +655,13 @@ static void SV_PrepareSendLuaFileToNextNode(void)
void SV_PrepareSendLuaFile(void) void SV_PrepareSendLuaFile(void)
{ {
char *binfilename; char *binfilename;
INT32 i;
luafiletransfers->ongoing = true; luafiletransfers->ongoing = true;
// Set status to "waiting" for everyone // Set status to "waiting" for everyone
for (INT32 i = 0; i < MAXNETNODES; i++) for (i = 0; i < MAXNETNODES; i++)
luafiletransfers->nodestatus[i] = (netnodes[i].ingame ? LFTNS_WAITING : LFTNS_NONE); luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE);
if (FIL_ReadFileOK(luafiletransfers->realfilename)) if (FIL_ReadFileOK(luafiletransfers->realfilename))
{ {
@ -1139,13 +1137,12 @@ void FileSendTicker(void)
} }
} }
void PT_FileAck(SINT8 node) void PT_FileAck(void)
{ {
fileack_pak *packet = &netbuffer->u.fileack; fileack_pak *packet = &netbuffer->u.fileack;
INT32 node = doomcom->remotenode;
filetran_t *trans = &transfer[node]; filetran_t *trans = &transfer[node];
INT32 i, j;
if (client)
return;
// Wrong file id? Ignore it, it's probably a late packet // Wrong file id? Ignore it, it's probably a late packet
if (!(trans->txlist && packet->fileid == trans->txlist->fileid)) if (!(trans->txlist && packet->fileid == trans->txlist->fileid))
@ -1164,11 +1161,11 @@ void PT_FileAck(SINT8 node)
trans->dontsenduntil = 0; trans->dontsenduntil = 0;
} }
for (INT32 i = 0; i < packet->numsegments; i++) for (i = 0; i < packet->numsegments; i++)
{ {
fileacksegment_t *segment = &packet->segments[i]; fileacksegment_t *segment = &packet->segments[i];
for (INT32 j = 0; j < 32; j++) for (j = 0; j < 32; j++)
if (LONG(segment->acks) & (1 << j)) if (LONG(segment->acks) & (1 << j))
{ {
if (LONG(segment->start) * FILEFRAGMENTSIZE >= trans->txlist->size) if (LONG(segment->start) * FILEFRAGMENTSIZE >= trans->txlist->size)
@ -1193,23 +1190,24 @@ void PT_FileAck(SINT8 node)
} }
} }
void PT_FileReceived(SINT8 node) void PT_FileReceived(void)
{ {
filetx_t *trans = transfer[node].txlist; filetx_t *trans = transfer[doomcom->remotenode].txlist;
if (server && trans && netbuffer->u.filereceived == trans->fileid) if (trans && netbuffer->u.filereceived == trans->fileid)
SV_EndFileSend(node); SV_EndFileSend(doomcom->remotenode);
} }
static void SendAckPacket(fileack_pak *packet, UINT8 fileid) static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
{ {
size_t packetsize; size_t packetsize;
INT32 i;
packetsize = sizeof(*packet) + packet->numsegments * sizeof(*packet->segments); packetsize = sizeof(*packet) + packet->numsegments * sizeof(*packet->segments);
// Finalise the packet // Finalise the packet
packet->fileid = fileid; packet->fileid = fileid;
for (INT32 i = 0; i < packet->numsegments; i++) for (i = 0; i < packet->numsegments; i++)
{ {
packet->segments[i].start = LONG(packet->segments[i].start); packet->segments[i].start = LONG(packet->segments[i].start);
packet->segments[i].acks = LONG(packet->segments[i].acks); packet->segments[i].acks = LONG(packet->segments[i].acks);
@ -1249,7 +1247,9 @@ static void AddFragmentToAckPacket(fileack_pak *packet, UINT8 iteration, UINT32
void FileReceiveTicker(void) void FileReceiveTicker(void)
{ {
for (INT32 i = 0; i < fileneedednum; i++) INT32 i;
for (i = 0; i < fileneedednum; i++)
{ {
fileneeded_t *file = &fileneeded[i]; fileneeded_t *file = &fileneeded[i];
@ -1263,7 +1263,8 @@ void FileReceiveTicker(void)
if (file->ackresendposition != UINT32_MAX && file->status == FS_DOWNLOADING) if (file->ackresendposition != UINT32_MAX && file->status == FS_DOWNLOADING)
{ {
// Acknowledge ~70 MB/s, whichs means the client sends ~18 KB/s // Acknowledge ~70 MB/s, whichs means the client sends ~18 KB/s
for (INT32 j = 0; j < 2048; j++) INT32 j;
for (j = 0; j < 2048; j++)
{ {
if (file->receivedfragments[file->ackresendposition]) if (file->receivedfragments[file->ackresendposition])
AddFragmentToAckPacket(file->ackpacket, file->iteration, file->ackresendposition, i); AddFragmentToAckPacket(file->ackpacket, file->iteration, file->ackresendposition, i);
@ -1280,27 +1281,8 @@ void FileReceiveTicker(void)
} }
} }
void PT_FileFragment(SINT8 node, INT32 netconsole) void PT_FileFragment(void)
{ {
if (netnodes[node].ingame)
{
// 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; INT32 filenum = netbuffer->u.filetxpak.fileid;
fileneeded_t *file = &fileneeded[filenum]; fileneeded_t *file = &fileneeded[filenum];
UINT32 fragmentpos = LONG(netbuffer->u.filetxpak.position); UINT32 fragmentpos = LONG(netbuffer->u.filetxpak.position);
@ -1457,7 +1439,9 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s); I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
} }
#ifndef NONET
lastfilenum = filenum; lastfilenum = filenum;
#endif
} }
/** \brief Checks if a node is downloading a file /** \brief Checks if a node is downloading a file
@ -1485,14 +1469,15 @@ void SV_AbortSendFiles(INT32 node)
void CloseNetFile(void) void CloseNetFile(void)
{ {
INT32 i;
// Is sending? // Is sending?
for (INT32 i = 0; i < MAXNETNODES; i++) for (i = 0; i < MAXNETNODES; i++)
SV_AbortSendFiles(i); SV_AbortSendFiles(i);
// Receiving a file? // Receiving a file?
if (fileneeded) if (fileneeded)
{ {
for (INT32 i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
{ {
fclose(fileneeded[i].file); fclose(fileneeded[i].file);
@ -1525,7 +1510,9 @@ void CloseNetFile(void)
void Command_Downloads_f(void) void Command_Downloads_f(void)
{ {
for (INT32 node = 0; node < MAXNETNODES; node++) INT32 node;
for (node = 0; node < MAXNETNODES; node++)
if (transfer[node].txlist if (transfer[node].txlist
&& transfer[node].txlist->ram == SF_FILE) // Node is downloading a file? && transfer[node].txlist->ram == SF_FILE) // Node is downloading a file?
{ {
@ -1559,11 +1546,14 @@ void Command_Downloads_f(void)
void nameonly(char *s) void nameonly(char *s)
{ {
for (size_t j = strlen(s); j != (size_t)-1; j--) size_t j, len;
void *ns;
for (j = strlen(s); j != (size_t)-1; j--)
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/')) if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
{ {
void *ns = &(s[j+1]); ns = &(s[j+1]);
size_t len = strlen(ns); len = strlen(ns);
#if 0 #if 0
M_Memcpy(s, ns, len+1); M_Memcpy(s, ns, len+1);
#else #else
@ -1576,9 +1566,9 @@ void nameonly(char *s)
// Returns the length in characters of the last element of a path. // Returns the length in characters of the last element of a path.
size_t nameonlylength(const char *s) size_t nameonlylength(const char *s)
{ {
size_t len = strlen(s); size_t j, len = strlen(s);
for (size_t j = len; j != (size_t)-1; j--) for (j = len; j != (size_t)-1; j--)
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/')) if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
return len - j - 1; return len - j - 1;

View file

@ -15,7 +15,7 @@
#include "d_net.h" #include "d_net.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "../w_wad.h" #include "w_wad.h"
typedef enum typedef enum
{ {
@ -70,13 +70,13 @@ extern INT32 fileneedednum;
extern fileneeded_t *fileneeded; extern fileneeded_t *fileneeded;
extern char downloaddir[512]; extern char downloaddir[512];
#ifndef NONET
extern INT32 lastfilenum; extern INT32 lastfilenum;
extern INT32 downloadcompletednum; extern INT32 downloadcompletednum;
extern UINT32 downloadcompletedsize; extern UINT32 downloadcompletedsize;
extern INT32 totalfilesrequestednum; extern INT32 totalfilesrequestednum;
extern UINT32 totalfilesrequestedsize; extern UINT32 totalfilesrequestedsize;
#endif
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
void AllocFileNeeded(INT32 size); void AllocFileNeeded(INT32 size);
void FreeFileNeeded(void); void FreeFileNeeded(void);
@ -90,16 +90,16 @@ void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemet
UINT8 fileid); UINT8 fileid);
void FileSendTicker(void); void FileSendTicker(void);
void PT_FileAck(SINT8 node); void PT_FileAck(void);
void PT_FileReceived(SINT8 node); void PT_FileReceived(void);
boolean SendingFile(INT32 node); boolean SendingFile(INT32 node);
void FileReceiveTicker(void); void FileReceiveTicker(void);
void PT_FileFragment(SINT8 node, INT32 netconsole); void PT_FileFragment(void);
boolean CL_CheckDownloadable(void); boolean CL_CheckDownloadable(void);
boolean CL_SendFileRequest(void); boolean CL_SendFileRequest(void);
void PT_RequestFile(SINT8 node); boolean PT_RequestFile(INT32 node);
typedef enum typedef enum
{ {

View file

@ -34,7 +34,7 @@
#include "r_sky.h" #include "r_sky.h"
#include "fastcmp.h" #include "fastcmp.h"
#include "lua_script.h" // Reluctantly included for LUA_EvalMath #include "lua_script.h" // Reluctantly included for LUA_EvalMath
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_light.h" #include "hardware/hw_light.h"

View file

@ -35,7 +35,7 @@
#include "r_sky.h" #include "r_sky.h"
#include "fastcmp.h" #include "fastcmp.h"
#include "lua_script.h" // Reluctantly included for LUA_EvalMath #include "lua_script.h" // Reluctantly included for LUA_EvalMath
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_light.h" #include "hardware/hw_light.h"

View file

@ -4831,7 +4831,7 @@ const char *const MENUTYPES_LIST[] = {
"MP_SERVER", "MP_SERVER",
"MP_CONNECT", "MP_CONNECT",
"MP_ROOM", "MP_ROOM",
"MP_PLAYERSETUP", "MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
"MP_SERVER_OPTIONS", "MP_SERVER_OPTIONS",
// Options // Options

View file

@ -56,6 +56,7 @@
#endif #endif
#ifdef _WINDOWS #ifdef _WINDOWS
#define NONET
#if !defined (HWRENDER) && !defined (NOHW) #if !defined (HWRENDER) && !defined (NOHW)
#define HWRENDER #define HWRENDER
#endif #endif
@ -656,7 +657,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Maintain compatibility with older 2.2 demos /// Maintain compatibility with older 2.2 demos
#define OLD22DEMOCOMPAT #define OLD22DEMOCOMPAT
#ifdef HAVE_CURL #if defined (HAVE_CURL) && ! defined (NONET)
#define MASTERSERVER #define MASTERSERVER
#else #else
#undef UPDATE_ALERT #undef UPDATE_ALERT

View file

@ -683,7 +683,7 @@ extern boolean singletics;
// Netgame stuff // Netgame stuff
// ============= // =============
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
extern consvar_t cv_timetic; // display high resolution timer extern consvar_t cv_timetic; // display high resolution timer
extern consvar_t cv_powerupdisplay; // display powerups extern consvar_t cv_powerupdisplay; // display powerups

View file

@ -1,4 +1,4 @@
#include "../netcode/i_net.h" #include "../i_net.h"
boolean I_InitNetwork(void) boolean I_InitNetwork(void)
{ {

View file

@ -14,7 +14,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "d_main.h" #include "d_main.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "f_finale.h" #include "f_finale.h"
#include "g_game.h" #include "g_game.h"
#include "hu_stuff.h" #include "hu_stuff.h"

View file

@ -26,7 +26,7 @@
#include <string.h> #include <string.h>
#include "filesrch.h" #include "filesrch.h"
#include "netcode/d_netfil.h" #include "d_netfil.h"
#include "m_misc.h" #include "m_misc.h"
#include "z_zone.h" #include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange #include "m_menu.h" // Addons_option_Onchange

View file

@ -5,7 +5,7 @@
#define __FILESRCH_H__ #define __FILESRCH_H__
#include "doomdef.h" #include "doomdef.h"
#include "netcode/d_netfil.h" #include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH #include "m_menu.h" // MAXSTRINGLENGTH
#include "w_wad.h" #include "w_wad.h"

View file

@ -15,7 +15,7 @@
#include "console.h" #include "console.h"
#include "d_main.h" #include "d_main.h"
#include "d_player.h" #include "d_player.h"
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#include "p_setup.h" #include "p_setup.h"
#include "i_time.h" #include "i_time.h"
#include "i_system.h" #include "i_system.h"

View file

@ -15,8 +15,7 @@
#include "console.h" #include "console.h"
#include "d_main.h" #include "d_main.h"
#include "d_player.h" #include "d_player.h"
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#include "netcode/net_command.h"
#include "f_finale.h" #include "f_finale.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"

View file

@ -18,7 +18,7 @@
#include "i_gamepad.h" #include "i_gamepad.h"
#include "keys.h" #include "keys.h"
#include "hu_stuff.h" // need HUFONT start & end #include "hu_stuff.h" // need HUFONT start & end
#include "netcode/d_net.h" #include "d_net.h"
#include "console.h" #include "console.h"
#define MAXMOUSESENSITIVITY 100 // sensitivity steps #define MAXMOUSESENSITIVITY 100 // sensitivity steps

View file

@ -29,7 +29,7 @@
#include "../r_patch.h" #include "../r_patch.h"
#include "../r_picformats.h" #include "../r_picformats.h"
#include "../r_bsp.h" #include "../r_bsp.h"
#include "../netcode/d_clisrv.h" #include "../d_clisrv.h"
#include "../w_wad.h" #include "../w_wad.h"
#include "../z_zone.h" #include "../z_zone.h"
#include "../r_splats.h" #include "../r_splats.h"

View file

@ -18,15 +18,14 @@ Documentation available here.
#include <curl/curl.h> #include <curl/curl.h>
#endif #endif
#include "../doomdef.h" #include "doomdef.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "client_connection.h" #include "command.h"
#include "../command.h" #include "m_argv.h"
#include "../m_argv.h" #include "m_menu.h"
#include "../m_menu.h"
#include "mserv.h" #include "mserv.h"
#include "i_tcp.h"/* for current_port */ #include "i_tcp.h"/* for current_port */
#include "../i_threads.h" #include "i_threads.h"
/* reasonable default I guess?? */ /* reasonable default I guess?? */
#define DEFAULT_BUFFER_SIZE (4096) #define DEFAULT_BUFFER_SIZE (4096)

View file

@ -19,9 +19,7 @@
#include "m_cond.h" // emblems #include "m_cond.h" // emblems
#include "m_misc.h" // word jumping #include "m_misc.h" // word jumping
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#include "netcode/net_command.h"
#include "netcode/gamestate.h"
#include "g_game.h" #include "g_game.h"
#include "g_input.h" #include "g_input.h"
@ -177,12 +175,14 @@ static huddrawlist_h luahuddrawlist_scores;
static tic_t resynch_ticker = 0; static tic_t resynch_ticker = 0;
#ifndef NONET
// just after // just after
static void Command_Say_f(void); static void Command_Say_f(void);
static void Command_Sayto_f(void); static void Command_Sayto_f(void);
static void Command_Sayteam_f(void); static void Command_Sayteam_f(void);
static void Command_CSay_f(void); static void Command_CSay_f(void);
static void Got_Saycmd(UINT8 **p, INT32 playernum); static void Got_Saycmd(UINT8 **p, INT32 playernum);
#endif
void HU_LoadGraphics(void) void HU_LoadGraphics(void)
{ {
@ -327,11 +327,13 @@ void HU_LoadGraphics(void)
// //
void HU_Init(void) void HU_Init(void)
{ {
#ifndef NONET
COM_AddCommand("say", Command_Say_f); COM_AddCommand("say", Command_Say_f);
COM_AddCommand("sayto", Command_Sayto_f); COM_AddCommand("sayto", Command_Sayto_f);
COM_AddCommand("sayteam", Command_Sayteam_f); COM_AddCommand("sayteam", Command_Sayteam_f);
COM_AddCommand("csay", Command_CSay_f); COM_AddCommand("csay", Command_CSay_f);
RegisterNetXCmd(XD_SAY, Got_Saycmd); RegisterNetXCmd(XD_SAY, Got_Saycmd);
#endif
// set shift translation table // set shift translation table
shiftxform = english_shiftxform; shiftxform = english_shiftxform;
@ -361,6 +363,8 @@ void HU_Start(void)
// EXECUTION // EXECUTION
//====================================================================== //======================================================================
#ifndef NONET
// EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM // EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM
static UINT32 chat_nummsg_log = 0; static UINT32 chat_nummsg_log = 0;
@ -408,9 +412,11 @@ static void HU_removeChatText_Log(void)
} }
chat_nummsg_log--; // lost 1 msg. chat_nummsg_log--; // lost 1 msg.
} }
#endif
void HU_AddChatText(const char *text, boolean playsound) 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. if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat.
S_StartSound(NULL, sfx_radio); 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. // reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game.
@ -432,8 +438,14 @@ void HU_AddChatText(const char *text, boolean playsound)
CONS_Printf("%s\n", text); CONS_Printf("%s\n", text);
else // if we aren't, still save the message to log.txt else // if we aren't, still save the message to log.txt
CON_LogMessage(va("%s\n", text)); 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. /** Runs a say command, sending an ::XD_SAY message.
* A say command consists of a signed 8-bit integer for the target, an * A say command consists of a signed 8-bit integer for the target, an
* unsigned 8-bit flag variable, and then the message itself. * unsigned 8-bit flag variable, and then the message itself.
@ -853,6 +865,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
#endif #endif
} }
#endif
// //
// //
void HU_Ticker(void) void HU_Ticker(void)
@ -868,6 +882,7 @@ void HU_Ticker(void)
else else
hu_showscores = false; hu_showscores = false;
#ifndef NONET
if (chat_on) if (chat_on)
{ {
// count down the scroll timer. // count down the scroll timer.
@ -895,6 +910,7 @@ void HU_Ticker(void)
HU_removeChatText_Mini(); HU_removeChatText_Mini();
} }
} }
#endif
if (cechotimer > 0) --cechotimer; if (cechotimer > 0) --cechotimer;
@ -902,6 +918,8 @@ void HU_Ticker(void)
resynch_ticker++; resynch_ticker++;
} }
#ifndef NONET
static boolean teamtalk = false; static boolean teamtalk = false;
static boolean justscrolleddown; static boolean justscrolleddown;
static boolean justscrolledup; static boolean justscrolledup;
@ -1009,6 +1027,8 @@ static void HU_sendChatMessage(void)
} }
} }
#endif
void HU_clearChatChars(void) void HU_clearChatChars(void)
{ {
memset(w_chat, '\0', sizeof(w_chat)); memset(w_chat, '\0', sizeof(w_chat));
@ -1023,13 +1043,16 @@ void HU_clearChatChars(void)
// //
boolean HU_Responder(event_t *ev) boolean HU_Responder(event_t *ev)
{ {
#ifndef NONET
INT32 c=0; INT32 c=0;
#endif
if (ev->type != ev_keydown) if (ev->type != ev_keydown)
return false; return false;
// only KeyDown events now... // only KeyDown events now...
#ifndef NONET
c = (INT32)ev->key; c = (INT32)ev->key;
if (!chat_on) if (!chat_on)
@ -1179,6 +1202,7 @@ boolean HU_Responder(event_t *ev)
return true; return true;
} }
#endif
return false; return false;
} }
@ -1188,6 +1212,8 @@ boolean HU_Responder(event_t *ev)
// HEADS UP DRAWING // HEADS UP DRAWING
//====================================================================== //======================================================================
#ifndef NONET
// Precompile a wordwrapped string to any given width. // Precompile a wordwrapped string to any given width.
// This is a muuuch better method than V_WORDWRAP. // 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. // again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day.
@ -1767,6 +1793,7 @@ static void HU_DrawChat_Old(void)
if (hu_tick < 4) if (hu_tick < 4)
V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true); V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true);
} }
#endif
// Draw crosshairs at the exact center of the view. // Draw crosshairs at the exact center of the view.
// In splitscreen, crosshairs are stretched vertically to compensate for V_PERPLAYER squishing them. // In splitscreen, crosshairs are stretched vertically to compensate for V_PERPLAYER squishing them.
@ -1906,6 +1933,7 @@ static void HU_DrawDemoInfo(void)
// //
void HU_Drawer(void) void HU_Drawer(void)
{ {
#ifndef NONET
// draw chat string plus cursor // draw chat string plus cursor
if (chat_on) if (chat_on)
{ {
@ -1922,6 +1950,7 @@ void HU_Drawer(void)
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden) 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. HU_drawMiniChat(); // draw messages in a cool fashion.
} }
#endif
if (cechotimer) if (cechotimer)
HU_DrawCEcho(); HU_DrawCEcho();

View file

@ -18,8 +18,8 @@
#pragma interface #pragma interface
#endif #endif
#include "../doomdef.h" #include "doomdef.h"
#include "../command.h" #include "command.h"
/// \brief program net id /// \brief program net id
#define DOOMCOM_ID (INT32)0x12345678l #define DOOMCOM_ID (INT32)0x12345678l

View file

@ -36,8 +36,15 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#include "../doomdef.h" #include "doomdef.h"
#if defined (NOMD5) && !defined (NONET)
//#define NONET
#endif
#ifdef NONET
#undef HAVE_MINIUPNPC
#else
#ifdef USE_WINSOCK1 #ifdef USE_WINSOCK1
#include <winsock.h> #include <winsock.h>
#else #else
@ -120,16 +127,18 @@ typedef union
static UINT8 UPNP_support = TRUE; static UINT8 UPNP_support = TRUE;
#endif // HAVE_MINIUPNC #endif // HAVE_MINIUPNC
#endif // !NONET
#define MAXBANS 100 #define MAXBANS 100
#include "../i_system.h" #include "i_system.h"
#include "i_net.h" #include "i_net.h"
#include "d_net.h" #include "d_net.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "i_tcp.h" #include "i_tcp.h"
#include "../m_argv.h" #include "m_argv.h"
#include "../doomstat.h" #include "doomstat.h"
// win32 // win32
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
@ -142,7 +151,7 @@ typedef union
#define SELECTTEST #define SELECTTEST
#define DEFAULTPORT "5029" #define DEFAULTPORT "5029"
#ifdef USE_WINSOCK #if defined (USE_WINSOCK) && !defined (NONET)
typedef SOCKET SOCKET_TYPE; typedef SOCKET SOCKET_TYPE;
#define ERRSOCKET (SOCKET_ERROR) #define ERRSOCKET (SOCKET_ERROR)
#else #else
@ -154,6 +163,7 @@ typedef union
#define ERRSOCKET (-1) #define ERRSOCKET (-1)
#endif #endif
#ifndef NONET
// define socklen_t in DOS/Windows if it is not already defined // define socklen_t in DOS/Windows if it is not already defined
#ifdef USE_WINSOCK1 #ifdef USE_WINSOCK1
typedef int socklen_t; typedef int socklen_t;
@ -168,6 +178,7 @@ static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1]; static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS]; static mysockaddr_t banned[MAXBANS];
static UINT8 bannedmask[MAXBANS]; static UINT8 bannedmask[MAXBANS];
#endif
static size_t numbans = 0; static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
@ -176,6 +187,7 @@ static boolean init_tcp_driver = false;
static const char *serverport_name = DEFAULTPORT; static const char *serverport_name = DEFAULTPORT;
static const char *clientport_name;/* any port */ static const char *clientport_name;/* any port */
#ifndef NONET
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
// stupid microsoft makes things complicated // stupid microsoft makes things complicated
static char *get_WSAErrorStr(int e) static char *get_WSAErrorStr(int e)
@ -362,33 +374,47 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
#endif #endif
return s; return s;
} }
#endif
static const char *SOCK_GetNodeAddress(INT32 node) static const char *SOCK_GetNodeAddress(INT32 node)
{ {
if (node == 0) if (node == 0)
return "self"; return "self";
#ifdef NONET
return NULL;
#else
if (!nodeconnected[node]) if (!nodeconnected[node])
return NULL; return NULL;
return SOCK_AddrToStr(&clientaddress[node]); return SOCK_AddrToStr(&clientaddress[node]);
#endif
} }
static const char *SOCK_GetBanAddress(size_t ban) static const char *SOCK_GetBanAddress(size_t ban)
{ {
if (ban >= numbans) if (ban >= numbans)
return NULL; return NULL;
#ifdef NONET
return NULL;
#else
return SOCK_AddrToStr(&banned[ban]); return SOCK_AddrToStr(&banned[ban]);
#endif
} }
static const char *SOCK_GetBanMask(size_t ban) 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 static char s[16]; //255.255.255.255 netmask? no, just CDIR for only
if (ban >= numbans) if (ban >= numbans)
return NULL; return NULL;
if (sprintf(s,"%d",bannedmask[ban]) > 0) if (sprintf(s,"%d",bannedmask[ban]) > 0)
return s; return s;
#endif
return NULL; return NULL;
} }
#ifndef NONET
static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
{ {
UINT32 bitmask = INADDR_NONE; UINT32 bitmask = INADDR_NONE;
@ -416,20 +442,24 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
*/ */
static void cleanupnodes(void) static void cleanupnodes(void)
{ {
SINT8 j;
if (!Playing()) if (!Playing())
return; return;
// Why can't I start at zero? // Why can't I start at zero?
for (SINT8 j = 1; j < MAXNETNODES; j++) for (j = 1; j < MAXNETNODES; j++)
if (!(netnodes[j].ingame || SendingFile(j))) if (!(nodeingame[j] || SendingFile(j)))
nodeconnected[j] = false; nodeconnected[j] = false;
} }
static SINT8 getfreenode(void) static SINT8 getfreenode(void)
{ {
SINT8 j;
cleanupnodes(); cleanupnodes();
for (SINT8 j = 0; j < MAXNETNODES; j++) for (j = 0; j < MAXNETNODES; j++)
if (!nodeconnected[j]) if (!nodeconnected[j])
{ {
nodeconnected[j] = true; nodeconnected[j] = true;
@ -442,8 +472,8 @@ static SINT8 getfreenode(void)
* downloading a needed wad, but it's better than not letting anyone join... * downloading a needed wad, but it's better than not letting anyone join...
*/ */
/*I_Error("No more free nodes!!1!11!11!!1111\n"); /*I_Error("No more free nodes!!1!11!11!!1111\n");
for (SINT8 j = 1; j < MAXNETNODES; j++) for (j = 1; j < MAXNETNODES; j++)
if (!netnodes[j].ingame) if (!nodeingame[j])
return j;*/ return j;*/
return -1; return -1;
@ -454,27 +484,28 @@ void Command_Numnodes(void)
{ {
INT32 connected = 0; INT32 connected = 0;
INT32 ingame = 0; INT32 ingame = 0;
INT32 i;
for (INT32 i = 1; i < MAXNETNODES; i++) for (i = 1; i < MAXNETNODES; i++)
{ {
if (!(nodeconnected[i] || netnodes[i].ingame)) if (!(nodeconnected[i] || nodeingame[i]))
continue; continue;
if (nodeconnected[i]) if (nodeconnected[i])
connected++; connected++;
if (netnodes[i].ingame) if (nodeingame[i])
ingame++; ingame++;
CONS_Printf("%2d - ", i); CONS_Printf("%2d - ", i);
if (netnodes[i].player != -1) if (nodetoplayer[i] != -1)
CONS_Printf("player %.2d", netnodes[i].player); CONS_Printf("player %.2d", nodetoplayer[i]);
else else
CONS_Printf(" "); CONS_Printf(" ");
if (nodeconnected[i]) if (nodeconnected[i])
CONS_Printf(" - connected"); CONS_Printf(" - connected");
else else
CONS_Printf(" - "); CONS_Printf(" - ");
if (netnodes[i].ingame) if (nodeingame[i])
CONS_Printf(" - ingame"); CONS_Printf(" - ingame");
else else
CONS_Printf(" - "); CONS_Printf(" - ");
@ -487,17 +518,19 @@ void Command_Numnodes(void)
connected, ingame); connected, ingame);
} }
#endif #endif
#endif
#ifndef NONET
// Returns true if a packet was received from a new node, false in all other cases // Returns true if a packet was received from a new node, false in all other cases
static boolean SOCK_Get(void) static boolean SOCK_Get(void)
{ {
size_t i; size_t i, n;
int j; int j;
ssize_t c; ssize_t c;
mysockaddr_t fromaddress; mysockaddr_t fromaddress;
socklen_t fromlen; socklen_t fromlen;
for (size_t n = 0; n < mysocketses; n++) for (n = 0; n < mysocketses; n++)
{ {
fromlen = (socklen_t)sizeof(fromaddress); fromlen = (socklen_t)sizeof(fromaddress);
c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0, c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0,
@ -550,17 +583,20 @@ static boolean SOCK_Get(void)
doomcom->remotenode = -1; // no packet doomcom->remotenode = -1; // no packet
return false; return false;
} }
#endif
// check if we can send (do not go over the buffer) // check if we can send (do not go over the buffer)
#ifndef NONET
static fd_set masterset; static fd_set masterset;
#ifdef SELECTTEST #ifdef SELECTTEST
static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len) static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
{ {
size_t i;
boolean testset = false; boolean testset = false;
FD_ZERO(dst); FD_ZERO(dst);
for (size_t i = 0; i < len;i++) for (i = 0; i < len;i++)
{ {
if(fd[i] != (SOCKET_TYPE)ERRSOCKET && if(fd[i] != (SOCKET_TYPE)ERRSOCKET &&
FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
@ -600,7 +636,9 @@ static boolean SOCK_CanGet(void)
return false; return false;
} }
#endif #endif
#endif
#ifndef NONET
static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
{ {
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
@ -624,15 +662,16 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
static void SOCK_Send(void) static void SOCK_Send(void)
{ {
ssize_t c = ERRSOCKET; ssize_t c = ERRSOCKET;
size_t i, j;
if (!nodeconnected[doomcom->remotenode]) if (!nodeconnected[doomcom->remotenode])
return; return;
if (doomcom->remotenode == BROADCASTADDR) if (doomcom->remotenode == BROADCASTADDR)
{ {
for (size_t i = 0; i < mysocketses; i++) for (i = 0; i < mysocketses; i++)
{ {
for (size_t j = 0; j < broadcastaddresses; j++) for (j = 0; j < broadcastaddresses; j++)
{ {
if (myfamily[i] == broadcastaddress[j].any.sa_family) if (myfamily[i] == broadcastaddress[j].any.sa_family)
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
@ -642,7 +681,7 @@ static void SOCK_Send(void)
} }
else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
{ {
for (size_t i = 0; i < mysocketses; i++) for (i = 0; i < mysocketses; i++)
{ {
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
@ -662,7 +701,9 @@ static void SOCK_Send(void)
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
} }
} }
#endif
#ifndef NONET
static void SOCK_FreeNodenum(INT32 numnode) static void SOCK_FreeNodenum(INT32 numnode)
{ {
// can't disconnect from self :) // can't disconnect from self :)
@ -677,10 +718,12 @@ static void SOCK_FreeNodenum(INT32 numnode)
// put invalid address // put invalid address
memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode])); memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode]));
} }
#endif
// //
// UDPsocket // UDPsocket
// //
#ifndef NONET
// allocate a socket // allocate a socket
static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen) static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen)
@ -1001,10 +1044,12 @@ static boolean UDP_Socket(void)
return true; return true;
} }
#endif
boolean I_InitTcpDriver(void) boolean I_InitTcpDriver(void)
{ {
boolean tcp_was_up = init_tcp_driver; boolean tcp_was_up = init_tcp_driver;
#ifndef NONET
if (!init_tcp_driver) if (!init_tcp_driver)
{ {
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
@ -1059,7 +1104,7 @@ boolean I_InitTcpDriver(void)
#endif #endif
init_tcp_driver = true; init_tcp_driver = true;
} }
#endif
if (!tcp_was_up && init_tcp_driver) if (!tcp_was_up && init_tcp_driver)
{ {
I_AddExitFunc(I_ShutdownTcpDriver); I_AddExitFunc(I_ShutdownTcpDriver);
@ -1073,9 +1118,11 @@ boolean I_InitTcpDriver(void)
return init_tcp_driver; return init_tcp_driver;
} }
#ifndef NONET
static void SOCK_CloseSocket(void) static void SOCK_CloseSocket(void)
{ {
for (size_t i=0; i < MAXNETNODES+1; i++) size_t i;
for (i=0; i < MAXNETNODES+1; i++)
{ {
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
&& FD_ISSET(mysockets[i], &masterset)) && FD_ISSET(mysockets[i], &masterset))
@ -1086,9 +1133,11 @@ static void SOCK_CloseSocket(void)
mysockets[i] = ERRSOCKET; mysockets[i] = ERRSOCKET;
} }
} }
#endif
void I_ShutdownTcpDriver(void) void I_ShutdownTcpDriver(void)
{ {
#ifndef NONET
SOCK_CloseSocket(); SOCK_CloseSocket();
CONS_Printf("I_ShutdownTcpDriver: "); CONS_Printf("I_ShutdownTcpDriver: ");
@ -1098,8 +1147,10 @@ void I_ShutdownTcpDriver(void)
#endif #endif
CONS_Printf("shut down\n"); CONS_Printf("shut down\n");
init_tcp_driver = false; init_tcp_driver = false;
#endif
} }
#ifndef NONET
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
{ {
SINT8 newnode = -1; SINT8 newnode = -1;
@ -1143,13 +1194,17 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
I_freeaddrinfo(ai); I_freeaddrinfo(ai);
return newnode; return newnode;
} }
#endif
static boolean SOCK_OpenSocket(void) static boolean SOCK_OpenSocket(void)
{ {
#ifndef NONET
size_t i;
memset(clientaddress, 0, sizeof (clientaddress)); memset(clientaddress, 0, sizeof (clientaddress));
nodeconnected[0] = true; // always connected to self nodeconnected[0] = true; // always connected to self
for (size_t i = 1; i < MAXNETNODES; i++) for (i = 1; i < MAXNETNODES; i++)
nodeconnected[i] = false; nodeconnected[i] = false;
nodeconnected[BROADCASTADDR] = true; nodeconnected[BROADCASTADDR] = true;
I_NetSend = SOCK_Send; I_NetSend = SOCK_Send;
@ -1167,12 +1222,18 @@ static boolean SOCK_OpenSocket(void)
// build the socket but close it first // build the socket but close it first
SOCK_CloseSocket(); SOCK_CloseSocket();
return UDP_Socket(); return UDP_Socket();
#else
return false;
#endif
} }
static boolean SOCK_Ban(INT32 node) static boolean SOCK_Ban(INT32 node)
{ {
if (node > MAXNETNODES) if (node > MAXNETNODES)
return false; return false;
#ifdef NONET
return false;
#else
if (numbans == MAXBANS) if (numbans == MAXBANS)
return false; return false;
@ -1191,10 +1252,16 @@ static boolean SOCK_Ban(INT32 node)
#endif #endif
numbans++; numbans++;
return true; return true;
#endif
} }
static boolean SOCK_SetBanAddress(const char *address, const char *mask) 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; struct my_addrinfo *ai, *runp, hints;
int gaie; int gaie;
@ -1239,6 +1306,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
I_freeaddrinfo(ai); I_freeaddrinfo(ai);
return true; return true;
#endif
} }
static void SOCK_ClearBans(void) static void SOCK_ClearBans(void)

View file

@ -17,7 +17,7 @@
#include "command.h" #include "command.h"
#include "doomtype.h" #include "doomtype.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "m_fixed.h" #include "m_fixed.h"
#include "i_system.h" #include "i_system.h"

View file

@ -27,11 +27,11 @@
#include "y_inter.h" #include "y_inter.h"
#include "hu_stuff.h" // HU_AddChatText #include "hu_stuff.h" // HU_AddChatText
#include "console.h" #include "console.h"
#include "netcode/d_netcmd.h" // IsPlayerAdmin #include "d_netcmd.h" // IsPlayerAdmin
#include "m_menu.h" // Player Setup menu color stuff #include "m_menu.h" // Player Setup menu color stuff
#include "m_misc.h" // M_MapNumber #include "m_misc.h" // M_MapNumber
#include "b_bot.h" // B_UpdateBotleader #include "b_bot.h" // B_UpdateBotleader
#include "netcode/d_clisrv.h" // CL_RemovePlayer #include "d_clisrv.h" // CL_RemovePlayer
#include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision #include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision
#include "lua_script.h" #include "lua_script.h"

View file

@ -16,7 +16,6 @@
#include "g_game.h" #include "g_game.h"
#include "byteptr.h" #include "byteptr.h"
#include "z_zone.h" #include "z_zone.h"
#include "netcode/net_command.h"
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"

View file

@ -25,7 +25,7 @@
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "m_perfstats.h" #include "m_perfstats.h"
#include "netcode/d_netcmd.h" // for cv_perfstats #include "d_netcmd.h" // for cv_perfstats
#include "i_system.h" // I_GetPreciseTime #include "i_system.h" // I_GetPreciseTime
/* ========================================================================= /* =========================================================================

View file

@ -28,7 +28,7 @@
#include "p_slopes.h" // for P_SlopeById and slopelist #include "p_slopes.h" // for P_SlopeById and slopelist
#include "p_polyobj.h" // polyobj_t, PolyObjects #include "p_polyobj.h" // polyobj_t, PolyObjects
#ifdef LUA_ALLOW_BYTECODE #ifdef LUA_ALLOW_BYTECODE
#include "netcode/d_netfil.h" // for LUA_DumpFile #include "d_netfil.h" // for LUA_DumpFile
#endif #endif
#include "lua_script.h" #include "lua_script.h"

View file

@ -19,7 +19,7 @@
#include "r_local.h" #include "r_local.h"
#include "p_local.h" #include "p_local.h"
#include "p_setup.h" #include "p_setup.h"
#include "netcode/d_net.h" #include "d_net.h"
#include "m_cheat.h" #include "m_cheat.h"
#include "m_menu.h" #include "m_menu.h"

View file

@ -20,7 +20,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "d_main.h" #include "d_main.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "console.h" #include "console.h"
#include "r_fps.h" #include "r_fps.h"
#include "r_local.h" #include "r_local.h"
@ -55,10 +55,8 @@
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
#endif #endif
#include "netcode/d_net.h" #include "d_net.h"
#include "netcode/mserv.h" #include "mserv.h"
#include "netcode/server_connection.h"
#include "netcode/client_connection.h"
#include "m_misc.h" #include "m_misc.h"
#include "m_anigif.h" #include "m_anigif.h"
#include "byteptr.h" #include "byteptr.h"
@ -149,7 +147,9 @@ static struct
INT32 index; INT32 index;
} gamepadInfo[MAX_CONNECTED_GAMEPADS + 1]; } gamepadInfo[MAX_CONNECTED_GAMEPADS + 1];
#ifndef NONET
static UINT32 serverlistpage; static UINT32 serverlistpage;
#endif
static UINT8 numsaves = 0; static UINT8 numsaves = 0;
static saveinfo_t* savegameinfo = NULL; // Extra info about the save games. static saveinfo_t* savegameinfo = NULL; // Extra info about the save games.
@ -189,8 +189,10 @@ static void M_GoBack(INT32 choice);
static void M_StopMessage(INT32 choice); static void M_StopMessage(INT32 choice);
static boolean stopstopmessage = false; static boolean stopstopmessage = false;
#ifndef NONET
static void M_HandleServerPage(INT32 choice); static void M_HandleServerPage(INT32 choice);
static void M_RoomMenu(INT32 choice); static void M_RoomMenu(INT32 choice);
#endif
// Prototyping is fun, innit? // Prototyping is fun, innit?
// ========================================================================== // ==========================================================================
@ -292,6 +294,7 @@ static void M_SetupMultiPlayer2(INT32 choice);
static void M_StartSplitServerMenu(INT32 choice); static void M_StartSplitServerMenu(INT32 choice);
static void M_StartServer(INT32 choice); static void M_StartServer(INT32 choice);
static void M_ServerOptions(INT32 choice); static void M_ServerOptions(INT32 choice);
#ifndef NONET
static void M_StartServerMenu(INT32 choice); static void M_StartServerMenu(INT32 choice);
static void M_ConnectMenu(INT32 choice); static void M_ConnectMenu(INT32 choice);
static void M_ConnectMenuModChecks(INT32 choice); static void M_ConnectMenuModChecks(INT32 choice);
@ -299,6 +302,7 @@ static void M_Refresh(INT32 choice);
static void M_Connect(INT32 choice); static void M_Connect(INT32 choice);
static void M_ChooseRoom(INT32 choice); static void M_ChooseRoom(INT32 choice);
menu_t MP_MainDef; menu_t MP_MainDef;
#endif
// Options // Options
// Split into multiple parts due to size // Split into multiple parts due to size
@ -377,9 +381,11 @@ static void M_DrawVideoMode(void);
static void M_DrawColorMenu(void); static void M_DrawColorMenu(void);
static void M_DrawScreenshotMenu(void); static void M_DrawScreenshotMenu(void);
static void M_DrawMonitorToggles(void); static void M_DrawMonitorToggles(void);
#ifndef NONET
static void M_DrawConnectMenu(void); static void M_DrawConnectMenu(void);
static void M_DrawMPMainMenu(void); static void M_DrawMPMainMenu(void);
static void M_DrawRoomMenu(void); static void M_DrawRoomMenu(void);
#endif
static void M_DrawGamepadList(void); static void M_DrawGamepadList(void);
static void M_DrawSetupMultiPlayerMenu(void); static void M_DrawSetupMultiPlayerMenu(void);
@ -393,8 +399,10 @@ static void M_HandleImageDef(INT32 choice);
static void M_HandleLoadSave(INT32 choice); static void M_HandleLoadSave(INT32 choice);
static void M_HandleLevelStats(INT32 choice); static void M_HandleLevelStats(INT32 choice);
static void M_HandlePlaystyleMenu(INT32 choice); static void M_HandlePlaystyleMenu(INT32 choice);
#ifndef NONET
static boolean M_CancelConnect(void); static boolean M_CancelConnect(void);
static void M_HandleConnectIP(INT32 choice); static void M_HandleConnectIP(INT32 choice);
#endif
static void M_HandleSetupMultiPlayer(INT32 choice); static void M_HandleSetupMultiPlayer(INT32 choice);
static void M_HandleVideoMode(INT32 choice); static void M_HandleVideoMode(INT32 choice);
@ -493,7 +501,11 @@ consvar_t cv_dummyloadless = CVAR_INIT ("dummyloadless", "In-game", CV_HIDEN, lo
static menuitem_t MainMenu[] = static menuitem_t MainMenu[] =
{ {
{IT_STRING|IT_CALL, NULL, "1 Player", M_SinglePlayerMenu, 76}, {IT_STRING|IT_CALL, NULL, "1 Player", M_SinglePlayerMenu, 76},
#ifndef NONET
{IT_STRING|IT_SUBMENU, NULL, "Multiplayer", &MP_MainDef, 84}, {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_STRING|IT_CALL, NULL, "Extras", M_SecretsMenu, 92},
{IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 100}, {IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 100},
{IT_STRING|IT_CALL, NULL, "Options", M_Options, 108}, {IT_STRING|IT_CALL, NULL, "Options", M_Options, 108},
@ -944,10 +956,16 @@ static menuitem_t SP_PlayerMenu[] =
static menuitem_t MP_SplitServerMenu[] = static menuitem_t MP_SplitServerMenu[] =
{ {
{IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_MapChange, 100}, {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_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
}; };
#ifndef NONET
static menuitem_t MP_MainMenu[] = static menuitem_t MP_MainMenu[] =
{ {
{IT_HEADER, NULL, "Join a game", NULL, 0}, {IT_HEADER, NULL, "Join a game", NULL, 0},
@ -1034,6 +1052,8 @@ menuitem_t MP_RoomMenu[] =
{IT_DISABLED, NULL, "", M_ChooseRoom, 162}, {IT_DISABLED, NULL, "", M_ChooseRoom, 162},
}; };
#endif
static menuitem_t MP_PlayerSetupMenu[] = static menuitem_t MP_PlayerSetupMenu[] =
{ {
{IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name
@ -1601,12 +1621,14 @@ enum
static menuitem_t OP_ServerOptionsMenu[] = static menuitem_t OP_ServerOptionsMenu[] =
{ {
{IT_HEADER, NULL, "General", NULL, 0}, {IT_HEADER, NULL, "General", NULL, 0},
#ifndef NONET
{IT_STRING | IT_CVAR | IT_CV_STRING, {IT_STRING | IT_CVAR | IT_CV_STRING,
NULL, "Server name", &cv_servername, 7}, NULL, "Server name", &cv_servername, 7},
{IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21}, {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21},
{IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26}, {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, "Allow players to join", &cv_allownewplayer, 31},
{IT_STRING | IT_CVAR, NULL, "Minutes for reconnecting", &cv_rejointimeout, 36}, {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, "Map progression", &cv_advancemap, 41},
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46}, {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46},
@ -1645,6 +1667,7 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216}, {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216},
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221}, {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221},
#ifndef NONET
{IT_HEADER, NULL, "Advanced", NULL, 230}, {IT_HEADER, NULL, "Advanced", NULL, 230},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236}, {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236},
@ -1652,6 +1675,7 @@ static menuitem_t OP_ServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256}, {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256},
{IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261}, {IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261},
#endif
}; };
static menuitem_t OP_MonitorToggleMenu[] = static menuitem_t OP_MonitorToggleMenu[] =
@ -1961,7 +1985,11 @@ menu_t MP_SplitServerDef =
MTREE2(MN_MP_MAIN, MN_MP_SPLITSCREEN), MTREE2(MN_MP_MAIN, MN_MP_SPLITSCREEN),
"M_MULTI", "M_MULTI",
sizeof (MP_SplitServerMenu)/sizeof (menuitem_t), sizeof (MP_SplitServerMenu)/sizeof (menuitem_t),
#ifndef NONET
&MP_MainDef, &MP_MainDef,
#else
&MainDef,
#endif
MP_SplitServerMenu, MP_SplitServerMenu,
M_DrawServerMenu, M_DrawServerMenu,
27, 30 - 50, 27, 30 - 50,
@ -1969,6 +1997,8 @@ menu_t MP_SplitServerDef =
NULL NULL
}; };
#ifndef NONET
menu_t MP_MainDef = menu_t MP_MainDef =
{ {
MN_MP_MAIN, MN_MP_MAIN,
@ -2020,10 +2050,15 @@ menu_t MP_RoomDef =
0, 0,
NULL NULL
}; };
#endif
menu_t MP_PlayerSetupDef = menu_t MP_PlayerSetupDef =
{ {
#ifdef NONET
MTREE2(MN_MP_MAIN, MN_MP_PLAYERSETUP),
#else
MTREE3(MN_MP_MAIN, MN_MP_SPLITSCREEN, MN_MP_PLAYERSETUP), MTREE3(MN_MP_MAIN, MN_MP_SPLITSCREEN, MN_MP_PLAYERSETUP),
#endif
"M_SPLAYR", "M_SPLAYR",
sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t), sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t),
&MainDef, // doesn't matter &MainDef, // doesn't matter
@ -3973,7 +4008,9 @@ void M_Init(void)
OP_GamepadSetMenu[i].itemaction = M_AssignGamepad; OP_GamepadSetMenu[i].itemaction = M_AssignGamepad;
} }
#ifndef NONET
CV_RegisterVar(&cv_serversort); CV_RegisterVar(&cv_serversort);
#endif
} }
void M_InitCharacterTables(void) void M_InitCharacterTables(void)
@ -10986,6 +11023,7 @@ static void M_EndGame(INT32 choice)
#define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT) #define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT)
#ifndef NONET
static UINT32 localservercount; static UINT32 localservercount;
static void M_HandleServerPage(INT32 choice) static void M_HandleServerPage(INT32 choice)
@ -11257,9 +11295,11 @@ static int ServerListEntryComparator_modified(const void *entry1, const void *en
// Default to strcmp. // Default to strcmp.
return strcmp(sa->info.servername, sb->info.servername); return strcmp(sa->info.servername, sb->info.servername);
} }
#endif
void M_SortServerList(void) void M_SortServerList(void)
{ {
#ifndef NONET
switch(cv_serversort.value) switch(cv_serversort.value)
{ {
case 0: // Ping. case 0: // Ping.
@ -11281,8 +11321,10 @@ void M_SortServerList(void)
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename);
break; break;
} }
#endif
} }
#ifndef NONET
#ifdef UPDATE_ALERT #ifdef UPDATE_ALERT
static boolean M_CheckMODVersion(int id) static boolean M_CheckMODVersion(int id)
{ {
@ -11481,6 +11523,7 @@ static void M_ChooseRoom(INT32 choice)
if (currentMenu == &MP_ConnectDef) if (currentMenu == &MP_ConnectDef)
M_Refresh(0); M_Refresh(0);
} }
#endif //NONET
//=========================================================================== //===========================================================================
// Start Server Menu // Start Server Menu
@ -11528,6 +11571,7 @@ static void M_DrawServerMenu(void)
{ {
M_DrawGenericMenu(); M_DrawGenericMenu();
#ifndef NONET
// Room name // Room name
if (currentMenu == &MP_ServerDef) if (currentMenu == &MP_ServerDef)
{ {
@ -11539,10 +11583,15 @@ static void M_DrawServerMenu(void)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
V_YELLOWMAP, room_list[menuRoomIndex].name); V_YELLOWMAP, room_list[menuRoomIndex].name);
} }
#endif
if (cv_nextmap.value) if (cv_nextmap.value)
{ {
#ifndef NONET
#define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey #define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey
#else
#define imgheight 100
#endif
patch_t *PictureOfLevel; patch_t *PictureOfLevel;
lumpnum_t lumpnum; lumpnum_t lumpnum;
char headerstr[40]; char headerstr[40];
@ -11594,6 +11643,7 @@ static void M_ServerOptions(INT32 choice)
{ {
(void)choice; (void)choice;
#ifndef NONET
if ((splitscreen && !netgame) || currentMenu == &MP_SplitServerDef) if ((splitscreen && !netgame) || currentMenu == &MP_SplitServerDef)
{ {
OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name
@ -11614,6 +11664,7 @@ static void M_ServerOptions(INT32 choice)
OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR;
OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR;
} }
#endif
/* Disable fading because of different menu head. */ /* Disable fading because of different menu head. */
if (currentMenu == &OP_MainDef)/* from Options menu */ if (currentMenu == &OP_MainDef)/* from Options menu */
@ -11625,6 +11676,7 @@ static void M_ServerOptions(INT32 choice)
M_SetupNextMenu(&OP_ServerOptionsDef); M_SetupNextMenu(&OP_ServerOptionsDef);
} }
#ifndef NONET
static void M_StartServerMenu(INT32 choice) static void M_StartServerMenu(INT32 choice)
{ {
(void)choice; (void)choice;
@ -11881,6 +11933,7 @@ static void M_HandleConnectIP(INT32 choice)
M_ClearMenus(true); M_ClearMenus(true);
} }
} }
#endif //!NONET
// ======================== // ========================
// MULTIPLAYER PLAYER SETUP // MULTIPLAYER PLAYER SETUP

View file

@ -20,7 +20,7 @@
#include "command.h" #include "command.h"
#include "f_finale.h" // for ttmode_enum #include "f_finale.h" // for ttmode_enum
#include "i_threads.h" #include "i_threads.h"
#include "netcode/mserv.h" #include "mserv.h"
#include "r_things.h" // for SKINNAMESIZE #include "r_things.h" // for SKINNAMESIZE
// Compatibility with old-style named NiGHTS replay files. // Compatibility with old-style named NiGHTS replay files.
@ -74,7 +74,7 @@ typedef enum
MN_MP_SERVER, MN_MP_SERVER,
MN_MP_CONNECT, MN_MP_CONNECT,
MN_MP_ROOM, MN_MP_ROOM,
MN_MP_PLAYERSETUP, MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
MN_MP_SERVER_OPTIONS, MN_MP_SERVER_OPTIONS,
// Options // Options

View file

@ -12,7 +12,7 @@
#include "m_perfstats.h" #include "m_perfstats.h"
#include "v_video.h" #include "v_video.h"
#include "i_video.h" #include "i_video.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "r_main.h" #include "r_main.h"
#include "i_system.h" #include "i_system.h"
#include "z_zone.h" #include "z_zone.h"

View file

@ -15,14 +15,13 @@
#include <time.h> #include <time.h>
#endif #endif
#include "../doomstat.h" #include "doomstat.h"
#include "../doomdef.h" #include "doomdef.h"
#include "../command.h" #include "command.h"
#include "../i_threads.h" #include "i_threads.h"
#include "mserv.h" #include "mserv.h"
#include "client_connection.h" #include "m_menu.h"
#include "../m_menu.h" #include "z_zone.h"
#include "../z_zone.h"
#ifdef MASTERSERVER #ifdef MASTERSERVER
@ -46,7 +45,9 @@ static I_cond MSCond;
# define Unlock_state() # define Unlock_state()
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/
#ifndef NONET
static void Command_Listserv_f(void); static void Command_Listserv_f(void);
#endif
#endif/*MASTERSERVER*/ #endif/*MASTERSERVER*/
@ -88,6 +89,7 @@ msg_rooms_t room_list[NUM_LIST_ROOMS+1]; // +1 for easy test
*/ */
void AddMServCommands(void) void AddMServCommands(void)
{ {
#ifndef NONET
CV_RegisterVar(&cv_masterserver); CV_RegisterVar(&cv_masterserver);
CV_RegisterVar(&cv_masterserver_update_rate); CV_RegisterVar(&cv_masterserver_update_rate);
CV_RegisterVar(&cv_masterserver_timeout); CV_RegisterVar(&cv_masterserver_timeout);
@ -98,6 +100,7 @@ void AddMServCommands(void)
COM_AddCommand("listserv", Command_Listserv_f); 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("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident
#endif #endif
#endif
} }
#ifdef MASTERSERVER #ifdef MASTERSERVER
@ -186,6 +189,7 @@ void GetMODVersion_Console(void)
} }
#endif #endif
#ifndef NONET
/** Gets a list of game servers. Called from console. /** Gets a list of game servers. Called from console.
*/ */
static void Command_Listserv_f(void) static void Command_Listserv_f(void)
@ -196,6 +200,7 @@ static void Command_Listserv_f(void)
HMS_list_servers(); HMS_list_servers();
} }
} }
#endif
static void static void
Finish_registration (void) Finish_registration (void)

View file

@ -14,7 +14,7 @@
#ifndef _MSERV_H_ #ifndef _MSERV_H_
#define _MSERV_H_ #define _MSERV_H_
#include "../i_threads.h" #include "i_threads.h"
// lowered from 32 due to menu changes // lowered from 32 due to menu changes
#define NUM_LIST_ROOMS 16 #define NUM_LIST_ROOMS 16

View file

@ -1,13 +0,0 @@
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

File diff suppressed because it is too large Load diff

View file

@ -1,61 +0,0 @@
// 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 PT_ServerInfo(SINT8 node);
void PT_MoreFilesNeeded(SINT8 node);
void PT_ServerRefuse(SINT8 node);
void PT_ServerCFG(SINT8 node);
#endif

View file

@ -1,484 +0,0 @@
// 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 <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
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;
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 (size_t 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;
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 (size_t 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 <playername/playernum> <reason>: 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 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 (size_t 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 <ip> <reason>: 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 <playername/playernum> <reason>: 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 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 (size_t 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 <serveraddress> (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)
{
for (INT32 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)
{
size_t maxlen = 0;
const char *address;
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
const size_t plen = strlen(player_names[i]);
if (playeringame[i] && plen > maxlen)
maxlen = plen;
}
for (INT32 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");
}
}
}

View file

@ -1,33 +0,0 @@
// 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

File diff suppressed because it is too large Load diff

View file

@ -1,131 +0,0 @@
// 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 d_clisrv.h
/// \brief high level networking stuff
#ifndef __D_CLISRV__
#define __D_CLISRV__
#include "protocol.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 "mserv.h"
#define CLIENTBACKUPTICS 32
#ifdef PACKETDROP
void Command_Drop(void);
void Command_Droprate(void);
#endif
#ifdef _DEBUG
void Command_Numnodes(void);
#endif
extern INT32 mapchangepending;
// Points inside doomcom
extern doomdata_t *netbuffer;
#define BASEPACKETSIZE offsetof(doomdata_t, u)
#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
typedef enum
{
KR_KICK = 1, //Kicked by server
KR_PINGLIMIT = 2, //Broke Ping Limit
KR_SYNCH = 3, //Synch Failure
KR_TIMEOUT = 4, //Connection Timeout
KR_BAN = 5, //Banned by server
KR_LEAVE = 6, //Quit the game
} kickreason_t;
/* the max number of name changes in some time period */
#define MAXNAMECHANGES (5)
#define NAMECHANGERATE (60*TICRATE)
extern boolean server;
extern boolean serverrunning;
#define client (!server)
extern boolean dedicated; // For dedicated server
extern UINT16 software_MAXPACKETLENGTH;
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;
extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed;
// Used in d_net, the only dependence
void D_ClientServerInit(void);
// Create any new ticcmds and broadcast to other players.
void NetUpdate(void);
void GetPackets(void);
void ResetNode(INT32 node);
INT16 Consistancy(void);
void SV_StartSinglePlayerServer(void);
void SV_SpawnServer(void);
void SV_StopServer(void);
void SV_ResetServer(void);
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_HandleTimeout(void);
// Is there a game running
boolean Playing(void);
// Broadcasts special packets to other players
// to notify of game exit
void D_QuitNetGame(void);
//? How many ticks to run?
boolean TryRunTics(tic_t realtic);
// extra data for lmps
// these functions scare me. they contain magic.
/*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum);
void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum);*/
// 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);
extern char motd[254], server_context[8];
extern UINT8 playernode[MAXPLAYERS];
INT32 D_NumPlayers(void);
tic_t GetLag(INT32 node);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset;
extern boolean hu_stopped;
#endif

View file

@ -1,336 +0,0 @@
// 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)
{
for (INT32 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)
{
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
LUA_InvalidatePlayer(&players[i]);
sprintf(player_names[i], "Player %d", i + 1);
}
CL_LoadReceivedSavegame(true);
neededtic = max(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 <playername/playernum>: 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;
}

View file

@ -1,31 +0,0 @@
// 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

View file

@ -1,386 +0,0 @@
// 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 "gamestate.h"
#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"
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)
{
// Remove this tic from the list.
*tctprev = textcmdtic->next;
// Free all players.
for (INT32 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)
{
for (INT32 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)
{
size_t total = 1; // num of textcmds in the tic (ntextcmd byte)
for (INT32 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 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;
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)
{
// 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];
if (!(server && cv_rejointimeout.value))
msg &= ~KICK_MSG_KEEP_BODY;
buf[0] = playernum;
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);
}

View file

@ -1,66 +0,0 @@
// 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 SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf);
void CL_CopyNetCommandsFromServerPacket(tic_t tic);
void CL_SendNetCommands(void);
void SendKick(UINT8 playernum, UINT8 msg);
void SendKicksForNode(SINT8 node, UINT8 msg);
#endif

View file

@ -1,507 +0,0 @@
// 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 "net_command.h"
#include "gamestate.h"
#include "../byteptr.h"
#include "../g_game.h"
#include "../g_state.h"
#include "../p_setup.h"
#include "../p_tick.h"
#include "../command.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];
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];
const char *nodeaddress;
char *port;
// 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 (INT32 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)
{
netbuffer->packettype = PT_PLAYERINFO;
for (UINT8 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_pak) * 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 PT_ClientJoin(SINT8 node)
{
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
INT32 numplayers = netbuffer->u.clientcfg.localplayers;
INT32 rejoinernum;
// Ignore duplicate packets
if (client || netnodes[node].ingame)
return;
rejoinernum = FindRejoinerNum(node);
const char *refuse = GetRefuseMessage(node, rejoinernum);
if (refuse)
{
SV_SendRefuse(node, refuse);
return;
}
for (INT32 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;
}
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 (INT32 i = 0; i < numplayers; i++)
SV_AddPlayer(node, names[i]);
joindelay += cv_joindelay.value * TICRATE;
}
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);
}

View file

@ -1,30 +0,0 @@
// 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 "../command.h"
#include "../doomdef.h"
#include "../doomtype.h"
void PT_ClientJoin(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 consvar_t cv_showjoinaddress, cv_allownewplayer, cv_maxplayers, cv_joindelay, cv_rejointimeout;
#endif

View file

@ -1,454 +0,0 @@
// 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 "gamestate.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; // Smallest netnode.tic
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)
{
D_FreeTextcmd(tic);
for (INT32 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)
{
memset(&localcmds, 0, sizeof(ticcmd_t));
memset(&localcmds2, 0, sizeof(ticcmd_t));
// Reset the net command list
for (INT32 i = 0; i < TEXTCMD_HASH_SIZE; i++)
while (textcmds[i])
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 nodenum, INT32 netconsole)
{
netnode_t *node = &netnodes[nodenum];
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, nodenum);
realend = ExpandTics(netbuffer->u.clientpak.resendfrom, nodenum);
if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
|| node->supposedtic < realend)
{
node->supposedtic = realend;
}
// Discard out of order packet
if (node->tic > realend)
{
DEBFILE(va("out of order ticcmd discarded nettics = %u\n", node->tic));
return;
}
// 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)
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;
// Copy ticcmd
G_MoveTiccmd(&netcmds[maketic%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],
&netbuffer->u.client2pak.cmd2, 1);
CheckTiccmdHacks(netconsole);
CheckConsistancy(nodenum, realstart);
}
void PT_ServerTics(SINT8 node, INT32 netconsole)
{
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;
realend = min(realend, gametic + CLIENTBACKUPTICS);
cl_packetmissed = realstart > neededtic;
if (realstart <= neededtic && realend > neededtic)
{
UINT8 *pak = (UINT8 *)&netbuffer->u.serverpak.cmds;
for (tic_t 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));
CL_CopyNetCommandsFromServerPacket(i);
}
neededtic = realend;
}
else
{
DEBFILE(va("frame not in bound: %u\n", 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)
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;
for (tic_t 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 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)
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;
}
// Sends the server packet
// Sends tic/net commands from firstticstosend to maketic-1
void SV_SendTics(void)
{
tic_t realfirsttic, lasttictosend;
// 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)
{
netnode_t *node = netnodes[n];
// assert node->supposedtic>=node->tic
realfirsttic = node->supposedtic;
lasttictosend = min(maketic, node->tic + CLIENTBACKUPTICS);
if (realfirsttic >= lasttictosend)
{
// 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 tics are Ok
continue;
DEBFILE(va("Sent %d anyway\n", realfirsttic));
}
realfirsttic = max(realfirsttic, firstticstosend);
lasttictosend = realfirsttic + SV_CalculateNumTicsForPacket(n, realfirsttic, lasttictosend);
// 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);
// 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));
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 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
node->supposedtic = lasttictosend;
node->supposedtic = max(node->supposedtic, node->tic);
}
// node 0 is me!
netnodes[0].supposedtic = maketic;
}
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)
{
for (INT32 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 tics have been processed, make the next
maketic++;
}

View file

@ -1,44 +0,0 @@
// 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 nodenum, 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

View file

@ -17,7 +17,7 @@
#include "r_main.h" #include "r_main.h"
#include "s_sound.h" #include "s_sound.h"
#include "z_zone.h" #include "z_zone.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
// ========================================================================== // ==========================================================================
// CEILINGS // CEILINGS

View file

@ -11,7 +11,7 @@
#include "p_haptic.h" #include "p_haptic.h"
#include "g_game.h" #include "g_game.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "i_gamepad.h" #include "i_gamepad.h"
#include "doomstat.h" #include "doomstat.h"

View file

@ -30,7 +30,6 @@
#include "m_misc.h" #include "m_misc.h"
#include "v_video.h" // video flags for CEchos #include "v_video.h" // video flags for CEchos
#include "f_finale.h" #include "f_finale.h"
#include "netcode/net_command.h"
// CTF player names // CTF player names
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""

View file

@ -17,7 +17,7 @@
#include "r_state.h" #include "r_state.h"
#include "z_zone.h" #include "z_zone.h"
#include "m_random.h" #include "m_random.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
/** Removes any active lighting effects in a sector. /** Removes any active lighting effects in a sector.
* *

View file

@ -36,7 +36,6 @@
#include "p_slopes.h" #include "p_slopes.h"
#include "f_finale.h" #include "f_finale.h"
#include "m_cond.h" #include "m_cond.h"
#include "netcode/net_command.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; 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); consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);

View file

@ -87,8 +87,6 @@
#include "taglist.h" #include "taglist.h"
#include "netcode/net_command.h"
// //
// Map MD5, calculated on level load. // Map MD5, calculated on level load.
// Sent to clients in PT_SERVERINFO. // Sent to clients in PT_SERVERINFO.

View file

@ -26,8 +26,6 @@
#include "r_main.h" #include "r_main.h"
#include "r_fps.h" #include "r_fps.h"
#include "i_video.h" // rendermode #include "i_video.h" // rendermode
#include "netcode/net_command.h"
#include "netcode/server_connection.h"
// Object place // Object place
#include "m_cheat.h" #include "m_cheat.h"

View file

@ -18,8 +18,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "i_system.h" #include "i_system.h"
#include "d_event.h" #include "d_event.h"
#include "netcode/d_net.h" #include "d_net.h"
#include "netcode/net_command.h"
#include "g_game.h" #include "g_game.h"
#include "p_local.h" #include "p_local.h"
#include "r_fps.h" #include "r_fps.h"

View file

@ -20,7 +20,7 @@
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
#include "netcode/d_netcmd.h" #include "d_netcmd.h"
#include "m_misc.h" #include "m_misc.h"
#include "p_local.h" // Camera... #include "p_local.h" // Camera...
#include "p_slopes.h" #include "p_slopes.h"

View file

@ -34,7 +34,7 @@
#include "p_tick.h" #include "p_tick.h"
#include "p_local.h" #include "p_local.h"
#include "p_slopes.h" #include "p_slopes.h"
#include "netcode/d_netfil.h" // blargh. for nameonly(). #include "d_netfil.h" // blargh. for nameonly().
#include "m_cheat.h" // objectplace #include "m_cheat.h" // objectplace
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_md2.h" #include "hardware/hw_md2.h"

View file

@ -27,7 +27,7 @@
#include "hu_stuff.h" #include "hu_stuff.h"
#include "z_zone.h" #include "z_zone.h"
#include "d_main.h" #include "d_main.h"
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#include "f_finale.h" #include "f_finale.h"
#include "y_inter.h" // usebuffer #include "y_inter.h" // usebuffer
#include "i_sound.h" // closed captions #include "i_sound.h" // closed captions

View file

@ -15,7 +15,7 @@
#include "../i_system.h" #include "../i_system.h"
#include "../doomdef.h" #include "../doomdef.h"
#include "../d_main.h" #include "../d_main.h"
#include "../netcode/d_netcmd.h" #include "../d_netcmd.h"
#include "../g_game.h" #include "../g_game.h"
#include "../m_argv.h" #include "../m_argv.h"
#include "../m_menu.h" #include "../m_menu.h"

View file

@ -21,16 +21,16 @@
#include "../i_system.h" #include "../i_system.h"
#include "../d_event.h" #include "../d_event.h"
#include "../netcode/d_net.h" #include "../d_net.h"
#include "../m_argv.h" #include "../m_argv.h"
#include "../doomstat.h" #include "../doomstat.h"
#include "../netcode/i_net.h" #include "../i_net.h"
#include "../z_zone.h" #include "../z_zone.h"
#include "../netcode/i_tcp.h" #include "../i_tcp.h"
#ifdef HAVE_SDL #ifdef HAVE_SDL

View file

@ -188,8 +188,7 @@ static char returnWadPath[256];
#include "../i_gamepad.h" #include "../i_gamepad.h"
#include "../i_threads.h" #include "../i_threads.h"
#include "../screen.h" //vid.WndParent #include "../screen.h" //vid.WndParent
#include "../netcode/d_net.h" #include "../d_net.h"
#include "../netcode/commands.h"
#include "../g_game.h" #include "../g_game.h"
#include "../filesrch.h" #include "../filesrch.h"
#include "endtxt.h" #include "endtxt.h"
@ -208,7 +207,7 @@ static char returnWadPath[256];
#if !defined(NOMUMBLE) && defined(HAVE_MUMBLE) #if !defined(NOMUMBLE) && defined(HAVE_MUMBLE)
// Mumble context string // Mumble context string
#include "../netcode/d_clisrv.h" #include "../d_clisrv.h"
#include "../byteptr.h" #include "../byteptr.h"
#endif #endif
@ -1593,7 +1592,9 @@ void I_Quit(void)
SDLforceUngrabMouse(); SDLforceUngrabMouse();
quiting = SDL_FALSE; quiting = SDL_FALSE;
M_SaveConfig(NULL); //save game config, cvars.. M_SaveConfig(NULL); //save game config, cvars..
#ifndef NONET
D_SaveBan(); // save the ban list D_SaveBan(); // save the ban list
#endif
G_SaveGameData(); // Tails 12-08-2002 G_SaveGameData(); // Tails 12-08-2002
//added:16-02-98: when recording a demo, should exit using 'q' key, //added:16-02-98: when recording a demo, should exit using 'q' key,
// but sometimes we forget and use 'F10'.. so save here too. // but sometimes we forget and use 'F10'.. so save here too.
@ -1708,7 +1709,9 @@ void I_Error(const char *error, ...)
// --- // ---
M_SaveConfig(NULL); // save game config, cvars.. M_SaveConfig(NULL); // save game config, cvars..
#ifndef NONET
D_SaveBan(); // save the ban list D_SaveBan(); // save the ban list
#endif
G_SaveGameData(); // Tails 12-08-2002 G_SaveGameData(); // Tails 12-08-2002
// Shutdown. Here might be other errors. // Shutdown. Here might be other errors.

View file

@ -21,7 +21,7 @@
#include "SDL_ttf.h" #include "SDL_ttf.h"
#include "../doomdef.h" #include "../doomdef.h"
#include "../doomstat.h" #include "../doomstat.h"
#include "../netcode/d_netfil.h" #include "../d_netfil.h"
#include "../filesrch.h" #include "../filesrch.h"
#include "i_ttf.h" #include "i_ttf.h"

View file

@ -1,535 +0,0 @@
// 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 SPEED 5
#define NUM_BLOCKS_X 20
#define NUM_BLOCKS_Y 10
#define BLOCK_SIZE 12
#define BORDER_SIZE 12
#define MAP_WIDTH (NUM_BLOCKS_X * BLOCK_SIZE)
#define MAP_HEIGHT (NUM_BLOCKS_Y * BLOCK_SIZE)
#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 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
{
boolean paused;
boolean pausepressed;
tic_t time;
tic_t nextupdate;
boolean gameover;
UINT8 background;
UINT16 snakelength;
enum bonustype_s snakebonus;
tic_t snakebonustime;
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 bonustype_s bonustype;
UINT8 bonusx;
UINT8 bonusy;
} snake_t;
static const char *bonuspatches[] = {
NULL,
"DL_SLOW",
"TVSSC0",
"TVIVC0",
"TVARC0",
"DL_SCISSORS",
"TVRCC0",
"TVEGC0",
};
static const char *backgrounds[] = {
"RVPUMICF",
"FRSTRCKF",
"TAR",
"MMFLRB4",
"RVDARKF1",
"RVZWALF1",
"RVZWALF4",
"RVZWALF5",
"RVZGRS02",
"RVZGRS04",
};
static void Initialise(snake_t *snake)
{
snake->paused = false;
snake->pausepressed = false;
snake->time = 0;
snake->nextupdate = SPEED;
snake->gameover = false;
snake->background = M_RandomKey(sizeof(backgrounds) / sizeof(*backgrounds));
snake->snakelength = 1;
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(NUM_BLOCKS_X);
snake->appley = M_RandomKey(NUM_BLOCKS_Y);
snake->bonustype = BONUS_NONE;
}
static UINT8 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 FindFreeSlot(snake_t *snake, UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady)
{
UINT8 x, y;
UINT16 i;
do
{
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 != 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));
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]))
{
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 = BONUS_NONE;
}
snake->nextupdate--;
if (snake->nextupdate)
return;
if (snake->snakebonus == BONUS_SLOW)
snake->nextupdate = SPEED * 2;
else if (snake->snakebonus == BONUS_FAST)
snake->nextupdate = SPEED * 2 / 3;
else
snake->nextupdate = 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 < 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 < NUM_BLOCKS_Y - 1)
y++;
else
snake->gameover = true;
break;
}
// Check collision with snake
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 == BONUS_SCISSORS)
{
snake->snakebonus = 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 < NUM_BLOCKS_X * 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
FindFreeSlot(snake, &snake->applex, &snake->appley, x, y);
// Spawn new bonus
if (!(snake->snakelength % 5))
{
do
{
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));
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 != BONUS_NONE && x == snake->bonusx && y == snake->bonusy)
{
S_StartSound(NULL, sfx_ncchip);
switch (snake->bonustype)
{
case BONUS_SLOW:
snake->snakebonus = BONUS_SLOW;
snake->snakebonustime = 20 * TICRATE;
break;
case BONUS_FAST:
snake->snakebonus = BONUS_FAST;
snake->snakebonustime = 20 * TICRATE;
break;
case BONUS_GHOST:
snake->snakebonus = BONUS_GHOST;
snake->snakebonustime = 10 * TICRATE;
break;
case 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 BONUS_SCISSORS:
snake->snakebonus = BONUS_SCISSORS;
snake->snakebonustime = 60 * TICRATE;
break;
case 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] = GetOppositeDir(snake->snakedir[i2]);
snake->snakex [i2] = tmpx;
snake->snakey [i2] = tmpy;
snake->snakedir[i2] = GetOppositeDir(tmpdir);
}
snake->snakedir[0] = 0;
S_StartSound(NULL, sfx_gravch);
break;
default:
if (snake->snakebonus != BONUS_GHOST)
{
snake->gameover = true;
S_StartSound(NULL, sfx_lose);
}
}
snake->bonustype = BONUS_NONE;
}
}
void Snake_Draw(void *opaque)
{
INT16 i;
snake_t *snake = opaque;
// Background
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawFlatFill(
LEFT_X + BORDER_SIZE,
TOP_Y + BORDER_SIZE,
MAP_WIDTH,
MAP_HEIGHT,
W_GetNumForName(backgrounds[snake->background])
);
// Borders
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(
(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),
NULL
);
// Bonus
if (snake->bonustype != BONUS_NONE)
V_DrawFixedPatch(
(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(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(
(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 == BONUS_GHOST ? V_TRANSLUCENT : 0,
W_CachePatchLongName(patchname, PU_HUDGFX),
NULL
);
}
}
// Length
V_DrawString(RIGHT_X + 4, TOP_Y, V_MONOSPACE, va("%u", snake->snakelength));
// Bonus
if (snake->snakebonus != BONUS_NONE
&& (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2))
V_DrawFixedPatch(
(RIGHT_X + 10) * FRACUNIT,
(TOP_Y + 24) * FRACUNIT,
FRACUNIT / 2,
0,
W_CachePatchLongName(bonuspatches[snake->snakebonus], PU_HUDGFX),
NULL
);
}
void Snake_Free(void **opaque)
{
if (*opaque)
{
free(opaque);
*opaque = NULL;
}
}

View file

@ -1,20 +0,0 @@
// 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

View file

@ -51,8 +51,8 @@
#include "filesrch.h" #include "filesrch.h"
#include "d_main.h" #include "d_main.h"
#include "netcode/d_netfil.h" #include "d_netfil.h"
#include "netcode/d_clisrv.h" #include "d_clisrv.h"
#include "dehacked.h" #include "dehacked.h"
#include "r_defs.h" #include "r_defs.h"
#include "r_data.h" #include "r_data.h"

View file

@ -15,7 +15,7 @@
#include "f_finale.h" #include "f_finale.h"
#include "g_game.h" #include "g_game.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "netcode/i_net.h" #include "i_net.h"
#include "i_video.h" #include "i_video.h"
#include "p_tick.h" #include "p_tick.h"
#include "r_defs.h" #include "r_defs.h"