# HG changeset patch # User asmolcic # Date 1622311716 -7200 # Sat May 29 20:08:36 2021 +0200 # Node ID ea2a073a4b021689b32c4ae813717a5b93126804 # Parent dd3c3b57023f64cda84f09ed13e4c03a4ad2b920 server save game diff -r dd3c3b57023f -r ea2a073a4b02 src/c_cmds.cpp --- a/src/c_cmds.cpp Fri Sep 01 06:40:50 2017 -0500 +++ b/src/c_cmds.cpp Sat May 29 20:08:36 2021 +0200 @@ -841,7 +841,7 @@ int argstart = 2; int arg[4] = { 0, 0, 0, 0 }; int argn = 0, i; - + if (argc > 2) { if (stricmp(argv[2], "always") == 0) @@ -1155,8 +1155,8 @@ } if (( NETWORK_GetState( ) != NETSTATE_SINGLE ) && ( NETWORK_GetState( ) != NETSTATE_SINGLE_MULTIPLAYER )) { - Printf ("cannot load during a network game\n"); - return; + Printf ("Trying to load during a network game\n"); + // return; } FString fname = argv[1]; DefaultExtension (fname, ".zds"); @@ -1201,8 +1201,8 @@ // [BB] No saving in multiplayer. if ( NETWORK_GetState( ) == NETSTATE_CLIENT ) { - Printf ("You cannot save the game in multiplayer.\n"); - return; + Printf ("Trying to save the game in multiplayer.\n"); + // return; } // [BB] Saving bots is not supported yet. @@ -1281,7 +1281,7 @@ AActor *linetarget; if (CheckCheatmode () || players[consoleplayer].mo == NULL) return; - P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, + P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &linetarget, 0, ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART); if (linetarget) { @@ -1410,11 +1410,11 @@ } // [TL] Get the next map if available. - const char * next = G_GetExitMap( ); - + const char * next = G_GetExitMap( ); + // [BB] G_GetExitMap() can return an empty string. if ( next && strncmp(next, "enDSeQ", 6) && ( strlen ( next ) > 0 ) ) - { + { // Fuck that DEM shit! if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { @@ -1430,7 +1430,7 @@ else { Net_WriteByte (DEM_CHANGEMAP); - } + } Net_WriteString( next ); } @@ -1449,7 +1449,7 @@ return; } char *next = NULL; - + if (*level.nextmap) next = level.nextmap; @@ -1487,7 +1487,7 @@ // [TL] Get the secret level or next map if not available. const char * next = G_GetSecretExitMap(); - + // [BB] G_GetSecretExitMap() can return an empty string. if ( next && strncmp(next, "enDSeQ", 6) && ( strlen ( next ) > 0 ) ) { @@ -1521,7 +1521,7 @@ return; } char *next = NULL; - + if (*level.secretmap) next = level.secretmap; @@ -1657,7 +1657,7 @@ cmdTotal += argv[i]; } - + AddCommandString(cmdTotal.LockBuffer()); cmdTotal.UnlockBuffer(); } diff -r dd3c3b57023f -r ea2a073a4b02 src/g_game.cpp --- a/src/g_game.cpp Fri Sep 01 06:40:50 2017 -0500 +++ b/src/g_game.cpp Sat May 29 20:08:36 2021 +0200 @@ -1,4 +1,4 @@ -// Emacs style mode select -*- C++ -*- +// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ @@ -33,7 +33,7 @@ #include "templates.h" #include "version.h" -#include "doomdef.h" +#include "doomdef.h" #include "doomstat.h" #include "d_protocol.h" #include "d_netinf.h" @@ -58,7 +58,7 @@ #include "c_dispatch.h" #include "v_video.h" #include "w_wad.h" -#include "p_local.h" +#include "p_local.h" #include "s_sound.h" #include "gstrings.h" #include "r_main.h" @@ -184,15 +184,15 @@ gamestate_t gamestate = GS_STARTUP; int paused; -bool sendpause; // send a pause event next tic -bool sendsave; // send a save event next tic +bool sendpause; // send a pause event next tic +bool sendsave; // send a save event next tic bool sendturn180; // [RH] send a 180 degree turn next tic bool usergame; // ok to save / end game bool insave; // Game is saving - used to block exit commands -bool timingdemo; // if true, exit with report on completion -bool nodrawers; // for comparative timing purposes -bool noblit; // for comparative timing purposes +bool timingdemo; // if true, exit with report on completion +bool nodrawers; // for comparative timing purposes +bool noblit; // for comparative timing purposes bool viewactive; @@ -215,17 +215,17 @@ size_t maxdemosize; BYTE* zdemformend; // end of FORM ZDEM chunk BYTE* zdembodyend; // end of ZDEM BODY chunk -bool singledemo; // quit after playing a demo from cmdline - -bool precache = true; // if true, load all graphics at start - -wbstartstruct_t wminfo; // parms for world map / intermission - +bool singledemo; // quit after playing a demo from cmdline + +bool precache = true; // if true, load all graphics at start + +wbstartstruct_t wminfo; // parms for world map / intermission + short consistancy[MAXPLAYERS][BACKUPTICS]; - - -#define MAXPLMOVE (forwardmove[1]) - + + +#define MAXPLMOVE (forwardmove[1]) + #define TURBOTHRESHOLD 12800 float normforwardmove[2] = {0x19, 0x32}; // [RH] For setting turbo from console @@ -236,7 +236,7 @@ fixed_t flyspeed[2] = {1*256, 3*256}; int lookspeed[2] = {450, 512}; -#define SLOWTURNTICS 6 +#define SLOWTURNTICS 6 // [BB] This is a new school port, so cl_run defaults to true. CVAR (Bool, cl_run, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // Always run? @@ -248,12 +248,12 @@ CVAR (Float, m_yaw, 1.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) CVAR (Float, m_forward, 1.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) CVAR (Float, m_side, 2.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) - -int turnheld; // for accelerative turning - -// mouse values are used once + +int turnheld; // for accelerative turning + +// mouse values are used once int mousex; -int mousey; +int mousey; FString savegamefile; char savedescription[SAVESTRINGSIZE]; @@ -261,8 +261,8 @@ // [RH] Name of screenshot file to generate (usually NULL) FString shotfile; -AActor* bodyque[BODYQUESIZE]; -int bodyqueslot; +AActor* bodyque[BODYQUESIZE]; +int bodyqueslot; void R_ExecuteSetViewSize (void); @@ -355,7 +355,7 @@ if (slot < NUM_WEAPON_SLOTS) { - SendItemUse = players[consoleplayer].weapons.Slots[slot].PickWeapon (&players[consoleplayer], + SendItemUse = players[consoleplayer].weapons.Slots[slot].PickWeapon (&players[consoleplayer], !(dmflags2 & DF2_DONTCHECKAMMO)); } } @@ -486,7 +486,7 @@ } } if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel) - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), + StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V')); } who->player->inventorytics = 5*TICRATE; @@ -516,7 +516,7 @@ who->InvSel = item; } if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel) - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), + StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V')); } who->player->inventorytics = 5*TICRATE; @@ -704,7 +704,7 @@ if (turnheld < SLOWTURNTICS) tspeed += 2; // slow turn - + if (Button_Right.bDown) { G_AddViewAngle (angleturn[tspeed]); @@ -1037,7 +1037,7 @@ // Otherwise, cycle to the next player. int pnum = consoleplayer; - if (changespy != SPY_CANCEL) + if (changespy != SPY_CANCEL) { player_t *player = players[consoleplayer].camera->player; // only use the camera as starting index if it's a valid player. @@ -1272,7 +1272,7 @@ // any other key pops up menu if in demos // [RH] But only if the key isn't bound to a "special" command // [BB] We explicitly don't check if a client side demo is played to allow binding demo_pause, etc.. - if (gameaction == ga_nothing && + if (gameaction == ga_nothing && (demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL)) { const char *cmd = Bindings.GetBind (ev->data1); @@ -1313,7 +1313,7 @@ // Handle chat input at the level and intermission screens. if ( gamestate == GS_LEVEL || gamestate == GS_INTERMISSION ) { - if ( CHAT_Input( ev )) + if ( CHAT_Input( ev )) return ( true ); // [RC] If the player hits the spacebar, and they aren't in the game, ask them if they'd like to join. @@ -1354,7 +1354,7 @@ break; // [RH] mouse buttons are sent as key up/down events - case EV_Mouse: + case EV_Mouse: mousex = (int)(ev->x * mouse_sensitivity); mousey = (int)(ev->y * mouse_sensitivity); break; @@ -1712,7 +1712,7 @@ { // [EP] Clear all the HUD messages. if ( StatusBar ) - StatusBar->DetachAllMessages(); + StatusBar->DetachAllMessages(); } GAME_ResetMap( ); @@ -1799,7 +1799,7 @@ if ( lastmanstanding ) { ULONG ulIdx; - + for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if (( playeringame[ulIdx] == false ) || ( PLAYER_IsTrueSpectator( &players[ulIdx] ))) @@ -1847,7 +1847,7 @@ if ( possession ) { ULONG ulIdx; - + for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if (( playeringame[ulIdx] == false ) || ( PLAYER_IsTrueSpectator( &players[ulIdx] ))) @@ -2216,10 +2216,10 @@ } // -// G_CheckSpot +// G_CheckSpot // Returns false if the player cannot be respawned -// at the given mapthing spot -// because something is occupying it +// at the given mapthing spot +// because something is occupying it // bool G_CheckSpot (int playernum, FPlayerStart *mthing) @@ -2279,9 +2279,9 @@ // -// G_DeathMatchSpawnPlayer -// Spawns a player at one of the random death match spots -// called at level load and each death +// G_DeathMatchSpawnPlayer +// Spawns a player at one of the random death match spots +// called at level load and each death // // [RH] Returns the distance of the closest player to the given mapthing @@ -2804,7 +2804,7 @@ { AActor *pActor; TThinkerIterator Iterator; - + while ( (pActor = Iterator.Next( ))) { if ( pActor->target == pOldBody ) @@ -2902,8 +2902,8 @@ } // We have deathmatch starts, but nothing else. - if (( deathmatchstarts.Size( ) > 0 ) && - ( TemporaryTeamStarts.Size( ) == 0 ) && !bTeamStarts && + if (( deathmatchstarts.Size( ) > 0 ) && + ( TemporaryTeamStarts.Size( ) == 0 ) && !bTeamStarts && bPlayerStarts == false ) { // Since we only have deathmatch starts, enable deathmatch, and disable teamgame/coop. @@ -3176,7 +3176,7 @@ } // [BB] If we are using teams and the teams are supposed to be selected automatically, select the team // for all non-spectator players that are not on a team yet now. - else if ( dmflags2 & DF2_NO_TEAM_SELECT ) + else if ( dmflags2 & DF2_NO_TEAM_SELECT ) { for ( ULONG ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { @@ -3767,7 +3767,7 @@ // If this object belongs to someone's inventory, and it originally spawned on the // level, respawn the item in its original location, but don't take it out of the // player's inventory. - if (( pActor->IsKindOf( RUNTIME_CLASS( AInventory ))) && + if (( pActor->IsKindOf( RUNTIME_CLASS( AInventory ))) && ( static_cast( pActor )->Owner )) { if ( pActor->ulSTFlags & STFL_LEVELSPAWNED ) @@ -4525,7 +4525,18 @@ savegamefile = filename; strncpy (savedescription, description, sizeof(savedescription)-1); savedescription[sizeof(savedescription)-1] = '\0'; - sendsave = true; + if (NETWORK_GetState() == NETSTATE_SERVER) { + if (gamestate == GS_LEVEL) { + G_DoSaveGame (true, savegamefile, savedescription); + gameaction = ga_nothing; + savegamefile = ""; + savedescription[0] = '\0'; + } else { + Printf ("Won't save if not in level\n"); + } + } else { + sendsave = true; + } } FString G_BuildSaveName (const char *prefix, int slot) @@ -4580,8 +4591,8 @@ UCVarValue num; const char *readableTime; int count = autosavecount != 0 ? autosavecount : 1; - - if (nextautosave == -1) + + if (nextautosave == -1) { nextautosave = (autosavenum + 1) % count; } @@ -4661,7 +4672,7 @@ static void PutSavePic (FILE *file, int width, int height) { - if (width <= 0 || height <= 0 || !storesavepic) + if (width <= 0 || height <= 0 || !storesavepic || NETWORK_GetState() == NETSTATE_SERVER) { M_CreateDummyPNG (file); } @@ -4767,7 +4778,7 @@ } fclose(stdfile); } - if (success) + if (success) { if (longsavemessages) Printf ("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars()); else Printf ("%s\n", GStrings("GGSAVED")); @@ -4782,7 +4793,7 @@ delete level.info->snapshot; level.info->snapshot = NULL; } - + insave = false; } @@ -4838,7 +4849,7 @@ break; } } -} +} bool stoprecording; @@ -4909,7 +4920,7 @@ DefaultExtension (demoname, ".lmp"); maxdemosize = 0x20000; demobuffer = (BYTE *)M_Malloc (maxdemosize); - demorecording = true; + demorecording = true; } @@ -5243,7 +5254,7 @@ } else { - // don't spend a lot of time in loadlevel + // don't spend a lot of time in loadlevel precache = false; demonew = true; if (mapname[0] != 0) @@ -5342,10 +5353,10 @@ } else { - D_AdvanceDemo (); + D_AdvanceDemo (); } - return true; + return true; } if (demorecording) @@ -5377,13 +5388,13 @@ formlen = demobuffer + 4; WriteLong (int(demo_p - demobuffer - 8), &formlen); - bool saved = M_WriteFile (demoname, demobuffer, int(demo_p - demobuffer)); - M_Free (demobuffer); + bool saved = M_WriteFile (demoname, demobuffer, int(demo_p - demobuffer)); + M_Free (demobuffer); demorecording = false; stoprecording = false; if (saved) { - Printf ("Demo %s recorded\n", demoname.GetChars()); + Printf ("Demo %s recorded\n", demoname.GetChars()); } else { @@ -5391,7 +5402,7 @@ } } - return false; + return false; } // [BC] New console command that freezes all actors (except the player diff -r dd3c3b57023f -r ea2a073a4b02 src/g_level.cpp --- a/src/g_level.cpp Fri Sep 01 06:40:50 2017 -0500 +++ b/src/g_level.cpp Sat May 29 20:08:36 2021 +0200 @@ -404,7 +404,7 @@ { UnlatchCVars (); } - + G_VerifySkill(); if ( NETWORK_InClientMode() == false ) { @@ -619,7 +619,7 @@ { levelname = level.nextmap; // If there is already an end sequence please leave it alone! } - else + else { // [BB] The server doesn't support end sequences, so just return to the current map. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) @@ -657,8 +657,8 @@ startpos = position; gameaction = ga_completed; - - if (nextinfo != NULL) + + if (nextinfo != NULL) { if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB))) { @@ -797,7 +797,7 @@ nextmap = level.secretmap; } } - + // [TL] Advance to the next map in the rotation if no secret level. return (nextmap) ? nextmap : G_GetExitMap( ); } @@ -816,10 +816,10 @@ return; } - G_ChangeLevel(G_GetExitMap(), position, keepFacing ? CHANGELEVEL_KEEPFACING : 0); + G_ChangeLevel(G_GetExitMap(), position, keepFacing ? CHANGELEVEL_KEEPFACING : 0); } -void G_SecretExitLevel (int position) +void G_SecretExitLevel (int position) { // [TL] Prevent ending a map during survival countdown. if (( survival ) && @@ -839,7 +839,7 @@ void SERVERCONSOLE_UpdateScoreboard( void ); void G_DoCompleted (void) { - int i; + int i; gameaction = ga_nothing; @@ -1026,12 +1026,12 @@ //========================================================================== // -// G_DoLoadLevel +// G_DoLoadLevel // //========================================================================== -extern gamestate_t wipegamestate; - +extern gamestate_t wipegamestate; + void SERVERCONSOLE_SetCurrentMapname( const char *pszString ); void SERVERCONSOLE_UpdatePlayerInfo( LONG lPlayer, ULONG ulUpdateFlags ); void G_DoLoadLevel (int position, bool autosave) @@ -1244,7 +1244,7 @@ case GAMEMODE_DOMINATION: domination.ForceSet( Val, CVAR_Bool ); - break; + break; default: I_Error( "G_DoLoadLevel: Invalid campaign game type, %d!", pInfo->GameMode ); @@ -1347,7 +1347,7 @@ "\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", level.mapname, level.LevelName.GetChars()); - + // [RC] Update the G15 display. G15_NextLevel( level.mapname, level.LevelName.GetChars() ); } @@ -1357,7 +1357,7 @@ if (gamestate != GS_TITLELEVEL) { - gamestate = GS_LEVEL; + gamestate = GS_LEVEL; } // Set the sky map. @@ -1377,7 +1377,7 @@ R_InitSkyMap (); for (i = 0; i < MAXPLAYERS; i++) - { + { // [BC] Added teamgame, invasion. if (playeringame[i] && ((deathmatch || teamgame || invasion) || players[i].playerstate == PST_DEAD)) players[i].playerstate = PST_ENTER; // [BC] @@ -1469,14 +1469,14 @@ P_StartLightning (); } - gameaction = ga_nothing; + gameaction = ga_nothing; // clear cmd building stuff ResetButtonStates (); SendItemUse = NULL; SendItemDrop = NULL; - mousex = mousey = 0; + mousex = mousey = 0; sendpause = sendsave = sendturn180 = SendLand = false; LocalViewAngle = 0; LocalViewPitch = 0; @@ -1543,7 +1543,7 @@ if ( StatusBar ) StatusBar->AttachToPlayer (&players[consoleplayer]); P_DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. - + // [BC] Support for client-side demos. if (demoplayback || ( CLIENTDEMO_IsPlaying( )) || oldgs == GS_STARTUP || oldgs == GS_TITLELEVEL) C_HideConsole (); @@ -1608,19 +1608,19 @@ //========================================================================== // -// G_WorldDone +// G_WorldDone // //========================================================================== -void G_WorldDone (void) -{ +void G_WorldDone (void) +{ cluster_info_t *nextcluster; cluster_info_t *thiscluster; // [BC] Clients don't need to do this, otherwise they'll try to load the map on their end. if ( NETWORK_InClientMode() == false ) { - gameaction = ga_worlddone; + gameaction = ga_worlddone; } if (level.flags & LEVEL_CHANGEMAPCHEAT) @@ -1683,14 +1683,14 @@ } } } -} - +} + //========================================================================== // // //========================================================================== -void G_DoWorldDone (void) +void G_DoWorldDone (void) { ULONG ulIdx; @@ -1732,8 +1732,8 @@ // ASTAR_ClearPath( ulIdx ); } } -} - +} + //========================================================================== // // G_StartTravel @@ -1900,7 +1900,7 @@ } } } - + //========================================================================== // // [BC] G_AllowTravel @@ -2112,7 +2112,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) { int i = level.totaltime; - + // [BC] In client mode, we just want to save the lines we've seen. if ( NETWORK_InClientMode() ) { @@ -2237,7 +2237,11 @@ FCanvasTextureInfo::Serialize (arc); AM_SerializeMarkers(arc); - P_SerializePlayers (arc, hubLoad); + if ( NETWORK_GetState() != NETSTATE_SERVER ) { + P_SerializePlayers (arc, hubLoad); + } else { + Printf("Skipped saving players on network server!\n"); + } P_SerializeSounds (arc); if (arc.IsLoading()) { @@ -2399,7 +2403,7 @@ } FPNGChunkArchive *arc = NULL; - + // Write out which levels have been visited for (i = 0; i < wadlevelinfos.Size(); ++i) { @@ -2696,7 +2700,7 @@ musicNames.insert( info->Music ); } } - + if ( musicNames.size() <= 0 ) { Printf( "No music lumps loaded." ); @@ -2708,11 +2712,11 @@ { if ( it->Len() <= 0) continue; - + if ( (*it)[0] == '$' ) { Printf( " D_%s\n", GStrings( it->GetChars() + 1 ) ); - } + } else { Printf( " %s\n", it->GetChars() );