diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 335dde96f554bd8da39d88a452fa4a280320d5f5..ca33f1f7945eab8d6342ce3f958c599644ebd34b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -68,14 +68,6 @@ static boolean serverrunning = false; INT32 serverplayer = 0; char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) -// server specific vars -UINT8 playernode[MAXPLAYERS]; -UINT8 net_nodecount, net_playercount; - -SINT8 nodetoplayer[MAXNETNODES]; -SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) -UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen -boolean nodeingame[MAXNETNODES]; // set false as nodes leave game static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet static UINT8 nodewaiting[MAXNETNODES]; @@ -192,23 +184,6 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) listnetxcmd[id] = cmd_f; } -void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) -{ - // NET TODO -} - -// splitscreen player -void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) -{ - // NET TODO -} - -UINT8 GetFreeXCmdSize(void) -{ - // NET TODO - return -1; -} - // Frees all textcmd memory for the specified tic static void D_FreeTextcmd(void) { @@ -1727,15 +1702,6 @@ void D_QuitNetGame(void) // abort send/receive of files CloseNetFile(); - if (server) - { - // NET TODO: Send server shutdown packets to everyone. - } - else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]!=0) - { - // NET TODO: Send client quit packet to server. - } - D_CloseConnection(); adminplayer = -1; diff --git a/src/d_enet.c b/src/d_enet.c index 8bfdf22eb988ed0bd1fefaaca0b0ca8c7e7214f0..8e1fc79e9a0201eb3d0ffa554c4c102bcc1e6630 100644 --- a/src/d_enet.c +++ b/src/d_enet.c @@ -1,6 +1,30 @@ +#include <enet/enet.h> + #include "doomdef.h" #include "doomstat.h" #include "d_enet.h" +#include "z_zone.h" +#include "m_menu.h" + +UINT8 net_nodecount, net_playercount; +UINT8 playernode[MAXPLAYERS]; +SINT8 nodetoplayer[MAXNETNODES]; +SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) +UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen +boolean nodeingame[MAXNETNODES]; // set false as nodes leave game + +#define NETCHANNELS 4 + +#define DISCONNECT_SHUTDOWN 1 + +static ENetHost *ServerHost = NULL, + *ClientHost = NULL; +static ENetPeer *nodetopeer[MAXNETNODES]; +static UINT8 nodeleaving[MAXNETNODES]; + +typedef struct PeerData_s { + UINT8 node; +} PeerData_t; boolean Net_GetNetStat(void) { @@ -10,6 +34,70 @@ boolean Net_GetNetStat(void) void Net_AckTicker(void) { + ENetEvent e; + UINT8 i; + PeerData_t *pdata; + + while (enet_host_service(ClientHost, &e, 0) > 0) + switch (e.type) + { + case ENET_EVENT_TYPE_CONNECT: + break; + case ENET_EVENT_TYPE_DISCONNECT: + if (!server) + { + CL_Reset(); + D_StartTitle(); + if (e.data == DISCONNECT_SHUTDOWN) + M_StartMessage(M_GetText("Server shut down.\n\nPress ESC\n"), NULL, MM_NOTHING); + else + M_StartMessage(M_GetText("Disconnected from server.\n\nPress ESC\n"), NULL, MM_NOTHING); + } + break; + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(e.packet); + break; + default: + break; + } + while (enet_host_service(ServerHost, &e, 0) > 0) + switch (e.type) + { + case ENET_EVENT_TYPE_CONNECT: + for (i = 0; i < MAXNETNODES && nodetopeer[i]; i++) + ; + I_Assert(i < MAXNETNODES); // ENet should not be able to send connect events when nodes are full. + nodetopeer[i] = e.peer; + pdata = ZZ_Alloc(sizeof(*pdata)); + pdata->node = i; + e.peer->data = pdata; + break; + case ENET_EVENT_TYPE_DISCONNECT: + pdata = (PeerData_t *)e.peer->data; + if (!nodeleaving[pdata->node]) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = nodetoplayer[pdata->node]; + buf[1] = KICK_MSG_PLAYER_QUIT; + SendNetXCmd(XD_KICK, &buf, 2); + if (playerpernode[pdata->node] == 2) + { + buf[0] = nodetoplayer2[pdata->node]; + SendNetXCmd(XD_KICK, &buf, 2); + } + } + net_nodecount--; + nodeleaving[pdata->node] = false; + nodetopeer[pdata->node] = NULL; + Z_Free(pdata); + e.peer->data = NULL; + break; + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(e.packet); + break; + default: + break; + } } boolean Net_AllAckReceived(void) @@ -19,21 +107,89 @@ boolean Net_AllAckReceived(void) void D_SetDoomcom(void) { - //net_nodecount = net_playercount = 0; + net_nodecount = 0; + net_playercount = 0; } +// Initialize network. +// Returns true if the server is booting up right into a level according to startup args and whatnot. +// netgame is set to true before this is called if -server was passed. boolean D_CheckNetGame(void) { - multiplayer = false; - server = true; + if (enet_initialize()) + I_Error("Failed to initialize ENet.\n"); + if (netgame) + { + if (server) + { + ENetAddress address = { ENET_HOST_ANY, 5029 }; + ServerHost = enet_host_create(&address, MAXNETNODES, NETCHANNELS, 0, 0); + if (!ServerHost) + I_Error("ENet failed to open server host. (Check if the port is in use?)"); + } + if (!dedicated) + { + ClientHost = enet_host_create(NULL, 1, NETCHANNELS, 0, 0); + if (!ClientHost) + I_Error("ENet failed to initialize client host."); + } + } else + server = true; + multiplayer = netgame; D_ClientServerInit(); - return false; + return netgame; } void D_CloseConnection(void) { + ENetEvent e; + if (ServerHost) + { + UINT8 i; + // tell everyone to go away + for (i = 0; i < MAXNETNODES; i++) + if (nodeingame[i]) + enet_peer_disconnect(nodetopeer[i], DISCONNECT_SHUTDOWN); + // wait for messages to go through. + while (enet_host_service(ServerHost, &e, 3000) > 0) + switch (e.type) + { + // i don't care, shut up. + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(e.packet); + break; + // good, go away. + case ENET_EVENT_TYPE_DISCONNECT: + break; + // no, we're shutting down. + case ENET_EVENT_TYPE_CONNECT: + enet_peer_reset(e.peer); + break; + } + // alright, we're finished. + enet_host_destroy(ServerHost); + } + if (ClientHost) + { + enet_peer_disconnect(nodetopeer[servernode], 0); + while (enet_host_service(ServerHost, &e, 3000) > 0) + switch (e.type) + { + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(e.packet); + break; + case ENET_EVENT_TYPE_DISCONNECT: + break; + case ENET_EVENT_TYPE_CONNECT: + // how the what ??? + enet_peer_reset(e.peer); + break; + } + enet_host_destroy(ClientHost); + } netgame = false; addedtogame = false; + servernode = 0; } void Net_UnAcknowledgPacket(INT32 node) @@ -42,6 +198,10 @@ void Net_UnAcknowledgPacket(INT32 node) void Net_CloseConnection(INT32 node) { + if (nodeleaving[node] || nodetopeer[node] == NULL) + return; + nodeleaving[node] = true; + enet_peer_disconnect(nodetopeer[node], 0); } void Net_AbortPacketType(UINT8 packettype) @@ -55,3 +215,17 @@ void Net_SendAcks(INT32 node) void Net_WaitAllAckReceived(UINT32 timeout) { } + +void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) +{ +} + +// splitscreen player +void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) +{ +} + +UINT8 GetFreeXCmdSize(void) +{ + return -1; +} diff --git a/src/d_enet.h b/src/d_enet.h index dd340ec7e4dd2d7f2d4969f55f696c430b80b984..6cc954a6da29f572434652ca5cbee63d0673f88f 100644 --- a/src/d_enet.h +++ b/src/d_enet.h @@ -1,6 +1,13 @@ // Make sure we allocate a network node for every player, "server full" denials, the Master server heartbeat, and potential RCON connections. #define MAXNETNODES MAXPLAYERS+2 +extern UINT8 net_nodecount, net_playercount; +extern UINT8 playernode[MAXPLAYERS]; +extern SINT8 nodetoplayer[MAXNETNODES]; +extern SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) +extern UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen +extern boolean nodeingame[MAXNETNODES]; // set false as nodes leave game + boolean Net_GetNetStat(void); void Net_AckTicker(void); boolean Net_AllAckReceived(void); diff --git a/src/d_main.c b/src/d_main.c index 160249ac7aed2fe956421cde3609cc8b9e4db925..dc981ca32a7d7a8f22bdbfa1b0cbea043c88bd1d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -592,11 +592,6 @@ void D_SRB2Loop(void) HW3S_BeginFrameUpdate(); #endif - // don't skip more than 10 frames at a time - // (fadein / fadeout cause massive frame skip!) - if (realtics > 8) - realtics = 1; - // process tics (but maybe not if realtic == 0) TryRunTics(realtics);