diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 33b4c12671..27dbfe0a71 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -132,7 +132,8 @@ enum PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt PRE_ALLFULL, // Sent from host to an unwanted guest PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt - PRE_GO // Sent from host to guest to continue game startup + PRE_GO, // Sent from host to guest to continue game startup + PRE_IN_PROGRESS, // Sent from host to guest if the game has already started }; // Set PreGamePacket.fake to this so that the game rejects any pregame packets @@ -269,6 +270,8 @@ void PacketSend (void) // I_Error ("SendPacket error: %s",strerror(errno)); } +void PreSend(const void* buffer, int bufferlen, const sockaddr_in* to); +void SendConAck(int num_connected, int num_needed); // // PacketGet @@ -303,7 +306,7 @@ void PacketGet (void) GetPlayerName(node).GetChars()); } - doomcom.data[0] = 0x80; // NCMD_EXIT + doomcom.data[0] = NCMD_EXIT; c = 1; } else if (err != WSAEWOULDBLOCK) @@ -342,9 +345,13 @@ void PacketGet (void) else if (c > 0) { //The packet is not from any in-game node, so we might as well discard it. // Don't show the message for disconnect notifications. - if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT) + if (TransmitBuffer[0] != NCMD_EXIT) { - DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + if (TransmitBuffer[0] != PRE_FAKE) + DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + // If it's someone waiting in the lobby, let them know the game already started + uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS }; + PreSend(msg, 2, &fromaddress); } doomcom.remotenode = -1; return; @@ -369,7 +376,22 @@ sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort) int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET)) return NULL; // no packet - I_Error ("PreGet: %s", neterror ()); + + if (doomcom.consoleplayer == 0) + { + int node = FindNode(&fromaddress); + I_NetMessage("Got unexpected disconnect."); + doomcom.numnodes--; + for (; node < doomcom.numnodes; ++node) + sendaddress[node] = sendaddress[node + 1]; + + // Let remaining guests know that somebody left. + SendConAck(doomcom.numnodes, doomcom.numplayers); + } + else + { + I_NetError("The host disbanded the game unexpectedly"); + } } return &fromaddress; } @@ -708,7 +730,7 @@ bool HostGame (int i) doomcom.numnodes = 1; - I_NetInit ("Waiting for players", numplayers); + I_NetInit ("Hosting game", numplayers); // Wait for numplayers-1 different connections if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) @@ -783,13 +805,15 @@ bool Guest_ContactHost (void *userdata) } else if (packet.Message == PRE_DISCONNECT) { - doomcom.numnodes = 0; - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); } else if (packet.Message == PRE_ALLFULL) { - doomcom.numnodes = 0; - I_FatalError ("The game is full."); + I_NetError("The game is full."); + } + else if (packet.Message == PRE_IN_PROGRESS) + { + I_NetError("The game was already started."); } } } @@ -850,7 +874,7 @@ bool Guest_WaitForOthers (void *userdata) return true; case PRE_DISCONNECT: - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); break; } } @@ -875,6 +899,7 @@ bool JoinGame (int i) BuildAddress (&sendaddress[1], Args->GetArg(i+1)); sendplayer[1] = 0; doomcom.numnodes = 2; + doomcom.consoleplayer = -1; // Let host know we are here @@ -1046,6 +1071,13 @@ void I_NetMessage(const char* text, ...) #endif } +void I_NetError(const char* error) +{ + doomcom.numnodes = 0; + StartWindow->NetClose(); + I_FatalError(error); +} + // todo: later these must be dispatched by the main menu, not the start screen. void I_NetProgress(int val) { diff --git a/src/common/engine/i_net.h b/src/common/engine/i_net.h index c52072c863..15720374d0 100644 --- a/src/common/engine/i_net.h +++ b/src/common/engine/i_net.h @@ -7,6 +7,7 @@ int I_InitNetwork (void); void I_NetCmd (void); void I_NetMessage(const char*, ...); +void I_NetError(const char* error); void I_NetProgress(int val); void I_NetInit(const char* msg, int num); bool I_NetLoop(bool (*timer_callback)(void*), void* userdata); diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index a8b78aaa83..b09991d04f 100644 --- a/src/common/engine/st_start.h +++ b/src/common/engine/st_start.h @@ -55,6 +55,7 @@ public: virtual void NetInit(const char *message, int num_players) {} virtual void NetProgress(int count) {} virtual void NetDone() {} + virtual void NetClose() {} virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; } virtual void AppendStatusLine(const char* status) {} virtual void LoadingStatus(const char* message, int colors) {} @@ -74,6 +75,7 @@ public: void NetProgress(int count); void NetMessage(const char* format, ...); // cover for printf void NetDone(); + void NetClose(); bool NetLoop(bool (*timer_callback)(void*), void* userdata); protected: int NetMaxPos, NetCurPos; diff --git a/src/common/platform/win32/i_mainwindow.cpp b/src/common/platform/win32/i_mainwindow.cpp index 95dda5031f..5bdd3569c2 100644 --- a/src/common/platform/win32/i_mainwindow.cpp +++ b/src/common/platform/win32/i_mainwindow.cpp @@ -128,6 +128,11 @@ void MainWindow::HideNetStartPane() NetStartWindow::HideNetStartPane(); } +void MainWindow::CloseNetStartPane() +{ + NetStartWindow::NetClose(); +} + void MainWindow::SetNetStartProgress(int pos) { NetStartWindow::SetNetStartProgress(pos); diff --git a/src/common/platform/win32/i_mainwindow.h b/src/common/platform/win32/i_mainwindow.h index 3c0c7e55df..83567135cf 100644 --- a/src/common/platform/win32/i_mainwindow.h +++ b/src/common/platform/win32/i_mainwindow.h @@ -29,6 +29,7 @@ public: void SetNetStartProgress(int pos); bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); void HideNetStartPane(); + void CloseNetStartPane(); void SetWindowTitle(const char* caption); diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index 8bc48d26e5..fceeb3cede 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -201,3 +201,8 @@ bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata { return mainwindow.RunMessageLoop(timer_callback, userdata); } + +void FBasicStartupScreen::NetClose() +{ + mainwindow.CloseNetStartPane(); +} diff --git a/src/common/widgets/netstartwindow.cpp b/src/common/widgets/netstartwindow.cpp index 69c83e5654..887f9cc316 100644 --- a/src/common/widgets/netstartwindow.cpp +++ b/src/common/widgets/netstartwindow.cpp @@ -64,6 +64,12 @@ bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newu return Instance->exitreason; } +void NetStartWindow::NetClose() +{ + if (Instance != nullptr) + Instance->OnClose(); +} + NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window) { SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); diff --git a/src/common/widgets/netstartwindow.h b/src/common/widgets/netstartwindow.h index 5d27b8ebfc..dcc9d688ea 100644 --- a/src/common/widgets/netstartwindow.h +++ b/src/common/widgets/netstartwindow.h @@ -14,6 +14,7 @@ public: static void HideNetStartPane(); static void SetNetStartProgress(int pos); static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); + static void NetClose(); private: NetStartWindow();