This commit is contained in:
Major Cooke 2023-01-21 12:05:50 -06:00
parent 050f982fe2
commit 3d7e8bf7af
10 changed files with 372 additions and 22 deletions

View file

@ -23,13 +23,13 @@ public:
void ToggleFullscreen(bool yes) override; void ToggleFullscreen(bool yes) override;
void SetWindowSize(int client_w, int client_h); void SetWindowSize(int client_w, int client_h);
void PositionWindow(bool fullscreen, bool initialcall = false); // RicardoLuis0: this needs to be public for proper fullscreen handling in netgame restarts
protected: protected:
void GetCenteredPos(int in_w, int in_h, int &winx, int &winy, int &winw, int &winh, int &scrwidth, int &scrheight); void GetCenteredPos(int in_w, int in_h, int &winx, int &winy, int &winw, int &winh, int &scrwidth, int &scrheight);
void KeepWindowOnScreen(int &winx, int &winy, int winw, int winh, int scrwidth, int scrheight); void KeepWindowOnScreen(int &winx, int &winy, int winw, int winh, int scrwidth, int scrheight);
void PositionWindow(bool fullscreen, bool initialcall = false);
float m_Gamma, m_Brightness, m_Contrast; float m_Gamma, m_Brightness, m_Contrast;
uint16_t m_origGamma[768]; uint16_t m_origGamma[768];
bool m_Fullscreen = false; bool m_Fullscreen = false;

View file

@ -79,6 +79,7 @@
#include "printf.h" #include "printf.h"
#include "i_mainwindow.h" #include "i_mainwindow.h"
#include "base_sysfb.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -314,6 +315,17 @@ void I_ShowFatalError(const char *msg)
} }
} }
void I_NetRestartShowConsole()
{
if(vid_fullscreen)
{
static_cast<SystemBaseFrameBuffer*>(screen)->PositionWindow(false, true);
screen->Update();
vid_fullscreen = true; // vid_fullscreen is forced to false by PositionWindow
}
mainwindow.RestoreConView(true);
}
// Here is how the error logging system works. // Here is how the error logging system works.
// //
// To catch exceptions that occur in secondary threads, CatchAllExceptions is // To catch exceptions that occur in secondary threads, CatchAllExceptions is

View file

@ -95,20 +95,22 @@ int MainWindow::GetGameTitleWindowHeight()
// Sets the main WndProc, hides all the child windows, and starts up in-game input. // Sets the main WndProc, hides all the child windows, and starts up in-game input.
void MainWindow::ShowGameView() void MainWindow::ShowGameView()
{ {
if (GetWindowLongPtr(Window, GWLP_USERDATA) == 0) if (GetWindowLongPtr(Window, GWLP_USERDATA) != 1)
{ {
SetWindowLongPtr(Window, GWLP_USERDATA, 1);
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)WndProc); SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)WndProc);
ShowWindow(ConWindow, SW_HIDE); ShowWindow(ConWindow, SW_HIDE);
ShowWindow(ProgressBar, SW_HIDE); ShowWindow(ProgressBar, SW_HIDE);
ConWindowHidden = true; ConWindowHidden = true;
ShowWindow(GameTitleWindow, SW_HIDE); ShowWindow(GameTitleWindow, SW_HIDE);
I_InitInput(Window);
if (GetWindowLongPtr(Window, GWLP_USERDATA) != 2) I_InitInput(Window);
SetWindowLongPtr(Window, GWLP_USERDATA, 1);
} }
} }
// Returns the main window to its startup state. // Returns the main window to its startup state.
void MainWindow::RestoreConView() void MainWindow::RestoreConView(bool netgame_restart)
{ {
HDC screenDC = GetDC(0); HDC screenDC = GetDC(0);
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
@ -118,6 +120,31 @@ void MainWindow::RestoreConView()
// Make sure the window has a frame in case it was fullscreened. // Make sure the window has a frame in case it was fullscreened.
SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW); SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
if(netgame_restart)
{
DEVMODE displaysettings;
// Many Windows structures that specify their size do so with the first
// element. DEVMODE is not one of those structures.
memset (&displaysettings, 0, sizeof(displaysettings));
displaysettings.dmSize = sizeof(displaysettings);
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
int x = (displaysettings.dmPelsWidth - width) / 2;
int y = (displaysettings.dmPelsHeight - height) / 2;
// Make sure the window has a frame in case it was fullscreened.
SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
{
SetWindowPos(Window, HWND_BOTTOM, x, y, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS);
SetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
}
else
{
SetWindowPos(Window, NULL, x, y, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOZORDER);
}
}
else
{
if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST) if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
{ {
SetWindowPos(Window, HWND_BOTTOM, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE); SetWindowPos(Window, HWND_BOTTOM, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
@ -127,16 +154,28 @@ void MainWindow::RestoreConView()
{ {
SetWindowPos(Window, NULL, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(Window, NULL, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
} }
}
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)LConProc); SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)LConProc);
ShowWindow(ConWindow, SW_SHOW); ShowWindow(ConWindow, SW_SHOW);
ConWindowHidden = false; ConWindowHidden = false;
ShowWindow(GameTitleWindow, SW_SHOW); ShowWindow(GameTitleWindow, SW_SHOW);
I_ShutdownInput(); // Make sure the mouse pointer is available.
if(netgame_restart)
{ // Make sure the input system isn't reset
I_CheckNativeMouse(true, false);
}
else
{ // Make sure the mouse pointer is available.
I_ShutdownInput();
}
// Make sure the progress bar isn't visible. // Make sure the progress bar isn't visible.
DeleteStartupScreen(); DeleteStartupScreen();
FlushBufferedConsoleStuff(); FlushBufferedConsoleStuff();
// Make sure the input system isn't reset
SetWindowLongPtr(Window, GWLP_USERDATA, 2);
} }
// Shows an error message, preferably in the main window, but it can use a normal message box too. // Shows an error message, preferably in the main window, but it can use a normal message box too.

View file

@ -17,7 +17,7 @@ public:
void Create(const FString& title, int x, int y, int width, int height); void Create(const FString& title, int x, int y, int width, int height);
void ShowGameView(); void ShowGameView();
void RestoreConView(); void RestoreConView(bool netgame_restart = false);
void ShowErrorPane(const char* text); void ShowErrorPane(const char* text);
void CheckForRestart(); void CheckForRestart();

View file

@ -479,7 +479,7 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname)
VkPPShader* VkShaderManager::GetVkShader(PPShader* shader) VkPPShader* VkShaderManager::GetVkShader(PPShader* shader)
{ {
if (!shader->Backend) if (!shader->Backend || !static_cast<VkPPShader*>(shader->Backend.get())->VertexShader)
shader->Backend = std::make_unique<VkPPShader>(fb, shader); shader->Backend = std::make_unique<VkPPShader>(fb, shader);
return static_cast<VkPPShader*>(shader->Backend.get()); return static_cast<VkPPShader*>(shader->Backend.get());
} }

View file

@ -136,7 +136,7 @@ VkFormat VkTextureManager::GetTextureFormat(PPTexture* texture)
VkPPTexture* VkTextureManager::GetVkTexture(PPTexture* texture) VkPPTexture* VkTextureManager::GetVkTexture(PPTexture* texture)
{ {
if (!texture->Backend) if (!texture->Backend || !static_cast<VkPPTexture*>(texture->Backend.get())->TexImage.View)
texture->Backend = std::make_unique<VkPPTexture>(fb, texture); texture->Backend = std::make_unique<VkPPTexture>(fb, texture);
return static_cast<VkPPTexture*>(texture->Backend.get()); return static_cast<VkPPTexture*>(texture->Backend.get());
} }

View file

@ -142,6 +142,14 @@ void Local_Job_Init();
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern void I_SetWindowTitle(const char* caption); extern void I_SetWindowTitle(const char* caption);
#ifdef _WIN32
extern void I_NetRestartShowConsole();
//RicardoLuis0: TODO fix host/join CCMD startup window on non-windows platforms
#else
#define I_NetRestartShowConsole()
#endif
extern void ReadStatistics(); extern void ReadStatistics();
extern void M_SetDefaultMode (); extern void M_SetDefaultMode ();
extern void G_NewInit (); extern void G_NewInit ();
@ -166,6 +174,7 @@ void G_BuildTiccmd (ticcmd_t* cmd);
void D_DoAdvanceDemo (); void D_DoAdvanceDemo ();
void D_LoadWadSettings (); void D_LoadWadSettings ();
void ParseGLDefs(); void ParseGLDefs();
void ClearGLDefs();
void DrawFullscreenSubtitle(FFont* font, const char *text); void DrawFullscreenSubtitle(FFont* font, const char *text);
void D_Cleanup(); void D_Cleanup();
void FreeSBarInfoScript(); void FreeSBarInfoScript();
@ -332,6 +341,7 @@ const char *Subtitle;
bool nospriterename; bool nospriterename;
FString lastIWAD; FString lastIWAD;
int restart = 0; int restart = 0;
bool restart_multiplayer = false;
extern bool AppActive; extern bool AppActive;
bool playedtitlemusic; bool playedtitlemusic;
@ -3049,6 +3059,9 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
gameinfo.nokeyboardcheats = iwad_info->nokeyboardcheats; gameinfo.nokeyboardcheats = iwad_info->nokeyboardcheats;
gameinfo.ConfigName = iwad_info->Configname; gameinfo.ConfigName = iwad_info->Configname;
// make sure shaders/etc aren't loaded twice when restarting the engine
ClearGLDefs();
const char *v = Args->CheckValue("-rngseed"); const char *v = Args->CheckValue("-rngseed");
if (v) if (v)
{ {
@ -3173,7 +3186,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
CT_Init (); CT_Init ();
if (!restart) if (!restart || restart_multiplayer)
{ {
if (!batchrun) Printf ("I_Init: Setting up machine state.\n"); if (!batchrun) Printf ("I_Init: Setting up machine state.\n");
CheckCPUID(&CPU); CheckCPUID(&CPU);
@ -3215,7 +3228,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
} }
if (!batchrun) Printf ("ST_Init: Init startup screen.\n"); if (!batchrun) Printf ("ST_Init: Init startup screen.\n");
if (!restart) if (!restart || restart_multiplayer)
{ {
StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5, StartScreen == nullptr); StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5, StartScreen == nullptr);
} }
@ -3382,7 +3395,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
} }
} }
if (!restart) if (!restart || restart_multiplayer)
{ {
if (!batchrun) Printf ("D_CheckNetGame: Checking network game status.\n"); if (!batchrun) Printf ("D_CheckNetGame: Checking network game status.\n");
if (StartScreen) StartScreen->LoadingStatus ("Checking network game status.", 0x3f); if (StartScreen) StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
@ -3409,7 +3422,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
if (cl_customizeinvulmap) if (cl_customizeinvulmap)
R_UpdateInvulnerabilityColormap(); R_UpdateInvulnerabilityColormap();
if (!restart) if (!restart || restart_multiplayer)
{ {
// start the apropriate game based on parms // start the apropriate game based on parms
auto v = Args->CheckValue ("-record"); auto v = Args->CheckValue ("-record");
@ -3462,7 +3475,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
} }
v = Args->CheckValue("-playdemo"); v = Args->CheckValue("-playdemo");
if (v != NULL) if (v && !restart_multiplayer)
{ {
singledemo = true; // quit after one demo singledemo = true; // quit after one demo
G_DeferedPlayDemo (v); G_DeferedPlayDemo (v);
@ -3470,7 +3483,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
else else
{ {
v = Args->CheckValue("-timedemo"); v = Args->CheckValue("-timedemo");
if (v) if (v && !restart_multiplayer)
{ {
G_TimeDemo(v); G_TimeDemo(v);
} }
@ -3524,7 +3537,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
D_StartTitle (); // start up intro loop D_StartTitle (); // start up intro loop
setmodeneeded = false; // This may be set to true here, but isn't needed for a restart setmodeneeded = false; // This may be set to true here, but isn't needed for a restart
} }
restart_multiplayer = false;
staticEventManager.OnEngineInitialize(); staticEventManager.OnEngineInitialize();
return 0; return 0;
} }
@ -3646,6 +3659,10 @@ static int D_DoomMain_Internal (void)
if (restart) if (restart)
{ {
C_InitConsole(SCREENWIDTH, SCREENHEIGHT, false); C_InitConsole(SCREENWIDTH, SCREENHEIGHT, false);
if(restart_multiplayer)
{
I_NetRestartShowConsole();
}
} }
nospriterename = false; nospriterename = false;
@ -3858,6 +3875,148 @@ UNSAFE_CCMD(restart)
wantToRestart = true; wantToRestart = true;
} }
UNSAFE_CCMD(host)
{
if(netgame || multiplayer)
{
Printf ("You must not be in a net game when hosting\n");
return;
}
int numplayers = 0;
FString map = "";
int ticdup = -1;
int port = -1;
int skill = -1;
FString loadsave = "";
int flags = 0;
const auto n = argv.argc();
if(n <= 1)
{
Printf ("Not enough arguments for host\n");
return;
}
numplayers = atoi(argv[1]);
for(int i = 2; i < n; i++)
{
FString arg(argv[i]);
auto sep = arg.IndexOf('=');
if(sep == -1)
{
if(arg.CompareNoCase("EXTRATIC") == 0)
{
flags |= MP_EXTRATIC;
}
else if(arg.CompareNoCase("PACKET_SERVER") == 0)
{
flags |= MP_PACKET_SERVER;
}
else if(arg.CompareNoCase("DEATHMATCH") == 0)
{
flags |= MP_DEATHMATCH;
}
else if(arg.CompareNoCase("ALTDEATH") == 0)
{
flags |= MP_ALTDEATH;
}
else if(arg.CompareNoCase("NOMONSTERS") == 0)
{
flags |= MP_NOMONSTERS;
}
else
{
Printf ("Invalid argument for host: %s\n",arg.GetChars());
return;
}
}
else
{
if(strnicmp(arg.GetChars(),"MAP",sep) == 0)
{
map = FString(arg.GetChars() + sep + 1);
}
else if(strnicmp(arg.GetChars(),"LOADSAVE",sep) == 0)
{
loadsave = FString(arg.GetChars() + sep + 1);
}
else if(strnicmp(arg.GetChars(),"PORT",sep) == 0)
{
port = atoi(arg.GetChars() + sep + 1);
}
else if(strnicmp(arg.GetChars(),"SKILL",sep) == 0)
{
skill = atoi(arg.GetChars() + sep + 1);
}
else if(strnicmp(arg.GetChars(),"TICDUP",sep) == 0)
{
ticdup = atoi(arg.GetChars() + sep + 1);
}
else
{
Printf ("Invalid argument for host: %s\n",arg.GetChars());
return;
}
}
}
D_RestartHostMultiplayer(numplayers,map,ticdup,port,skill,loadsave,flags);
}
UNSAFE_CCMD(join)
{
if(netgame || multiplayer)
{
Printf ("You must not be in a net game when joining\n");
return;
}
FString addr = "";
int port = -1;
FString loadsave = "";
const auto n = argv.argc();
if(n <= 1)
{
Printf ("Not enough arguments for host\n");
return;
}
addr = FString(argv[1]);
for(int i = 2; i < n; i++)
{
FString arg(argv[i]);
auto sep = arg.IndexOf('=');
if(sep == -1)
{
Printf ("Invalid argument for host: %s\n",arg.GetChars());
return;
}
else
{
if(strnicmp(arg.GetChars(),"LOADSAVE",sep) == 0)
{
loadsave = FString(arg.GetChars() + sep + 1);
}
else if(strnicmp(arg.GetChars(),"PORT",sep) == 0)
{
port = atoi(arg.GetChars() + sep + 1);
}
else
{
Printf ("Invalid argument for host: %s\n",arg.GetChars());
return;
}
}
}
D_RestartJoinMultiplayer(addr,port,loadsave);
}
DEFINE_FIELD_X(InputEventData, event_t, type) DEFINE_FIELD_X(InputEventData, event_t, type)
DEFINE_FIELD_X(InputEventData, event_t, subtype) DEFINE_FIELD_X(InputEventData, event_t, subtype)
DEFINE_FIELD_X(InputEventData, event_t, data1) DEFINE_FIELD_X(InputEventData, event_t, data1)

View file

@ -1802,6 +1802,124 @@ void D_QuitNetGame (void)
fclose (debugfile); fclose (debugfile);
} }
extern bool wantToRestart;
extern bool restart_multiplayer;
void D_RestartHostMultiplayer(int numplayers, FString map, int ticdup, int port, int skill, FString loadsave, int flags)
{
if(netgame || multiplayer)
{
I_FatalError ("You must not be in a net game before starting one");
}
Args->RemoveArgs("-join");
Args->RemoveArgs("-host");
Args->RemoveArgs("-net");
Args->RemoveArgs("-netmode");
Args->RemoveArgs("-port");
Args->RemoveArgs("-dup");
Args->RemoveArgs("-extratic");
Args->RemoveArgs("-deathmatch");
Args->RemoveArgs("-nomonsters");
Args->RemoveArgs("+map");
FString tmp;
tmp.Format("%d",numplayers);
Args->AppendArg("-host");
Args->AppendArg(tmp);
if(!map.IsEmpty()) {
Args->AppendArg("+map");
Args->AppendArg(map);
}
if(ticdup > 0)
{
tmp.Format("%d",ticdup);
Args->AppendArg("-dup");
Args->AppendArg(tmp);
}
if(port >= 0)
{
tmp.Format("%d",port);
Args->AppendArg("-port");
Args->AppendArg(tmp);
}
if(skill >= 0)
{
tmp.Format("%d",skill);
Args->AppendArg("-skill");
Args->AppendArg(tmp);
}
if(!loadsave.IsEmpty())
{
Args->AppendArg("+loadsave");
Args->AppendArg(loadsave);
}
if(flags & MP_EXTRATIC)
{
Args->AppendArg("-extratic");
}
if(flags & MP_PACKET_SERVER)
{
Args->AppendArg("-netmode");
Args->AppendArg("1");
}
if(flags & MP_DEATHMATCH)
{
Args->AppendArg("-deathmatch");
if(flags & MP_ALTDEATH)
{
Args->AppendArg("-altdeath");
}
}
if(flags & MP_NOMONSTERS)
{
Args->AppendArg("-nomonsters");
}
wantToRestart = true;
restart_multiplayer = true;
}
void D_RestartJoinMultiplayer(const char * host_addr, int port, FString loadsave)
{
if(netgame || multiplayer)
{
I_FatalError ("You must not be in a net game before starting one");
}
Args->RemoveArgs("-join");
Args->RemoveArgs("-host");
Args->RemoveArgs("-net");
Args->RemoveArgs("-netmode");
Args->RemoveArgs("-port");
Args->RemoveArgs("-dup");
Args->RemoveArgs("-extratic");
Args->RemoveArgs("-deathmatch");
Args->RemoveArgs("-nomonsters");
Args->RemoveArgs("+map");
Args->AppendArg("-join");
Args->AppendArg(host_addr);
if(port >= 0)
{
FString tmp;
tmp.Format("%d",port);
Args->AppendArg("-port");
Args->AppendArg(tmp);
}
if(!loadsave.IsEmpty())
{
Args->AppendArg("+loadsave");
Args->AppendArg(loadsave);
}
wantToRestart = true;
restart_multiplayer = true;
}
// Forces playsim processing time to be consistent across frames. // Forces playsim processing time to be consistent across frames.
// This improves interpolation for frames in between tics. // This improves interpolation for frames in between tics.
// //

View file

@ -56,6 +56,23 @@ void NetUpdate (void);
// to notify of game exit // to notify of game exit
void D_QuitNetGame (void); void D_QuitNetGame (void);
enum EMultiplayerHostFlags
{
MP_EXTRATIC = 1,
MP_PACKET_SERVER = 2,
MP_DEATHMATCH = 4,
MP_ALTDEATH = 8,
MP_NOMONSTERS = 16,
};
void D_RestartHostMultiplayer(int numplayers, FString map= "", int ticdup = -1, int port = -1, int skill = -1, FString loadsave = "", int flags = 0);
void D_RestartJoinMultiplayer(const char * host_addr, int port = -1, FString loadsave = "");
//? how many ticks to run? //? how many ticks to run?
void TryRunTics (void); void TryRunTics (void);

View file

@ -2016,7 +2016,6 @@ void LoadGLDefs(const char *defsLump)
InitializeActorLights(LightAssociations); InitializeActorLights(LightAssociations);
} }
//========================================================================== //==========================================================================
// //
// //
@ -2053,3 +2052,9 @@ void ParseGLDefs()
ParseVavoomSkybox(); ParseVavoomSkybox();
LoadGLDefs(defsLump); LoadGLDefs(defsLump);
} }
void ClearGLDefs()
{
PostProcessShaders.Clear();
usershaders.Clear();
}