2020-09-08 22:10:45 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
Doom 3 Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include "sys/platform.h"
# include "idlib/hashing/CRC32.h"
# include "idlib/LangDict.h"
# include "framework/async/AsyncNetwork.h"
# include "framework/Console.h"
# include "framework/Game.h"
# include "framework/EventLoop.h"
# include "renderer/ModelManager.h"
# include "framework/Session_local.h"
# if defined(__AROS__)
# define CDKEY_FILEPATH CDKEY_FILE
# define XPKEY_FILEPATH XPKEY_FILE
# else
# define CDKEY_FILEPATH ".. / " BASE_GAMEDIR " / " CDKEY_FILE
# define XPKEY_FILEPATH ".. / " BASE_GAMEDIR " / " XPKEY_FILE
# endif
2020-11-15 18:52:37 +00:00
extern " C " int questType ;
2020-09-08 22:10:45 +00:00
idCVar idSessionLocal : : com_showAngles ( " com_showAngles " , " 0 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
idCVar idSessionLocal : : com_minTics ( " com_minTics " , " 1 " , CVAR_SYSTEM , " " ) ;
2020-11-28 15:20:28 +00:00
idCVar idSessionLocal : : com_showTics ( " com_showTics " , " 1 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
idCVar idSessionLocal : : com_skipTics ( " com_skipTics " , " 1 " , CVAR_SYSTEM | CVAR_BOOL | CVAR_ARCHIVE , " Skip all missed tics and only use one tick per frame, unless in a low fps situation, then process all tics " ) ;
2020-09-11 21:41:18 +00:00
idCVar idSessionLocal : : com_fixedTic ( " com_fixedTic " , " 0 " , CVAR_SYSTEM | CVAR_INTEGER | CVAR_ARCHIVE , " " , - 1 , 10 ) ;
2020-09-08 22:10:45 +00:00
idCVar idSessionLocal : : com_showDemo ( " com_showDemo " , " 0 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
idCVar idSessionLocal : : com_skipGameDraw ( " com_skipGameDraw " , " 0 " , CVAR_SYSTEM | CVAR_BOOL , " " ) ;
idCVar idSessionLocal : : com_aviDemoSamples ( " com_aviDemoSamples " , " 16 " , CVAR_SYSTEM , " " ) ;
idCVar idSessionLocal : : com_aviDemoWidth ( " com_aviDemoWidth " , " 256 " , CVAR_SYSTEM , " " ) ;
idCVar idSessionLocal : : com_aviDemoHeight ( " com_aviDemoHeight " , " 256 " , CVAR_SYSTEM , " " ) ;
idCVar idSessionLocal : : com_aviDemoTics ( " com_aviDemoTics " , " 2 " , CVAR_SYSTEM | CVAR_INTEGER , " " , 1 , 60 ) ;
idCVar idSessionLocal : : com_wipeSeconds ( " com_wipeSeconds " , " 1 " , CVAR_SYSTEM , " " ) ;
idCVar idSessionLocal : : com_guid ( " com_guid " , " " , CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_ROM , " " ) ;
idSessionLocal sessLocal ;
idSession * session = & sessLocal ;
// these must be kept up to date with window Levelshot in guis/mainmenu.gui
const int PREVIEW_X = 211 ;
const int PREVIEW_Y = 31 ;
const int PREVIEW_WIDTH = 398 ;
const int PREVIEW_HEIGHT = 298 ;
void RandomizeStack ( void ) {
// attempt to force uninitialized stack memory bugs
int bytes = 4000000 ;
byte * buf = ( byte * ) _alloca ( bytes ) ;
int fill = rand ( ) & 255 ;
for ( int i = 0 ; i < bytes ; i + + ) {
buf [ i ] = fill ;
}
}
/*
= = = = = = = = = = = = = = = = =
Session_RescanSI_f
= = = = = = = = = = = = = = = = =
*/
void Session_RescanSI_f ( const idCmdArgs & args ) {
sessLocal . mapSpawnData . serverInfo = * cvarSystem - > MoveCVarsToDict ( CVAR_SERVERINFO ) ;
if ( game & & idAsyncNetwork : : server . IsActive ( ) ) {
game - > SetServerInfo ( sessLocal . mapSpawnData . serverInfo ) ;
}
}
# ifndef ID_DEDICATED
/*
= = = = = = = = = = = = = = = = = =
Session_Map_f
Restart the server on a different map
= = = = = = = = = = = = = = = = = =
*/
static void Session_Map_f ( const idCmdArgs & args ) {
idStr map , string ;
findFile_t ff ;
idCmdArgs rl_args ;
map = args . Argv ( 1 ) ;
if ( ! map . Length ( ) ) {
return ;
}
map . StripFileExtension ( ) ;
// make sure the level exists before trying to change, so that
// a typo at the server console won't end the game
// handle addon packs through reloadEngine
sprintf ( string , " maps/%s.map " , map . c_str ( ) ) ;
ff = fileSystem - > FindFile ( string , true ) ;
switch ( ff ) {
case FIND_NO :
common - > Printf ( " Can't find map %s \n " , string . c_str ( ) ) ;
return ;
case FIND_ADDON :
common - > Printf ( " map %s is in an addon pak - reloading \n " , string . c_str ( ) ) ;
rl_args . AppendArg ( " map " ) ;
rl_args . AppendArg ( map ) ;
cmdSystem - > SetupReloadEngine ( rl_args ) ;
return ;
default :
break ;
}
cvarSystem - > SetCVarBool ( " developer " , false ) ;
sessLocal . StartNewGame ( map , true ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Session_DevMap_f
Restart the server on a different map in developer mode
= = = = = = = = = = = = = = = = = =
*/
static void Session_DevMap_f ( const idCmdArgs & args ) {
idStr map , string ;
findFile_t ff ;
idCmdArgs rl_args ;
map = args . Argv ( 1 ) ;
if ( ! map . Length ( ) ) {
return ;
}
map . StripFileExtension ( ) ;
// make sure the level exists before trying to change, so that
// a typo at the server console won't end the game
// handle addon packs through reloadEngine
sprintf ( string , " maps/%s.map " , map . c_str ( ) ) ;
ff = fileSystem - > FindFile ( string , true ) ;
switch ( ff ) {
case FIND_NO :
common - > Printf ( " Can't find map %s \n " , string . c_str ( ) ) ;
return ;
case FIND_ADDON :
common - > Printf ( " map %s is in an addon pak - reloading \n " , string . c_str ( ) ) ;
rl_args . AppendArg ( " devmap " ) ;
rl_args . AppendArg ( map ) ;
cmdSystem - > SetupReloadEngine ( rl_args ) ;
return ;
default :
break ;
}
cvarSystem - > SetCVarBool ( " developer " , true ) ;
sessLocal . StartNewGame ( map , true ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Session_TestMap_f
= = = = = = = = = = = = = = = = = =
*/
static void Session_TestMap_f ( const idCmdArgs & args ) {
idStr map , string ;
map = args . Argv ( 1 ) ;
if ( ! map . Length ( ) ) {
return ;
}
map . StripFileExtension ( ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , " disconnect " ) ;
sprintf ( string , " dmap maps/%s.map " , map . c_str ( ) ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , string ) ;
sprintf ( string , " devmap %s " , map . c_str ( ) ) ;
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , string ) ;
}
# endif
/*
= = = = = = = = = = = = = = = = = =
Sess_WritePrecache_f
= = = = = = = = = = = = = = = = = =
*/
static void Sess_WritePrecache_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) ! = 2 ) {
common - > Printf ( " USAGE: writePrecache <execFile> \n " ) ;
return ;
}
idStr str = args . Argv ( 1 ) ;
str . DefaultFileExtension ( " .cfg " ) ;
idFile * f = fileSystem - > OpenFileWrite ( str , " fs_configpath " ) ;
declManager - > WritePrecacheCommands ( f ) ;
renderModelManager - > WritePrecacheCommands ( f ) ;
uiManager - > WritePrecacheCommands ( f ) ;
fileSystem - > CloseFile ( f ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : MaybeWaitOnCDKey
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : MaybeWaitOnCDKey ( void ) {
if ( authEmitTimeout > 0 ) {
authWaitBox = true ;
sessLocal . MessageBox ( MSG_WAIT , common - > GetLanguageDict ( ) - > GetString ( " #str_07191 " ) , NULL , true , NULL , NULL , true ) ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = =
Session_PromptKey_f
= = = = = = = = = = = = = = = = = = =
*/
static void Session_PromptKey_f ( const idCmdArgs & args ) {
const char * retkey ;
bool valid [ 2 ] ;
static bool recursed = false ;
if ( recursed ) {
common - > Warning ( " promptKey recursed - aborted " ) ;
return ;
}
recursed = true ;
do {
// in case we're already waiting for an auth to come back to us ( may happen exceptionally )
if ( sessLocal . MaybeWaitOnCDKey ( ) ) {
if ( sessLocal . CDKeysAreValid ( true ) ) {
recursed = false ;
return ;
}
}
// the auth server may have replied and set an error message, otherwise use a default
const char * prompt_msg = sessLocal . GetAuthMsg ( ) ;
if ( prompt_msg [ 0 ] = = ' \0 ' ) {
prompt_msg = common - > GetLanguageDict ( ) - > GetString ( " #str_04308 " ) ;
}
retkey = sessLocal . MessageBox ( MSG_CDKEY , prompt_msg , common - > GetLanguageDict ( ) - > GetString ( " #str_04305 " ) , true , NULL , NULL , true ) ;
if ( retkey ) {
if ( sessLocal . CheckKey ( retkey , false , valid ) ) {
// if all went right, then we may have sent an auth request to the master ( unless the prompt is used during a net connect )
bool canExit = true ;
if ( sessLocal . MaybeWaitOnCDKey ( ) ) {
// wait on auth reply, and got denied, prompt again
if ( ! sessLocal . CDKeysAreValid ( true ) ) {
// server says key is invalid - MaybeWaitOnCDKey was interrupted by a CDKeysAuthReply call, which has set the right error message
// the invalid keys have also been cleared in the process
sessLocal . MessageBox ( MSG_OK , sessLocal . GetAuthMsg ( ) , common - > GetLanguageDict ( ) - > GetString ( " #str_04310 " ) , true , NULL , NULL , true ) ;
canExit = false ;
}
}
if ( canExit ) {
// make sure that's saved on file
sessLocal . WriteCDKey ( ) ;
sessLocal . MessageBox ( MSG_OK , common - > GetLanguageDict ( ) - > GetString ( " #str_04307 " ) , common - > GetLanguageDict ( ) - > GetString ( " #str_04305 " ) , true , NULL , NULL , true ) ;
break ;
}
} else {
// offline check sees key invalid
// build a message about keys being wrong. do not attempt to change the current key state though
// ( the keys may be valid, but user would have clicked on the dialog anyway, that kind of thing )
idStr msg ;
idAsyncNetwork : : BuildInvalidKeyMsg ( msg , valid ) ;
sessLocal . MessageBox ( MSG_OK , msg , common - > GetLanguageDict ( ) - > GetString ( " #str_04310 " ) , true , NULL , NULL , true ) ;
}
} else if ( args . Argc ( ) = = 2 & & idStr : : Icmp ( args . Argv ( 1 ) , " force " ) = = 0 ) {
// cancelled in force mode
cmdSystem - > BufferCommandText ( CMD_EXEC_APPEND , " quit \n " ) ;
cmdSystem - > ExecuteCommandBuffer ( ) ;
}
} while ( retkey ) ;
recursed = false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
SESSION LOCAL
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Clear
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : Clear ( ) {
insideUpdateScreen = false ;
insideExecuteMapChange = false ;
loadingSaveGame = false ;
savegameFile = NULL ;
savegameVersion = 0 ;
currentMapName . Clear ( ) ;
aviDemoShortName . Clear ( ) ;
msgFireBack [ 0 ] . Clear ( ) ;
msgFireBack [ 1 ] . Clear ( ) ;
timeHitch = 0 ;
rw = NULL ;
sw = NULL ;
menuSoundWorld = NULL ;
readDemo = NULL ;
writeDemo = NULL ;
renderdemoVersion = 0 ;
cmdDemoFile = NULL ;
syncNextGameFrame = false ;
mapSpawned = false ;
guiActive = NULL ;
aviCaptureMode = false ;
timeDemo = TD_NO ;
waitingOnBind = false ;
lastPacifierTime = 0 ;
msgRunning = false ;
guiMsgRestore = NULL ;
msgIgnoreButtons = false ;
bytesNeededForMapLoad = 0 ;
# if ID_CONSOLE_LOCK
emptyDrawCount = 0 ;
# endif
ClearWipe ( ) ;
loadGameList . Clear ( ) ;
modsList . Clear ( ) ;
authEmitTimeout = 0 ;
authWaitBox = false ;
authMsg . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : idSessionLocal
= = = = = = = = = = = = = = =
*/
idSessionLocal : : idSessionLocal ( ) {
guiInGame = guiMainMenu = guiIntro \
= guiRestartMenu = guiLoading = guiGameOver = guiActive \
= guiTest = guiMsg = guiMsgRestore = guiTakeNotes = NULL ;
menuSoundWorld = NULL ;
demoversion = false ;
Clear ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : ~ idSessionLocal
= = = = = = = = = = = = = = =
*/
idSessionLocal : : ~ idSessionLocal ( ) {
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Stop
called on errors and game exits
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : Stop ( ) {
ClearWipe ( ) ;
// clear mapSpawned and demo playing flags
UnloadMap ( ) ;
// disconnect async client
idAsyncNetwork : : client . DisconnectFromServer ( ) ;
// kill async server
idAsyncNetwork : : server . Kill ( ) ;
if ( sw ) {
sw - > StopAllSounds ( ) ;
}
insideUpdateScreen = false ;
insideExecuteMapChange = false ;
// drop all guis
SetGUI ( NULL , NULL ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Shutdown
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : Shutdown ( ) {
int i ;
if ( aviCaptureMode ) {
EndAVICapture ( ) ;
}
if ( timeDemo = = TD_YES ) {
// else the game freezes when showing the timedemo results
timeDemo = TD_YES_THEN_QUIT ;
}
Stop ( ) ;
if ( rw ) {
delete rw ;
rw = NULL ;
}
if ( sw ) {
delete sw ;
sw = NULL ;
}
if ( menuSoundWorld ) {
delete menuSoundWorld ;
menuSoundWorld = NULL ;
}
mapSpawnData . serverInfo . Clear ( ) ;
mapSpawnData . syncedCVars . Clear ( ) ;
for ( i = 0 ; i < MAX_ASYNC_CLIENTS ; i + + ) {
mapSpawnData . userInfo [ i ] . Clear ( ) ;
mapSpawnData . persistentPlayerInfo [ i ] . Clear ( ) ;
}
if ( guiMainMenu_MapList ! = NULL ) {
guiMainMenu_MapList - > Shutdown ( ) ;
uiManager - > FreeListGUI ( guiMainMenu_MapList ) ;
guiMainMenu_MapList = NULL ;
}
Clear ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : IsMultiplayer
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : IsMultiplayer ( ) {
return idAsyncNetwork : : IsActive ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : StartWipe
Draws and captures the current state , then starts a wipe with that image
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : StartWipe ( const char * _wipeMaterial , bool hold ) {
console - > Close ( ) ;
// render the current screen into a texture for the wipe model
renderSystem - > CropRenderSize ( 640 , 480 , true ) ;
Draw ( ) ;
renderSystem - > CaptureRenderToImage ( " _scratch " ) ;
renderSystem - > UnCrop ( ) ;
wipeMaterial = declManager - > FindMaterial ( _wipeMaterial , false ) ;
wipeStartTic = com_ticNumber ;
wipeStopTic = wipeStartTic + 1000.0f / USERCMD_MSEC * com_wipeSeconds . GetFloat ( ) ;
wipeHold = hold ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : CompleteWipe
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : CompleteWipe ( ) {
if ( com_ticNumber = = 0 ) {
// if the async thread hasn't started, we would hang here
wipeStopTic = 0 ;
UpdateScreen ( true ) ;
return ;
}
while ( com_ticNumber < wipeStopTic ) {
# if ID_CONSOLE_LOCK
emptyDrawCount = 0 ;
# endif
UpdateScreen ( true ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : ShowLoadingGui
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : ShowLoadingGui ( ) {
if ( com_ticNumber = = 0 ) {
return ;
}
console - > Close ( ) ;
// introduced in D3XP code. don't think it actually fixes anything, but doesn't hurt either
# if 1
// Try and prevent the while loop from being skipped over (long hitch on the main thread?)
int stop = Sys_Milliseconds ( ) + 1000 ;
int force = 10 ;
while ( Sys_Milliseconds ( ) < stop | | force - - > 0 ) {
com_frameTime = com_ticNumber * USERCMD_MSEC ;
session - > Frame ( ) ;
session - > UpdateScreen ( false ) ;
}
# else
int stop = com_ticNumber + 1000.0f / USERCMD_MSEC * 1.0f ;
while ( com_ticNumber < stop ) {
com_frameTime = com_ticNumber * USERCMD_MSEC ;
session - > Frame ( ) ;
session - > UpdateScreen ( false ) ;
}
# endif
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : ClearWipe
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : ClearWipe ( void ) {
wipeHold = false ;
wipeStopTic = 0 ;
wipeStartTic = wipeStopTic + 1 ;
}
/*
= = = = = = = = = = = = = = = =
Session_TestGUI_f
= = = = = = = = = = = = = = = =
*/
static void Session_TestGUI_f ( const idCmdArgs & args ) {
sessLocal . TestGUI ( args . Argv ( 1 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : TestGUI
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : TestGUI ( const char * guiName ) {
if ( guiName & & * guiName ) {
guiTest = uiManager - > FindGui ( guiName , true , false , true ) ;
} else {
guiTest = NULL ;
}
}
/*
= = = = = = = = = = = = = = = =
FindUnusedFileName
= = = = = = = = = = = = = = = =
*/
static idStr FindUnusedFileName ( const char * format ) {
int i ;
char filename [ 1024 ] ;
for ( i = 0 ; i < 999 ; i + + ) {
sprintf ( filename , format , i ) ;
int len = fileSystem - > ReadFile ( filename , NULL , NULL ) ;
if ( len < = 0 ) {
return filename ; // file doesn't exist
}
}
return filename ;
}
/*
= = = = = = = = = = = = = = = =
Session_DemoShot_f
= = = = = = = = = = = = = = = =
*/
static void Session_DemoShot_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) ! = 2 ) {
idStr filename = FindUnusedFileName ( " demos/shot%03i.demo " ) ;
sessLocal . DemoShot ( filename ) ;
} else {
sessLocal . DemoShot ( va ( " demos/shot_%s.demo " , args . Argv ( 1 ) ) ) ;
}
}
# ifndef ID_DEDICATED
/*
= = = = = = = = = = = = = = = =
Session_RecordDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_RecordDemo_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) ! = 2 ) {
idStr filename = FindUnusedFileName ( " demos/demo%03i.demo " ) ;
sessLocal . StartRecordingRenderDemo ( filename ) ;
} else {
sessLocal . StartRecordingRenderDemo ( va ( " demos/%s.demo " , args . Argv ( 1 ) ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_CompressDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_CompressDemo_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) = = 2 ) {
sessLocal . CompressDemoFile ( " 2 " , args . Argv ( 1 ) ) ;
} else if ( args . Argc ( ) = = 3 ) {
sessLocal . CompressDemoFile ( args . Argv ( 2 ) , args . Argv ( 1 ) ) ;
} else {
common - > Printf ( " use: CompressDemo <file> [scheme] \n scheme is the same as com_compressDemo, defaults to 2 " ) ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_StopRecordingDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_StopRecordingDemo_f ( const idCmdArgs & args ) {
sessLocal . StopRecordingRenderDemo ( ) ;
}
/*
= = = = = = = = = = = = = = = =
Session_PlayDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_PlayDemo_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) > = 2 ) {
sessLocal . StartPlayingRenderDemo ( va ( " demos/%s " , args . Argv ( 1 ) ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_TimeDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_TimeDemo_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) > = 2 ) {
sessLocal . TimeRenderDemo ( va ( " demos/%s " , args . Argv ( 1 ) ) , ( args . Argc ( ) > 2 ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_TimeDemoQuit_f
= = = = = = = = = = = = = = = =
*/
static void Session_TimeDemoQuit_f ( const idCmdArgs & args ) {
sessLocal . TimeRenderDemo ( va ( " demos/%s " , args . Argv ( 1 ) ) ) ;
if ( sessLocal . timeDemo = = TD_YES ) {
// this allows hardware vendors to automate some testing
sessLocal . timeDemo = TD_YES_THEN_QUIT ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_AVIDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_AVIDemo_f ( const idCmdArgs & args ) {
sessLocal . AVIRenderDemo ( va ( " demos/%s " , args . Argv ( 1 ) ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Session_AVIGame_f
= = = = = = = = = = = = = = = =
*/
static void Session_AVIGame_f ( const idCmdArgs & args ) {
sessLocal . AVIGame ( args . Argv ( 1 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Session_AVICmdDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_AVICmdDemo_f ( const idCmdArgs & args ) {
sessLocal . AVICmdDemo ( args . Argv ( 1 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Session_WriteCmdDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_WriteCmdDemo_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) = = 1 ) {
idStr filename = FindUnusedFileName ( " demos/cmdDemo%03i.cdemo " ) ;
sessLocal . WriteCmdDemo ( filename ) ;
} else if ( args . Argc ( ) = = 2 ) {
sessLocal . WriteCmdDemo ( va ( " demos/%s.cdemo " , args . Argv ( 1 ) ) ) ;
} else {
common - > Printf ( " usage: writeCmdDemo [demoName] \n " ) ;
}
}
/*
= = = = = = = = = = = = = = = =
Session_PlayCmdDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_PlayCmdDemo_f ( const idCmdArgs & args ) {
sessLocal . StartPlayingCmdDemo ( args . Argv ( 1 ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Session_TimeCmdDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_TimeCmdDemo_f ( const idCmdArgs & args ) {
sessLocal . TimeCmdDemo ( args . Argv ( 1 ) ) ;
}
# endif
/*
= = = = = = = = = = = = = = = =
Session_Disconnect_f
= = = = = = = = = = = = = = = =
*/
static void Session_Disconnect_f ( const idCmdArgs & args ) {
sessLocal . Stop ( ) ;
sessLocal . StartMenu ( ) ;
if ( soundSystem ) {
soundSystem - > SetMute ( false ) ;
}
}
# ifndef ID_DEDICATED
/*
= = = = = = = = = = = = = = = =
Session_ExitCmdDemo_f
= = = = = = = = = = = = = = = =
*/
static void Session_ExitCmdDemo_f ( const idCmdArgs & args ) {
if ( ! sessLocal . cmdDemoFile ) {
common - > Printf ( " not reading from a cmdDemo \n " ) ;
return ;
}
fileSystem - > CloseFile ( sessLocal . cmdDemoFile ) ;
common - > Printf ( " Command demo exited at logIndex %i \n " , sessLocal . logIndex ) ;
sessLocal . cmdDemoFile = NULL ;
}
# endif
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : StartRecordingRenderDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : StartRecordingRenderDemo ( const char * demoName ) {
if ( writeDemo ) {
// allow it to act like a toggle
StopRecordingRenderDemo ( ) ;
return ;
}
if ( ! demoName [ 0 ] ) {
common - > Printf ( " idSessionLocal::StartRecordingRenderDemo: no name specified \n " ) ;
return ;
}
console - > Close ( ) ;
writeDemo = new idDemoFile ;
if ( ! writeDemo - > OpenForWriting ( demoName ) ) {
common - > Printf ( " error opening %s \n " , demoName ) ;
delete writeDemo ;
writeDemo = NULL ;
return ;
}
common - > Printf ( " recording to %s \n " , writeDemo - > GetName ( ) ) ;
writeDemo - > WriteInt ( DS_VERSION ) ;
writeDemo - > WriteInt ( RENDERDEMO_VERSION ) ;
// if we are in a map already, dump the current state
sw - > StartWritingDemo ( writeDemo ) ;
rw - > StartWritingDemo ( writeDemo ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : StopRecordingRenderDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : StopRecordingRenderDemo ( ) {
if ( ! writeDemo ) {
common - > Printf ( " idSessionLocal::StopRecordingRenderDemo: not recording \n " ) ;
return ;
}
sw - > StopWritingDemo ( ) ;
rw - > StopWritingDemo ( ) ;
writeDemo - > Close ( ) ;
common - > Printf ( " stopped recording %s. \n " , writeDemo - > GetName ( ) ) ;
delete writeDemo ;
writeDemo = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : StopPlayingRenderDemo
Reports timeDemo numbers and finishes any avi recording
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : StopPlayingRenderDemo ( ) {
if ( ! readDemo ) {
timeDemo = TD_NO ;
return ;
}
// Record the stop time before doing anything that could be time consuming
int timeDemoStopTime = Sys_Milliseconds ( ) ;
EndAVICapture ( ) ;
readDemo - > Close ( ) ;
sw - > StopAllSounds ( ) ;
soundSystem - > SetPlayingSoundWorld ( menuSoundWorld ) ;
common - > Printf ( " stopped playing %s. \n " , readDemo - > GetName ( ) ) ;
delete readDemo ;
readDemo = NULL ;
if ( timeDemo ) {
// report the stats
float demoSeconds = ( timeDemoStopTime - timeDemoStartTime ) * 0.001f ;
float demoFPS = numDemoFrames / demoSeconds ;
idStr message = va ( " %i frames rendered in %3.1f seconds = %3.1f fps \n " , numDemoFrames , demoSeconds , demoFPS ) ;
common - > Printf ( message ) ;
if ( timeDemo = = TD_YES_THEN_QUIT ) {
cmdSystem - > BufferCommandText ( CMD_EXEC_APPEND , " quit \n " ) ;
} else {
soundSystem - > SetMute ( true ) ;
MessageBox ( MSG_OK , message , " Time Demo Results " , true ) ;
soundSystem - > SetMute ( false ) ;
}
timeDemo = TD_NO ;
}
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : DemoShot
A demoShot is a single frame demo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : DemoShot ( const char * demoName ) {
StartRecordingRenderDemo ( demoName ) ;
// force draw one frame
UpdateScreen ( ) ;
StopRecordingRenderDemo ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : StartPlayingRenderDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : StartPlayingRenderDemo ( idStr demoName ) {
if ( ! demoName [ 0 ] ) {
common - > Printf ( " idSessionLocal::StartPlayingRenderDemo: no name specified \n " ) ;
return ;
}
// make sure localSound / GUI intro music shuts up
sw - > StopAllSounds ( ) ;
sw - > PlayShaderDirectly ( " " , 0 ) ;
menuSoundWorld - > StopAllSounds ( ) ;
menuSoundWorld - > PlayShaderDirectly ( " " , 0 ) ;
// exit any current game
Stop ( ) ;
// automatically put the console away
console - > Close ( ) ;
// bring up the loading screen manually, since demos won't
// call ExecuteMapChange()
guiLoading = uiManager - > FindGui ( " guis/map/loading.gui " , true , false , true ) ;
guiLoading - > SetStateString ( " demo " , common - > GetLanguageDict ( ) - > GetString ( " #str_02087 " ) ) ;
readDemo = new idDemoFile ;
demoName . DefaultFileExtension ( " .demo " ) ;
if ( ! readDemo - > OpenForReading ( demoName ) ) {
common - > Printf ( " couldn't open %s \n " , demoName . c_str ( ) ) ;
delete readDemo ;
readDemo = NULL ;
Stop ( ) ;
StartMenu ( ) ;
soundSystem - > SetMute ( false ) ;
return ;
}
insideExecuteMapChange = true ;
UpdateScreen ( ) ;
insideExecuteMapChange = false ;
guiLoading - > SetStateString ( " demo " , " " ) ;
// setup default render demo settings
// that's default for <= Doom3 v1.1
renderdemoVersion = 1 ;
savegameVersion = 16 ;
AdvanceRenderDemo ( true ) ;
numDemoFrames = 1 ;
lastDemoTic = - 1 ;
timeDemoStartTime = Sys_Milliseconds ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : TimeRenderDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : TimeRenderDemo ( const char * demoName , bool twice ) {
idStr demo = demoName ;
// no sound in time demos
soundSystem - > SetMute ( true ) ;
StartPlayingRenderDemo ( demo ) ;
if ( twice & & readDemo ) {
// cycle through once to precache everything
guiLoading - > SetStateString ( " demo " , common - > GetLanguageDict ( ) - > GetString ( " #str_04852 " ) ) ;
guiLoading - > StateChanged ( com_frameTime ) ;
while ( readDemo ) {
insideExecuteMapChange = true ;
UpdateScreen ( ) ;
insideExecuteMapChange = false ;
AdvanceRenderDemo ( true ) ;
}
guiLoading - > SetStateString ( " demo " , " " ) ;
StartPlayingRenderDemo ( demo ) ;
}
if ( ! readDemo ) {
return ;
}
timeDemo = TD_YES ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : BeginAVICapture
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : BeginAVICapture ( const char * demoName ) {
idStr name = demoName ;
name . ExtractFileBase ( aviDemoShortName ) ;
aviCaptureMode = true ;
aviDemoFrameCount = 0 ;
aviTicStart = 0 ;
sw - > AVIOpen ( va ( " demos/%s/ " , aviDemoShortName . c_str ( ) ) , aviDemoShortName . c_str ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : EndAVICapture
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : EndAVICapture ( ) {
if ( ! aviCaptureMode ) {
return ;
}
sw - > AVIClose ( ) ;
// write a .roqParam file so the demo can be converted to a roq file
idFile * f = fileSystem - > OpenFileWrite ( va ( " demos/%s/%s.roqParam " ,
aviDemoShortName . c_str ( ) , aviDemoShortName . c_str ( ) ) ) ;
f - > Printf ( " INPUT_DIR demos/%s \n " , aviDemoShortName . c_str ( ) ) ;
f - > Printf ( " FILENAME demos/%s/%s.RoQ \n " , aviDemoShortName . c_str ( ) , aviDemoShortName . c_str ( ) ) ;
f - > Printf ( " \n INPUT \n " ) ;
f - > Printf ( " %s_*.tga [00000-%05i] \n " , aviDemoShortName . c_str ( ) , ( int ) ( aviDemoFrameCount - 1 ) ) ;
f - > Printf ( " END_INPUT \n " ) ;
delete f ;
common - > Printf ( " captured %i frames for %s. \n " , ( int ) aviDemoFrameCount , aviDemoShortName . c_str ( ) ) ;
aviCaptureMode = false ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : AVIRenderDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : AVIRenderDemo ( const char * _demoName ) {
idStr demoName = _demoName ; // copy off from va() buffer
StartPlayingRenderDemo ( demoName ) ;
if ( ! readDemo ) {
return ;
}
BeginAVICapture ( demoName . c_str ( ) ) ;
// I don't understand why I need to do this twice, something
// strange with the nvidia swapbuffers?
UpdateScreen ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : AVICmdDemo
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : AVICmdDemo ( const char * demoName ) {
StartPlayingCmdDemo ( demoName ) ;
BeginAVICapture ( demoName ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : AVIGame
Start AVI recording the current game session
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : AVIGame ( const char * demoName ) {
if ( aviCaptureMode ) {
EndAVICapture ( ) ;
return ;
}
if ( ! mapSpawned ) {
common - > Printf ( " No map spawned. \n " ) ;
}
if ( ! demoName | | ! demoName [ 0 ] ) {
idStr filename = FindUnusedFileName ( " demos/game%03i.game " ) ;
demoName = filename . c_str ( ) ;
// write a one byte stub .game file just so the FindUnusedFileName works,
fileSystem - > WriteFile ( demoName , demoName , 1 ) ;
}
BeginAVICapture ( demoName ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : CompressDemoFile
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : CompressDemoFile ( const char * scheme , const char * demoName ) {
idStr fullDemoName = " demos/ " ;
fullDemoName + = demoName ;
fullDemoName . DefaultFileExtension ( " .demo " ) ;
idStr compressedName = fullDemoName ;
compressedName . StripFileExtension ( ) ;
compressedName . Append ( " _compressed.demo " ) ;
int savedCompression = cvarSystem - > GetCVarInteger ( " com_compressDemos " ) ;
bool savedPreload = cvarSystem - > GetCVarBool ( " com_preloadDemos " ) ;
cvarSystem - > SetCVarBool ( " com_preloadDemos " , false ) ;
cvarSystem - > SetCVarInteger ( " com_compressDemos " , atoi ( scheme ) ) ;
idDemoFile demoread , demowrite ;
if ( ! demoread . OpenForReading ( fullDemoName ) ) {
common - > Printf ( " Could not open %s for reading \n " , fullDemoName . c_str ( ) ) ;
return ;
}
if ( ! demowrite . OpenForWriting ( compressedName ) ) {
common - > Printf ( " Could not open %s for writing \n " , compressedName . c_str ( ) ) ;
demoread . Close ( ) ;
cvarSystem - > SetCVarBool ( " com_preloadDemos " , savedPreload ) ;
cvarSystem - > SetCVarInteger ( " com_compressDemos " , savedCompression ) ;
return ;
}
common - > SetRefreshOnPrint ( true ) ;
common - > Printf ( " Compressing %s to %s... \n " , fullDemoName . c_str ( ) , compressedName . c_str ( ) ) ;
static const int bufferSize = 65535 ;
char buffer [ bufferSize ] ;
int bytesRead ;
while ( 0 ! = ( bytesRead = demoread . Read ( buffer , bufferSize ) ) ) {
demowrite . Write ( buffer , bytesRead ) ;
common - > Printf ( " . " ) ;
}
demoread . Close ( ) ;
demowrite . Close ( ) ;
cvarSystem - > SetCVarBool ( " com_preloadDemos " , savedPreload ) ;
cvarSystem - > SetCVarInteger ( " com_compressDemos " , savedCompression ) ;
common - > Printf ( " Done \n " ) ;
common - > SetRefreshOnPrint ( false ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : StartNewGame
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : StartNewGame ( const char * mapName , bool devmap ) {
# ifdef ID_DEDICATED
common - > Printf ( " Dedicated servers cannot start singleplayer games. \n " ) ;
return ;
# else
# if ID_ENFORCE_KEY
// strict check. don't let a game start without a definitive answer
if ( ! CDKeysAreValid ( true ) ) {
bool prompt = true ;
if ( MaybeWaitOnCDKey ( ) ) {
// check again, maybe we just needed more time
if ( CDKeysAreValid ( true ) ) {
// can continue directly
prompt = false ;
}
}
if ( prompt ) {
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , " promptKey force " ) ;
cmdSystem - > ExecuteCommandBuffer ( ) ;
}
}
# endif
if ( idAsyncNetwork : : server . IsActive ( ) ) {
common - > Printf ( " Server running, use si_map / serverMapRestart \n " ) ;
return ;
}
if ( idAsyncNetwork : : client . IsActive ( ) ) {
common - > Printf ( " Client running, disconnect from server first \n " ) ;
return ;
}
// clear the userInfo so the player starts out with the defaults
mapSpawnData . userInfo [ 0 ] . Clear ( ) ;
mapSpawnData . persistentPlayerInfo [ 0 ] . Clear ( ) ;
mapSpawnData . userInfo [ 0 ] = * cvarSystem - > MoveCVarsToDict ( CVAR_USERINFO ) ;
mapSpawnData . serverInfo . Clear ( ) ;
mapSpawnData . serverInfo = * cvarSystem - > MoveCVarsToDict ( CVAR_SERVERINFO ) ;
mapSpawnData . serverInfo . Set ( " si_gameType " , " singleplayer " ) ;
// set the devmap key so any play testing items will be given at
// spawn time to set approximately the right weapons and ammo
if ( devmap ) {
mapSpawnData . serverInfo . Set ( " devmap " , " 1 " ) ;
}
mapSpawnData . syncedCVars . Clear ( ) ;
mapSpawnData . syncedCVars = * cvarSystem - > MoveCVarsToDict ( CVAR_NETWORKSYNC ) ;
MoveToNewMap ( mapName ) ;
# endif
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetAutoSaveName
= = = = = = = = = = = = = = =
*/
idStr idSessionLocal : : GetAutoSaveName ( const char * mapName ) const {
const idDecl * mapDecl = declManager - > FindType ( DECL_MAPDEF , mapName , false ) ;
const idDeclEntityDef * mapDef = static_cast < const idDeclEntityDef * > ( mapDecl ) ;
if ( mapDef ) {
mapName = common - > GetLanguageDict ( ) - > GetString ( mapDef - > dict . GetString ( " name " , mapName ) ) ;
}
// Fixme: Localization
return va ( " ^3AutoSave:^0 %s " , mapName ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : MoveToNewMap
Leaves the existing userinfo and serverinfo
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : MoveToNewMap ( const char * mapName ) {
mapSpawnData . serverInfo . Set ( " si_map " , mapName ) ;
ExecuteMapChange ( ) ;
if ( ! mapSpawnData . serverInfo . GetBool ( " devmap " ) ) {
// Autosave at the beginning of the level
// DG: set an explicit savename to avoid problems with autosave names
// (they were translated which caused problems like all alpha labs parts
// getting the same filename in spanish, probably because the strings contained
// dots and everything behind them was cut off as "file extension".. see #305)
idStr saveFileName = " Autosave_ " ;
saveFileName + = mapName ;
SaveGame ( GetAutoSaveName ( mapName ) , true , saveFileName ) ;
}
SetGUI ( NULL , NULL ) ;
}
/*
= = = = = = = = = = = = = =
SaveCmdDemoFromFile
= = = = = = = = = = = = = =
*/
void idSessionLocal : : SaveCmdDemoToFile ( idFile * file ) {
mapSpawnData . serverInfo . WriteToFileHandle ( file ) ;
for ( int i = 0 ; i < MAX_ASYNC_CLIENTS ; i + + ) {
mapSpawnData . userInfo [ i ] . WriteToFileHandle ( file ) ;
mapSpawnData . persistentPlayerInfo [ i ] . WriteToFileHandle ( file ) ;
}
file - > Write ( & mapSpawnData . mapSpawnUsercmd , sizeof ( mapSpawnData . mapSpawnUsercmd ) ) ;
if ( numClients < 1 ) {
numClients = 1 ;
}
file - > Write ( loggedUsercmds , numClients * logIndex * sizeof ( loggedUsercmds [ 0 ] ) ) ;
}
/*
= = = = = = = = = = = = = =
idSessionLocal : : LoadCmdDemoFromFile
= = = = = = = = = = = = = =
*/
void idSessionLocal : : LoadCmdDemoFromFile ( idFile * file ) {
mapSpawnData . serverInfo . ReadFromFileHandle ( file ) ;
for ( int i = 0 ; i < MAX_ASYNC_CLIENTS ; i + + ) {
mapSpawnData . userInfo [ i ] . ReadFromFileHandle ( file ) ;
mapSpawnData . persistentPlayerInfo [ i ] . ReadFromFileHandle ( file ) ;
}
file - > Read ( & mapSpawnData . mapSpawnUsercmd , sizeof ( mapSpawnData . mapSpawnUsercmd ) ) ;
}
/*
= = = = = = = = = = = = = =
idSessionLocal : : WriteCmdDemo
Dumps the accumulated commands for the current level .
This should still work after disconnecting from a level
= = = = = = = = = = = = = =
*/
void idSessionLocal : : WriteCmdDemo ( const char * demoName , bool save ) {
if ( ! demoName [ 0 ] ) {
common - > Printf ( " idSessionLocal::WriteCmdDemo: no name specified \n " ) ;
return ;
}
idStr statsName ;
if ( save ) {
statsName = demoName ;
statsName . StripFileExtension ( ) ;
statsName . DefaultFileExtension ( " .stats " ) ;
}
common - > Printf ( " writing save data to %s \n " , demoName ) ;
idFile * cmdDemoFile = fileSystem - > OpenFileWrite ( demoName ) ;
if ( ! cmdDemoFile ) {
common - > Printf ( " Couldn't open for writing %s \n " , demoName ) ;
return ;
}
if ( save ) {
cmdDemoFile - > Write ( & logIndex , sizeof ( logIndex ) ) ;
}
SaveCmdDemoToFile ( cmdDemoFile ) ;
if ( save ) {
idFile * statsFile = fileSystem - > OpenFileWrite ( statsName ) ;
if ( statsFile ) {
statsFile - > Write ( & statIndex , sizeof ( statIndex ) ) ;
statsFile - > Write ( loggedStats , numClients * statIndex * sizeof ( loggedStats [ 0 ] ) ) ;
fileSystem - > CloseFile ( statsFile ) ;
}
}
fileSystem - > CloseFile ( cmdDemoFile ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : FinishCmdLoad
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : FinishCmdLoad ( ) {
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : StartPlayingCmdDemo
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : StartPlayingCmdDemo ( const char * demoName ) {
// exit any current game
Stop ( ) ;
idStr fullDemoName = " demos/ " ;
fullDemoName + = demoName ;
fullDemoName . DefaultFileExtension ( " .cdemo " ) ;
cmdDemoFile = fileSystem - > OpenFileRead ( fullDemoName ) ;
if ( cmdDemoFile = = NULL ) {
common - > Printf ( " Couldn't open %s \n " , fullDemoName . c_str ( ) ) ;
return ;
}
guiLoading = uiManager - > FindGui ( " guis/map/loading.gui " , true , false , true ) ;
//cmdDemoFile->Read(&loadGameTime, sizeof(loadGameTime));
LoadCmdDemoFromFile ( cmdDemoFile ) ;
// start the map
ExecuteMapChange ( ) ;
cmdDemoFile = fileSystem - > OpenFileRead ( fullDemoName ) ;
// have to do this twice as the execmapchange clears the cmddemofile
LoadCmdDemoFromFile ( cmdDemoFile ) ;
// run one frame to get the view angles correct
RunGameTic ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : TimeCmdDemo
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : TimeCmdDemo ( const char * demoName ) {
StartPlayingCmdDemo ( demoName ) ;
ClearWipe ( ) ;
UpdateScreen ( ) ;
int startTime = Sys_Milliseconds ( ) ;
int count = 0 ;
int minuteStart , minuteEnd ;
float sec ;
// run all the frames in sequence
minuteStart = startTime ;
while ( cmdDemoFile ) {
RunGameTic ( ) ;
count + + ;
if ( count / 3600 ! = ( count - 1 ) / 3600 ) {
minuteEnd = Sys_Milliseconds ( ) ;
sec = ( minuteEnd - minuteStart ) / 1000.0 ;
minuteStart = minuteEnd ;
common - > Printf ( " minute %i took %3.1f seconds \n " , count / 3600 , sec ) ;
UpdateScreen ( ) ;
}
}
int endTime = Sys_Milliseconds ( ) ;
sec = ( endTime - startTime ) / 1000.0 ;
common - > Printf ( " %i seconds of game, replayed in %5.1f seconds \n " , count / 60 , sec ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : UnloadMap
Performs cleanup that needs to happen between maps , or when a
game is exited .
Exits with mapSpawned = false
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : UnloadMap ( ) {
StopPlayingRenderDemo ( ) ;
// end the current map in the game
if ( game ) {
game - > MapShutdown ( ) ;
}
if ( cmdDemoFile ) {
fileSystem - > CloseFile ( cmdDemoFile ) ;
cmdDemoFile = NULL ;
}
if ( writeDemo ) {
StopRecordingRenderDemo ( ) ;
}
mapSpawned = false ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : LoadLoadingGui
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : LoadLoadingGui ( const char * mapName ) {
// load / program a gui to stay up on the screen while loading
idStr stripped = mapName ;
stripped . StripFileExtension ( ) ;
stripped . StripPath ( ) ;
char guiMap [ MAX_STRING_CHARS ] ;
strncpy ( guiMap , va ( " guis/map/%s.gui " , stripped . c_str ( ) ) , MAX_STRING_CHARS ) ;
// give the gamecode a chance to override
game - > GetMapLoadingGUI ( guiMap ) ;
if ( uiManager - > CheckGui ( guiMap ) ) {
guiLoading = uiManager - > FindGui ( guiMap , true , false , true ) ;
} else {
guiLoading = uiManager - > FindGui ( " guis/map/loading.gui " , true , false , true ) ;
}
guiLoading - > SetStateFloat ( " map_loading " , 0.0f ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetBytesNeededForMapLoad
= = = = = = = = = = = = = = =
*/
int idSessionLocal : : GetBytesNeededForMapLoad ( const char * mapName ) {
const idDecl * mapDecl = declManager - > FindType ( DECL_MAPDEF , mapName , false ) ;
const idDeclEntityDef * mapDef = static_cast < const idDeclEntityDef * > ( mapDecl ) ;
if ( mapDef ) {
return mapDef - > dict . GetInt ( va ( " size%d " , Max ( 0 , com_machineSpec . GetInteger ( ) ) ) ) ;
} else {
if ( com_machineSpec . GetInteger ( ) < 2 ) {
return 200 * 1024 * 1024 ;
} else {
return 400 * 1024 * 1024 ;
}
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : SetBytesNeededForMapLoad
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : SetBytesNeededForMapLoad ( const char * mapName , int bytesNeeded ) {
idDecl * mapDecl = const_cast < idDecl * > ( declManager - > FindType ( DECL_MAPDEF , mapName , false ) ) ;
idDeclEntityDef * mapDef = static_cast < idDeclEntityDef * > ( mapDecl ) ;
if ( com_updateLoadSize . GetBool ( ) & & mapDef ) {
// we assume that if com_updateLoadSize is true then the file is writable
mapDef - > dict . SetInt ( va ( " size%d " , com_machineSpec . GetInteger ( ) ) , bytesNeeded ) ;
idStr declText = " \n mapDef " ;
declText + = mapDef - > GetName ( ) ;
declText + = " { \n " ;
for ( int i = 0 ; i < mapDef - > dict . GetNumKeyVals ( ) ; i + + ) {
const idKeyValue * kv = mapDef - > dict . GetKeyVal ( i ) ;
if ( kv & & ( kv - > GetKey ( ) . Cmp ( " classname " ) ! = 0 ) ) {
declText + = " \t \" " + kv - > GetKey ( ) + " \" \t \t \" " + kv - > GetValue ( ) + " \" \n " ;
}
}
declText + = " } " ;
mapDef - > SetText ( declText ) ;
mapDef - > ReplaceSourceFileText ( ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : ExecuteMapChange
Performs the initialization of a game based on mapSpawnData , used for both single
player and multiplayer , but not for renderDemos , which don ' t
create a game at all .
Exits with mapSpawned = true
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : ExecuteMapChange ( bool noFadeWipe ) {
int i ;
bool reloadingSameMap ;
// close console and remove any prints from the notify lines
console - > Close ( ) ;
if ( IsMultiplayer ( ) ) {
// make sure the mp GUI isn't up, or when players get back in the
// map, mpGame's menu and the gui will be out of sync.
SetGUI ( NULL , NULL ) ;
}
// mute sound
soundSystem - > SetMute ( true ) ;
// clear all menu sounds
menuSoundWorld - > ClearAllSoundEmitters ( ) ;
// unpause the game sound world
// NOTE: we UnPause again later down. not sure this is needed
if ( sw - > IsPaused ( ) ) {
sw - > UnPause ( ) ;
}
if ( ! noFadeWipe ) {
// capture the current screen and start a wipe
StartWipe ( " wipeMaterial " , true ) ;
// immediately complete the wipe to fade out the level transition
// run the wipe to completion
CompleteWipe ( ) ;
}
// extract the map name from serverinfo
idStr mapString = mapSpawnData . serverInfo . GetString ( " si_map " ) ;
idStr fullMapName = " maps/ " ;
fullMapName + = mapString ;
fullMapName . StripFileExtension ( ) ;
// shut down the existing game if it is running
UnloadMap ( ) ;
// don't do the deferred caching if we are reloading the same map
if ( fullMapName = = currentMapName ) {
reloadingSameMap = true ;
} else {
reloadingSameMap = false ;
currentMapName = fullMapName ;
}
// note which media we are going to need to load
if ( ! reloadingSameMap ) {
declManager - > BeginLevelLoad ( ) ;
renderSystem - > BeginLevelLoad ( ) ;
soundSystem - > BeginLevelLoad ( ) ;
}
uiManager - > BeginLevelLoad ( ) ;
uiManager - > Reload ( true ) ;
// set the loading gui that we will wipe to
LoadLoadingGui ( mapString ) ;
// cause prints to force screen updates as a pacifier,
// and draw the loading gui instead of game draws
insideExecuteMapChange = true ;
// if this works out we will probably want all the sizes in a def file although this solution will
// work for new maps etc. after the first load. we can also drop the sizes into the default.cfg
fileSystem - > ResetReadCount ( ) ;
if ( ! reloadingSameMap ) {
bytesNeededForMapLoad = GetBytesNeededForMapLoad ( mapString . c_str ( ) ) ;
} else {
bytesNeededForMapLoad = 30 * 1024 * 1024 ;
}
ClearWipe ( ) ;
// let the loading gui spin for 1 second to animate out
ShowLoadingGui ( ) ;
// note any warning prints that happen during the load process
common - > ClearWarnings ( mapString ) ;
// release the mouse cursor
// before we do this potentially long operation
Sys_GrabMouseCursor ( false ) ;
// if net play, we get the number of clients during mapSpawnInfo processing
if ( ! idAsyncNetwork : : IsActive ( ) ) {
numClients = 1 ;
}
int start = Sys_Milliseconds ( ) ;
common - > Printf ( " ----- Map Initialization ----- \n " ) ;
common - > Printf ( " Map: %s \n " , mapString . c_str ( ) ) ;
// let the renderSystem load all the geometry
if ( ! rw - > InitFromMap ( fullMapName ) ) {
common - > Error ( " couldn't load %s " , fullMapName . c_str ( ) ) ;
}
// for the synchronous networking we needed to roll the angles over from
// level to level, but now we can just clear everything
usercmdGen - > InitForNewMap ( ) ;
memset ( & mapSpawnData . mapSpawnUsercmd , 0 , sizeof ( mapSpawnData . mapSpawnUsercmd ) ) ;
// set the user info
for ( i = 0 ; i < numClients ; i + + ) {
game - > SetUserInfo ( i , mapSpawnData . userInfo [ i ] , idAsyncNetwork : : client . IsActive ( ) , false ) ;
game - > SetPersistentPlayerInfo ( i , mapSpawnData . persistentPlayerInfo [ i ] ) ;
}
// load and spawn all other entities ( from a savegame possibly )
if ( loadingSaveGame & & savegameFile ) {
if ( game - > InitFromSaveGame ( fullMapName + " .map " , rw , sw , savegameFile ) = = false ) {
// If the loadgame failed, restart the map with the player persistent data
loadingSaveGame = false ;
fileSystem - > CloseFile ( savegameFile ) ;
savegameFile = NULL ;
game - > SetServerInfo ( mapSpawnData . serverInfo ) ;
game - > InitFromNewMap ( fullMapName + " .map " , rw , sw , idAsyncNetwork : : server . IsActive ( ) , idAsyncNetwork : : client . IsActive ( ) , Sys_Milliseconds ( ) ) ;
}
} else {
game - > SetServerInfo ( mapSpawnData . serverInfo ) ;
game - > InitFromNewMap ( fullMapName + " .map " , rw , sw , idAsyncNetwork : : server . IsActive ( ) , idAsyncNetwork : : client . IsActive ( ) , Sys_Milliseconds ( ) ) ;
}
if ( ! idAsyncNetwork : : IsActive ( ) & & ! loadingSaveGame ) {
// spawn players
for ( i = 0 ; i < numClients ; i + + ) {
game - > SpawnPlayer ( i ) ;
}
}
// actually purge/load the media
if ( ! reloadingSameMap ) {
renderSystem - > EndLevelLoad ( ) ;
soundSystem - > EndLevelLoad ( mapString . c_str ( ) ) ;
declManager - > EndLevelLoad ( ) ;
SetBytesNeededForMapLoad ( mapString . c_str ( ) , fileSystem - > GetReadCount ( ) ) ;
}
uiManager - > EndLevelLoad ( ) ;
if ( ! idAsyncNetwork : : IsActive ( ) & & ! loadingSaveGame ) {
// run a few frames to allow everything to settle
for ( i = 0 ; i < 10 ; i + + ) {
game - > RunFrame ( mapSpawnData . mapSpawnUsercmd ) ;
}
}
int msec = Sys_Milliseconds ( ) - start ;
common - > Printf ( " %6d msec to load %s \n " , msec , mapString . c_str ( ) ) ;
// let the renderSystem generate interactions now that everything is spawned
rw - > GenerateAllInteractions ( ) ;
common - > PrintWarnings ( ) ;
if ( guiLoading & & bytesNeededForMapLoad ) {
float pct = guiLoading - > State ( ) . GetFloat ( " map_loading " ) ;
if ( pct < 0.0f ) {
pct = 0.0f ;
}
while ( pct < 1.0f ) {
guiLoading - > SetStateFloat ( " map_loading " , pct ) ;
guiLoading - > StateChanged ( com_frameTime ) ;
Sys_GenerateEvents ( ) ;
UpdateScreen ( ) ;
pct + = 0.05f ;
}
}
// capture the current screen and start a wipe
StartWipe ( " wipe2Material " ) ;
usercmdGen - > Clear ( ) ;
// start saving commands for possible writeCmdDemo usage
logIndex = 0 ;
statIndex = 0 ;
lastSaveIndex = 0 ;
// don't bother spinning over all the tics we spent loading
lastGameTic = latchedTicNumber = com_ticNumber ;
// remove any prints from the notify lines
console - > ClearNotifyLines ( ) ;
// stop drawing the laoding screen
insideExecuteMapChange = false ;
Sys_SetPhysicalWorkMemory ( - 1 , - 1 ) ;
// set the game sound world for playback
soundSystem - > SetPlayingSoundWorld ( sw ) ;
// when loading a save game the sound is paused
if ( sw - > IsPaused ( ) ) {
// unpause the game sound world
sw - > UnPause ( ) ;
}
// restart entity sound playback
soundSystem - > SetMute ( false ) ;
// we are valid for game draws now
mapSpawned = true ;
Sys_ClearEvents ( ) ;
}
/*
= = = = = = = = = = = = = = =
LoadGame_f
= = = = = = = = = = = = = = =
*/
void LoadGame_f ( const idCmdArgs & args ) {
console - > Close ( ) ;
if ( args . Argc ( ) < 2 | | idStr : : Icmp ( args . Argv ( 1 ) , " quick " ) = = 0 ) {
idStr saveName = common - > GetLanguageDict ( ) - > GetString ( " #str_07178 " ) ;
sessLocal . LoadGame ( saveName ) ;
} else {
sessLocal . LoadGame ( args . Argv ( 1 ) ) ;
}
}
/*
= = = = = = = = = = = = = = =
SaveGame_f
= = = = = = = = = = = = = = =
*/
void SaveGame_f ( const idCmdArgs & args ) {
if ( args . Argc ( ) < 2 | | idStr : : Icmp ( args . Argv ( 1 ) , " quick " ) = = 0 ) {
idStr saveName = common - > GetLanguageDict ( ) - > GetString ( " #str_07178 " ) ;
if ( sessLocal . SaveGame ( saveName ) ) {
common - > Printf ( " %s \n " , saveName . c_str ( ) ) ;
}
} else {
if ( sessLocal . SaveGame ( args . Argv ( 1 ) ) ) {
common - > Printf ( " Saved %s \n " , args . Argv ( 1 ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
TakeViewNotes_f
= = = = = = = = = = = = = = =
*/
void TakeViewNotes_f ( const idCmdArgs & args ) {
const char * p = ( args . Argc ( ) > 1 ) ? args . Argv ( 1 ) : " " ;
sessLocal . TakeNotes ( p ) ;
}
/*
= = = = = = = = = = = = = = =
TakeViewNotes2_f
= = = = = = = = = = = = = = =
*/
void TakeViewNotes2_f ( const idCmdArgs & args ) {
const char * p = ( args . Argc ( ) > 1 ) ? args . Argv ( 1 ) : " " ;
sessLocal . TakeNotes ( p , true ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : TakeNotes
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : TakeNotes ( const char * p , bool extended ) {
if ( ! mapSpawned ) {
common - > Printf ( " No map loaded! \n " ) ;
return ;
}
if ( extended ) {
guiTakeNotes = uiManager - > FindGui ( " guis/takeNotes2.gui " , true , false , true ) ;
#if 0
const char * people [ ] = {
" Nobody " , " Adam " , " Brandon " , " David " , " PHook " , " Jay " , " Jake " ,
" PatJ " , " Brett " , " Ted " , " Darin " , " Brian " , " Sean "
} ;
# else
const char * people [ ] = {
" Tim " , " Kenneth " , " Robert " ,
" Matt " , " Mal " , " Jerry " , " Steve " , " Pat " ,
" Xian " , " Ed " , " Fred " , " James " , " Eric " , " Andy " , " Seneca " , " Patrick " , " Kevin " ,
" MrElusive " , " Jim " , " Brian " , " John " , " Adrian " , " Nobody "
} ;
# endif
const int numPeople = sizeof ( people ) / sizeof ( people [ 0 ] ) ;
idListGUI * guiList_people = uiManager - > AllocListGUI ( ) ;
guiList_people - > Config ( guiTakeNotes , " person " ) ;
for ( int i = 0 ; i < numPeople ; i + + ) {
guiList_people - > Push ( people [ i ] ) ;
}
uiManager - > FreeListGUI ( guiList_people ) ;
} else {
guiTakeNotes = uiManager - > FindGui ( " guis/takeNotes.gui " , true , false , true ) ;
}
SetGUI ( guiTakeNotes , NULL ) ;
guiActive - > SetStateString ( " note " , " " ) ;
guiActive - > SetStateString ( " notefile " , p ) ;
guiActive - > SetStateBool ( " extended " , extended ) ;
guiActive - > Activate ( true , com_frameTime ) ;
}
/*
= = = = = = = = = = = = = = =
Session_Hitch_f
= = = = = = = = = = = = = = =
*/
void Session_Hitch_f ( const idCmdArgs & args ) {
idSoundWorld * sw = soundSystem - > GetPlayingSoundWorld ( ) ;
if ( sw ) {
soundSystem - > SetMute ( true ) ;
sw - > Pause ( ) ;
Sys_EnterCriticalSection ( ) ;
}
if ( args . Argc ( ) = = 2 ) {
Sys_Sleep ( atoi ( args . Argv ( 1 ) ) ) ;
} else {
Sys_Sleep ( 100 ) ;
}
if ( sw ) {
Sys_LeaveCriticalSection ( ) ;
sw - > UnPause ( ) ;
soundSystem - > SetMute ( false ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : ScrubSaveGameFileName
Turns a bad file name into a good one or your money back
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : ScrubSaveGameFileName ( idStr & saveFileName ) const {
int i ;
idStr inFileName ;
inFileName = saveFileName ;
inFileName . RemoveColors ( ) ;
inFileName . StripFileExtension ( ) ;
saveFileName . Clear ( ) ;
int len = inFileName . Length ( ) ;
for ( i = 0 ; i < len ; i + + ) {
if ( strchr ( " ',.~!@#$%^&*()[]{}<> \\ |/=?+;:- \' \" " , inFileName [ i ] ) ) {
// random junk
saveFileName + = ' _ ' ;
} else if ( ( const unsigned char ) inFileName [ i ] > = 128 ) {
// high ascii chars
saveFileName + = ' _ ' ;
} else if ( inFileName [ i ] = = ' ' ) {
saveFileName + = ' _ ' ;
} else {
saveFileName + = inFileName [ i ] ;
}
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : SaveGame
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : SaveGame ( const char * saveName , bool autosave , const char * saveFileName ) {
# ifdef ID_DEDICATED
common - > Printf ( " Dedicated servers cannot save games. \n " ) ;
return false ;
# else
int i ;
idStr previewFile , descriptionFile , mapName ;
// DG: support setting an explicit savename to avoid problems with autosave names
idStr gameFile = ( saveFileName ! = NULL ) ? saveFileName : saveName ;
if ( ! mapSpawned ) {
common - > Printf ( " Not playing a game. \n " ) ;
return false ;
}
if ( IsMultiplayer ( ) ) {
common - > Printf ( " Can't save during net play. \n " ) ;
return false ;
}
if ( game - > GetPersistentPlayerInfo ( 0 ) . GetInt ( " health " ) < = 0 ) {
MessageBox ( MSG_OK , common - > GetLanguageDict ( ) - > GetString ( " #str_04311 " ) , common - > GetLanguageDict ( ) - > GetString ( " #str_04312 " ) , true ) ;
common - > Printf ( " You must be alive to save the game \n " ) ;
return false ;
}
if ( Sys_GetDriveFreeSpace ( cvarSystem - > GetCVarString ( " fs_savepath " ) ) < 25 ) {
MessageBox ( MSG_OK , common - > GetLanguageDict ( ) - > GetString ( " #str_04313 " ) , common - > GetLanguageDict ( ) - > GetString ( " #str_04314 " ) , true ) ;
common - > Printf ( " Not enough drive space to save the game \n " ) ;
return false ;
}
idSoundWorld * pauseWorld = soundSystem - > GetPlayingSoundWorld ( ) ;
if ( pauseWorld ) {
pauseWorld - > Pause ( ) ;
soundSystem - > SetPlayingSoundWorld ( NULL ) ;
}
// setup up filenames and paths
ScrubSaveGameFileName ( gameFile ) ;
gameFile = " savegames/ " + gameFile ;
gameFile . SetFileExtension ( " .save " ) ;
previewFile = gameFile ;
previewFile . SetFileExtension ( " .tga " ) ;
descriptionFile = gameFile ;
descriptionFile . SetFileExtension ( " .txt " ) ;
// Open savegame file
idFile * fileOut = fileSystem - > OpenFileWrite ( gameFile ) ;
if ( fileOut = = NULL ) {
common - > Warning ( " Failed to open save file '%s' \n " , gameFile . c_str ( ) ) ;
if ( pauseWorld ) {
soundSystem - > SetPlayingSoundWorld ( pauseWorld ) ;
pauseWorld - > UnPause ( ) ;
}
return false ;
}
// Write SaveGame Header:
// Game Name / Version / Map Name / Persistant Player Info
// game
const char * gamename = GAME_NAME ;
fileOut - > WriteString ( gamename ) ;
// version
fileOut - > WriteInt ( SAVEGAME_VERSION ) ;
// map
mapName = mapSpawnData . serverInfo . GetString ( " si_map " ) ;
fileOut - > WriteString ( mapName ) ;
// persistent player info
for ( i = 0 ; i < MAX_ASYNC_CLIENTS ; i + + ) {
mapSpawnData . persistentPlayerInfo [ i ] = game - > GetPersistentPlayerInfo ( i ) ;
mapSpawnData . persistentPlayerInfo [ i ] . WriteToFileHandle ( fileOut ) ;
}
// let the game save its state
game - > SaveGame ( fileOut ) ;
// close the sava game file
fileSystem - > CloseFile ( fileOut ) ;
// Write screenshot
if ( ! autosave ) {
renderSystem - > CropRenderSize ( 320 , 240 , false ) ;
game - > Draw ( 0 ) ;
renderSystem - > CaptureRenderToFile ( previewFile , true ) ;
renderSystem - > UnCrop ( ) ;
}
// Write description, which is just a text file with
// the unclean save name on line 1, map name on line 2, screenshot on line 3
idFile * fileDesc = fileSystem - > OpenFileWrite ( descriptionFile ) ;
if ( fileDesc = = NULL ) {
common - > Warning ( " Failed to open description file '%s' \n " , descriptionFile . c_str ( ) ) ;
if ( pauseWorld ) {
soundSystem - > SetPlayingSoundWorld ( pauseWorld ) ;
pauseWorld - > UnPause ( ) ;
}
return false ;
}
idStr description = saveName ;
description . Replace ( " \\ " , " \\ \\ " ) ;
description . Replace ( " \" " , " \\ \" " ) ;
const idDeclEntityDef * mapDef = static_cast < const idDeclEntityDef * > ( declManager - > FindType ( DECL_MAPDEF , mapName , false ) ) ;
if ( mapDef ) {
mapName = common - > GetLanguageDict ( ) - > GetString ( mapDef - > dict . GetString ( " name " , mapName ) ) ;
}
fileDesc - > Printf ( " \" %s \" \n " , description . c_str ( ) ) ;
fileDesc - > Printf ( " \" %s \" \n " , mapName . c_str ( ) ) ;
if ( autosave ) {
idStr sshot = mapSpawnData . serverInfo . GetString ( " si_map " ) ;
sshot . StripPath ( ) ;
sshot . StripFileExtension ( ) ;
fileDesc - > Printf ( " \" guis/assets/autosave/%s \" \n " , sshot . c_str ( ) ) ;
} else {
fileDesc - > Printf ( " \" \" \n " ) ;
}
fileSystem - > CloseFile ( fileDesc ) ;
if ( pauseWorld ) {
soundSystem - > SetPlayingSoundWorld ( pauseWorld ) ;
pauseWorld - > UnPause ( ) ;
}
syncNextGameFrame = true ;
return true ;
# endif
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : LoadGame
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : LoadGame ( const char * saveName ) {
# ifdef ID_DEDICATED
common - > Printf ( " Dedicated servers cannot load games. \n " ) ;
return false ;
# else
int i ;
idStr in , loadFile , saveMap , gamename ;
if ( IsMultiplayer ( ) ) {
common - > Printf ( " Can't load during net play. \n " ) ;
return false ;
}
//Hide the dialog box if it is up.
StopBox ( ) ;
loadFile = saveName ;
ScrubSaveGameFileName ( loadFile ) ;
loadFile . SetFileExtension ( " .save " ) ;
in = " savegames/ " ;
in + = loadFile ;
// Open savegame file
// only allow loads from the game directory because we don't want a base game to load
idStr game = cvarSystem - > GetCVarString ( " fs_game " ) ;
savegameFile = fileSystem - > OpenFileRead ( in , true , game . Length ( ) ? game : NULL ) ;
if ( savegameFile = = NULL ) {
common - > Warning ( " Couldn't open savegame file %s " , in . c_str ( ) ) ;
return false ;
}
loadingSaveGame = true ;
// Read in save game header
// Game Name / Version / Map Name / Persistant Player Info
// game
savegameFile - > ReadString ( gamename ) ;
// if this isn't a savegame for the correct game, abort loadgame
if ( ! ( gamename = = GAME_NAME | | gamename = = " DOOM 3 " ) ) {
common - > Warning ( " Attempted to load an invalid savegame: %s " , in . c_str ( ) ) ;
loadingSaveGame = false ;
fileSystem - > CloseFile ( savegameFile ) ;
savegameFile = NULL ;
return false ;
}
// version
savegameFile - > ReadInt ( savegameVersion ) ;
// map
savegameFile - > ReadString ( saveMap ) ;
// persistent player info
for ( i = 0 ; i < MAX_ASYNC_CLIENTS ; i + + ) {
mapSpawnData . persistentPlayerInfo [ i ] . ReadFromFileHandle ( savegameFile ) ;
}
// check the version, if it doesn't match, cancel the loadgame,
// but still load the map with the persistant playerInfo from the header
// so that the player doesn't lose too much progress.
2020-12-11 01:43:15 +00:00
if ( savegameVersion < = 17 ) { // handle savegame v16 in v17
common - > Warning ( " Savegame Version Too Early: aborting loadgame and starting level with persistent data " ) ;
2020-09-08 22:10:45 +00:00
loadingSaveGame = false ;
fileSystem - > CloseFile ( savegameFile ) ;
savegameFile = NULL ;
}
common - > DPrintf ( " loading a v%d savegame \n " , savegameVersion ) ;
if ( saveMap . Length ( ) > 0 ) {
// Start loading map
mapSpawnData . serverInfo . Clear ( ) ;
mapSpawnData . serverInfo = * cvarSystem - > MoveCVarsToDict ( CVAR_SERVERINFO ) ;
mapSpawnData . serverInfo . Set ( " si_gameType " , " singleplayer " ) ;
mapSpawnData . serverInfo . Set ( " si_map " , saveMap ) ;
mapSpawnData . syncedCVars . Clear ( ) ;
mapSpawnData . syncedCVars = * cvarSystem - > MoveCVarsToDict ( CVAR_NETWORKSYNC ) ;
mapSpawnData . mapSpawnUsercmd [ 0 ] = usercmdGen - > TicCmd ( latchedTicNumber ) ;
// make sure no buttons are pressed
mapSpawnData . mapSpawnUsercmd [ 0 ] . buttons = 0 ;
ExecuteMapChange ( ) ;
SetGUI ( NULL , NULL ) ;
}
if ( loadingSaveGame ) {
fileSystem - > CloseFile ( savegameFile ) ;
loadingSaveGame = false ;
savegameFile = NULL ;
}
return true ;
# endif
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : ProcessEvent
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : ProcessEvent ( const sysEvent_t * event ) {
// hitting escape anywhere brings up the menu
// DG: but shift-escape should bring up console instead so ignore that
if ( ! guiActive & & event - > evType = = SE_KEY & & event - > evValue2 = = 1
& & event - > evValue = = K_ESCAPE & & ! idKeyInput : : IsDown ( K_SHIFT ) ) {
console - > Close ( ) ;
if ( game ) {
idUserInterface * gui = NULL ;
escReply_t op ;
op = game - > HandleESC ( & gui ) ;
if ( op = = ESC_IGNORE ) {
return true ;
} else if ( op = = ESC_GUI ) {
SetGUI ( gui , NULL ) ;
return true ;
}
}
StartMenu ( ) ;
return true ;
}
// let the pull-down console take it if desired
if ( console - > ProcessEvent ( event , false ) ) {
return true ;
}
// if we are testing a GUI, send all events to it
if ( guiTest ) {
// hitting escape exits the testgui
if ( event - > evType = = SE_KEY & & event - > evValue2 = = 1 & & event - > evValue = = K_ESCAPE ) {
guiTest = NULL ;
return true ;
}
static const char * cmd ;
cmd = guiTest - > HandleEvent ( event , com_frameTime ) ;
if ( cmd & & cmd [ 0 ] ) {
common - > Printf ( " testGui event returned: '%s' \n " , cmd ) ;
}
return true ;
}
// menus / etc
if ( guiActive ) {
MenuEvent ( event ) ;
return true ;
}
// if we aren't in a game, force the console to take it
if ( ! mapSpawned ) {
console - > ProcessEvent ( event , true ) ;
return true ;
}
// in game, exec bindings for all key downs
if ( event - > evType = = SE_KEY & & event - > evValue2 = = 1 ) {
idKeyInput : : ExecKeyBinding ( event - > evValue ) ;
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : DrawWipeModel
Draw the fade material over everything that has been drawn
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : DrawWipeModel ( ) {
int latchedTic = com_ticNumber ;
if ( wipeStartTic > = wipeStopTic ) {
return ;
}
if ( ! wipeHold & & latchedTic > = wipeStopTic ) {
return ;
}
float fade = ( float ) ( latchedTic - wipeStartTic ) / ( wipeStopTic - wipeStartTic ) ;
renderSystem - > SetColor4 ( 1 , 1 , 1 , fade ) ;
renderSystem - > DrawStretchPic ( 0 , 0 , 640 , 480 , 0 , 0 , 1 , 1 , wipeMaterial ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : AdvanceRenderDemo
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : AdvanceRenderDemo ( bool singleFrameOnly ) {
if ( lastDemoTic = = - 1 ) {
lastDemoTic = latchedTicNumber - 1 ;
}
int skipFrames = 0 ;
if ( ! aviCaptureMode & & ! timeDemo & & ! singleFrameOnly ) {
skipFrames = ( ( latchedTicNumber - lastDemoTic ) / USERCMD_PER_DEMO_FRAME ) - 1 ;
// never skip too many frames, just let it go into slightly slow motion
if ( skipFrames > 4 ) {
skipFrames = 4 ;
}
lastDemoTic = latchedTicNumber - latchedTicNumber % USERCMD_PER_DEMO_FRAME ;
} else {
// always advance a single frame with avidemo and timedemo
lastDemoTic = latchedTicNumber ;
}
while ( skipFrames > - 1 ) {
int ds = DS_FINISHED ;
readDemo - > ReadInt ( ds ) ;
if ( ds = = DS_FINISHED ) {
if ( numDemoFrames ! = 1 ) {
// if the demo has a single frame (a demoShot), continuously replay
// the renderView that has already been read
Stop ( ) ;
StartMenu ( ) ;
}
break ;
}
if ( ds = = DS_RENDER ) {
if ( rw - > ProcessDemoCommand ( readDemo , & currentDemoRenderView , & demoTimeOffset ) ) {
// a view is ready to render
skipFrames - - ;
numDemoFrames + + ;
}
continue ;
}
if ( ds = = DS_SOUND ) {
sw - > ProcessDemoCommand ( readDemo ) ;
continue ;
}
// appears in v1.2, with savegame format 17
if ( ds = = DS_VERSION ) {
readDemo - > ReadInt ( renderdemoVersion ) ;
common - > Printf ( " reading a v%d render demo \n " , renderdemoVersion ) ;
// set the savegameVersion to current for render demo paths that share the savegame paths
savegameVersion = SAVEGAME_VERSION ;
continue ;
}
common - > Error ( " Bad render demo token " ) ;
}
if ( com_showDemo . GetBool ( ) ) {
common - > Printf ( " frame:%i DemoTic:%i latched:%i skip:%i \n " , numDemoFrames , lastDemoTic , latchedTicNumber , skipFrames ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : DrawCmdGraph
Graphs yaw angle for testing smoothness
= = = = = = = = = = = = = = =
*/
static const int ANGLE_GRAPH_HEIGHT = 128 ;
static const int ANGLE_GRAPH_STRETCH = 3 ;
void idSessionLocal : : DrawCmdGraph ( ) {
if ( ! com_showAngles . GetBool ( ) ) {
return ;
}
renderSystem - > SetColor4 ( 0.1f , 0.1f , 0.1f , 1.0f ) ;
renderSystem - > DrawStretchPic ( 0 , 480 - ANGLE_GRAPH_HEIGHT , MAX_BUFFERED_USERCMD * ANGLE_GRAPH_STRETCH , ANGLE_GRAPH_HEIGHT , 0 , 0 , 1 , 1 , whiteMaterial ) ;
renderSystem - > SetColor4 ( 0.9f , 0.9f , 0.9f , 1.0f ) ;
for ( int i = 0 ; i < MAX_BUFFERED_USERCMD - 4 ; i + + ) {
usercmd_t cmd = usercmdGen - > TicCmd ( latchedTicNumber - ( MAX_BUFFERED_USERCMD - 4 ) + i ) ;
int h = cmd . angles [ 1 ] ;
h > > = 8 ;
h & = ( ANGLE_GRAPH_HEIGHT - 1 ) ;
renderSystem - > DrawStretchPic ( i * ANGLE_GRAPH_STRETCH , 480 - h , 1 , h , 0 , 0 , 1 , 1 , whiteMaterial ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : PacifierUpdate
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : PacifierUpdate ( ) {
if ( ! insideExecuteMapChange ) {
return ;
}
// never do pacifier screen updates while inside the
// drawing code, or we can have various recursive problems
if ( insideUpdateScreen ) {
return ;
}
int time = eventLoop - > Milliseconds ( ) ;
if ( time - lastPacifierTime < 100 ) {
return ;
}
lastPacifierTime = time ;
if ( guiLoading & & bytesNeededForMapLoad ) {
float n = fileSystem - > GetReadCount ( ) ;
float pct = ( n / bytesNeededForMapLoad ) ;
// pct = idMath::ClampFloat( 0.0f, 100.0f, pct );
guiLoading - > SetStateFloat ( " map_loading " , pct ) ;
guiLoading - > StateChanged ( com_frameTime ) ;
}
Sys_GenerateEvents ( ) ;
UpdateScreen ( ) ;
idAsyncNetwork : : client . PacifierUpdate ( ) ;
idAsyncNetwork : : server . PacifierUpdate ( ) ;
}
2020-11-29 19:02:53 +00:00
extern " C " void Doom3Quest_setUseScreenLayer ( int use ) ;
void setupScreenLayer ( )
{
int inMenu = ( ( ( idSessionLocal * ) session ) - > guiActive ! = 0 ) ;
int inGameGui = ( game & & game - > InGameGuiActive ( ) ) ;
int objectiveActive = ( game & & game - > ObjectiveSystemActive ( ) ) ;
int cinematic = ( game & & game - > InCinematic ( ) ) ;
bool loading = ( ( ( idSessionLocal * ) session ) - > insideExecuteMapChange ) ;
Doom3Quest_setUseScreenLayer ( inMenu ? 1 : 0 + inGameGui ? 2 : 0 + objectiveActive ? 4 : 0 + cinematic ? 8 : 0 + loading ? 16 : 0 ) ;
}
2020-09-08 22:10:45 +00:00
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Draw
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : Draw ( ) {
bool fullConsole = false ;
2020-11-29 19:02:53 +00:00
setupScreenLayer ( ) ;
2020-09-08 22:10:45 +00:00
if ( insideExecuteMapChange ) {
if ( guiLoading ) {
guiLoading - > Redraw ( com_frameTime ) ;
}
if ( guiActive = = guiMsg ) {
guiMsg - > Redraw ( com_frameTime ) ;
}
} else if ( guiTest ) {
// if testing a gui, clear the screen and draw it
// clear the background, in case the tested gui is transparent
// NOTE that you can't use this for aviGame recording, it will tick at real com_frameTime between screenshots..
renderSystem - > SetColor ( colorBlack ) ;
renderSystem - > DrawStretchPic ( 0 , 0 , 640 , 480 , 0 , 0 , 1 , 1 , declManager - > FindMaterial ( " _white " ) ) ;
guiTest - > Redraw ( com_frameTime ) ;
} else if ( guiActive & & ! guiActive - > State ( ) . GetBool ( " gameDraw " ) ) {
// draw the frozen gui in the background
if ( guiActive = = guiMsg & & guiMsgRestore ) {
guiMsgRestore - > Redraw ( com_frameTime ) ;
}
// draw the menus full screen
if ( guiActive = = guiTakeNotes & & ! com_skipGameDraw . GetBool ( ) ) {
game - > Draw ( GetLocalClientNum ( ) ) ;
}
guiActive - > Redraw ( com_frameTime ) ;
} else if ( readDemo ) {
rw - > RenderScene ( & currentDemoRenderView ) ;
renderSystem - > DrawDemoPics ( ) ;
} else if ( mapSpawned ) {
bool gameDraw = false ;
// normal drawing for both single and multi player
if ( ! com_skipGameDraw . GetBool ( ) & & GetLocalClientNum ( ) > = 0 ) {
// draw the game view
int start = Sys_Milliseconds ( ) ;
gameDraw = game - > Draw ( GetLocalClientNum ( ) ) ;
int end = Sys_Milliseconds ( ) ;
time_gameDraw + = ( end - start ) ; // note time used for com_speeds
}
if ( ! gameDraw ) {
renderSystem - > SetColor ( colorBlack ) ;
renderSystem - > DrawStretchPic ( 0 , 0 , 640 , 480 , 0 , 0 , 1 , 1 , declManager - > FindMaterial ( " _white " ) ) ;
}
// save off the 2D drawing from the game
if ( writeDemo ) {
renderSystem - > WriteDemoPics ( ) ;
}
} else {
# if ID_CONSOLE_LOCK
if ( com_allowConsole . GetBool ( ) ) {
console - > Draw ( true ) ;
} else {
emptyDrawCount + + ;
if ( emptyDrawCount > 5 ) {
// it's best if you can avoid triggering the watchgod by doing the right thing somewhere else
assert ( false ) ;
common - > Warning ( " idSession: triggering mainmenu watchdog " ) ;
emptyDrawCount = 0 ;
StartMenu ( ) ;
}
renderSystem - > SetColor4 ( 0 , 0 , 0 , 1 ) ;
renderSystem - > DrawStretchPic ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , 0 , 0 , 1 , 1 , declManager - > FindMaterial ( " _white " ) ) ;
}
# else
// draw the console full screen - this should only ever happen in developer builds
console - > Draw ( true ) ;
# endif
fullConsole = true ;
}
# if ID_CONSOLE_LOCK
if ( ! fullConsole & & emptyDrawCount ) {
common - > DPrintf ( " idSession: %d empty frame draws \n " , emptyDrawCount ) ;
emptyDrawCount = 0 ;
}
fullConsole = false ;
# endif
// draw the wipe material on top of this if it hasn't completed yet
DrawWipeModel ( ) ;
// draw debug graphs
DrawCmdGraph ( ) ;
// draw the half console / notify console on top of everything
if ( ! fullConsole ) {
console - > Draw ( false ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : UpdateScreen
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : UpdateScreen ( bool outOfSequence ) {
# ifdef _WIN32
if ( com_editors ) {
if ( ! Sys_IsWindowVisible ( ) ) {
return ;
}
}
# endif
if ( insideUpdateScreen ) {
return ;
// common->FatalError( "idSessionLocal::UpdateScreen: recursively called" );
}
insideUpdateScreen = true ;
// if this is a long-operation update and we are in windowed mode,
// release the mouse capture back to the desktop
if ( outOfSequence ) {
Sys_GrabMouseCursor ( false ) ;
}
2020-10-07 18:05:09 +00:00
renderSystem - > BeginFrame ( renderSystem - > GetScreenWidth ( ) , renderSystem - > GetScreenHeight ( ) ) ;
2020-09-11 21:41:18 +00:00
2020-10-07 18:05:09 +00:00
// draw everything
Draw ( ) ;
2020-09-09 22:16:24 +00:00
2020-10-07 18:05:09 +00:00
if ( com_speeds . GetBool ( ) ) {
renderSystem - > EndFrame ( & time_frontend , & time_backend ) ;
} else {
renderSystem - > EndFrame ( NULL , NULL ) ;
}
2020-09-08 22:10:45 +00:00
insideUpdateScreen = false ;
}
2020-11-28 15:20:28 +00:00
# define FPS_FRAMES 5
int calcFPS ( ) {
static int previousTimes [ FPS_FRAMES ] ;
static int index ;
int i , total ;
static int fps = 0 ;
static int previous ;
int t , frameTime ;
// don't use serverTime, because that will be drifting to
// correct for internet lag changes, timescales, timedemos, etc
t = Sys_Milliseconds ( ) ;
frameTime = t - previous ;
previous = t ;
previousTimes [ index % FPS_FRAMES ] = frameTime ;
index + + ;
if ( index > FPS_FRAMES ) {
// average multiple frames together to smooth changes out a bit
total = 0 ;
for ( i = 0 ; i < FPS_FRAMES ; i + + ) {
total + = previousTimes [ i ] ;
}
if ( ! total ) {
total = 1 ;
}
fps = 10000 * FPS_FRAMES / total ;
fps = ( fps + 5 ) / 10 ;
2020-12-11 01:43:15 +00:00
//common->Printf( " FPS: %i ", fps );
2020-11-28 15:20:28 +00:00
}
return fps ;
}
2020-09-08 22:10:45 +00:00
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Frame
= = = = = = = = = = = = = = =
*/
2020-11-15 18:52:37 +00:00
extern " C " int questType ;
2020-09-08 22:10:45 +00:00
extern bool CheckOpenALDeviceAndRecoverIfNeeded ( ) ;
void idSessionLocal : : Frame ( ) {
if ( com_asyncSound . GetInteger ( ) = = 0 ) {
soundSystem - > AsyncUpdateWrite ( Sys_Milliseconds ( ) ) ;
}
// DG: periodically check if sound device is still there and try to reset it if not
// (calling this from idSoundSystem::AsyncUpdate(), which runs in a separate thread
// by default, causes a deadlock when calling idCommon->Warning())
CheckOpenALDeviceAndRecoverIfNeeded ( ) ;
// Editors that completely take over the game
if ( com_editorActive & & ( com_editors & ( EDITOR_RADIANT | EDITOR_GUI ) ) ) {
return ;
}
// if the console is down, we don't need to hold
// the mouse cursor
if ( console - > Active ( ) | | com_editorActive ) {
Sys_GrabMouseCursor ( false ) ;
} else {
Sys_GrabMouseCursor ( true ) ;
}
// save the screenshot and audio from the last draw if needed
if ( aviCaptureMode ) {
idStr name ;
name = va ( " demos/%s/%s_%05i.tga " , aviDemoShortName . c_str ( ) , aviDemoShortName . c_str ( ) , aviTicStart ) ;
float ratio = 30.0f / ( 1000.0f / USERCMD_MSEC / com_aviDemoTics . GetInteger ( ) ) ;
aviDemoFrameCount + = ratio ;
if ( aviTicStart + 1 ! = ( int ) aviDemoFrameCount ) {
// skipped frames so write them out
int c = aviDemoFrameCount - aviTicStart ;
while ( c - - ) {
renderSystem - > TakeScreenshot ( com_aviDemoWidth . GetInteger ( ) , com_aviDemoHeight . GetInteger ( ) , name , com_aviDemoSamples . GetInteger ( ) , NULL ) ;
name = va ( " demos/%s/%s_%05i.tga " , aviDemoShortName . c_str ( ) , aviDemoShortName . c_str ( ) , + + aviTicStart ) ;
}
}
aviTicStart = aviDemoFrameCount ;
// remove any printed lines at the top before taking the screenshot
console - > ClearNotifyLines ( ) ;
// this will call Draw, possibly multiple times if com_aviDemoSamples is > 1
renderSystem - > TakeScreenshot ( com_aviDemoWidth . GetInteger ( ) , com_aviDemoHeight . GetInteger ( ) , name , com_aviDemoSamples . GetInteger ( ) , NULL ) ;
}
// at startup, we may be backwards
if ( latchedTicNumber > com_ticNumber ) {
latchedTicNumber = com_ticNumber ;
}
// se how many tics we should have before continuing
int minTic = latchedTicNumber + 1 ;
if ( com_minTics . GetInteger ( ) > 1 ) {
minTic = lastGameTic + com_minTics . GetInteger ( ) ;
}
if ( readDemo ) {
if ( ! timeDemo & & numDemoFrames ! = 1 ) {
minTic = lastDemoTic + USERCMD_PER_DEMO_FRAME ;
} else {
// timedemos and demoshots will run as fast as they can, other demos
// will not run more than 30 hz
minTic = latchedTicNumber ;
}
} else if ( writeDemo ) {
minTic = lastGameTic + USERCMD_PER_DEMO_FRAME ; // demos are recorded at 30 hz
}
// fixedTic lets us run a forced number of usercmd each frame without timing
if ( com_fixedTic . GetInteger ( ) ) {
minTic = latchedTicNumber ;
}
while ( 1 ) {
latchedTicNumber = com_ticNumber ;
if ( latchedTicNumber > = minTic ) {
break ;
}
Sys_WaitForEvent ( TRIGGER_EVENT_ONE ) ;
}
if ( authEmitTimeout ) {
// waiting for a game auth
if ( Sys_Milliseconds ( ) > authEmitTimeout ) {
// expired with no reply
// means that if a firewall is blocking the master, we will let through
common - > DPrintf ( " no reply from auth \n " ) ;
if ( authWaitBox ) {
// close the wait box
StopBox ( ) ;
authWaitBox = false ;
}
if ( cdkey_state = = CDKEY_CHECKING ) {
cdkey_state = CDKEY_OK ;
}
if ( xpkey_state = = CDKEY_CHECKING ) {
xpkey_state = CDKEY_OK ;
}
// maintain this empty as it's set by auth denials
authMsg . Empty ( ) ;
authEmitTimeout = 0 ;
SetCDKeyGuiVars ( ) ;
}
}
// send frame and mouse events to active guis
GuiFrameEvents ( ) ;
// advance demos
if ( readDemo ) {
AdvanceRenderDemo ( false ) ;
return ;
}
//------------ single player game tics --------------
if ( ! mapSpawned | | guiActive ) {
if ( ! com_asyncInput . GetBool ( ) ) {
// early exit, won't do RunGameTic .. but still need to update mouse position for GUIs
usercmdGen - > GetDirectUsercmd ( ) ;
}
}
if ( ! mapSpawned ) {
return ;
}
if ( guiActive ) {
lastGameTic = latchedTicNumber ;
return ;
}
// in message box / GUIFrame, idSessionLocal::Frame is used for GUI interactivity
// but we early exit to avoid running game frames
if ( idAsyncNetwork : : IsActive ( ) ) {
return ;
}
// check for user info changes
if ( cvarSystem - > GetModifiedFlags ( ) & CVAR_USERINFO ) {
mapSpawnData . userInfo [ 0 ] = * cvarSystem - > MoveCVarsToDict ( CVAR_USERINFO ) ;
game - > SetUserInfo ( 0 , mapSpawnData . userInfo [ 0 ] , false , false ) ;
cvarSystem - > ClearModifiedFlags ( CVAR_USERINFO ) ;
}
// see how many usercmds we are going to run
int numCmdsToRun = latchedTicNumber - lastGameTic ;
// don't let a long onDemand sound load unsync everything
if ( timeHitch ) {
int skip = timeHitch / USERCMD_MSEC ;
lastGameTic + = skip ;
numCmdsToRun - = skip ;
timeHitch = 0 ;
}
// don't get too far behind after a hitch
if ( numCmdsToRun > 10 ) {
lastGameTic = latchedTicNumber - 10 ;
}
// never use more than USERCMD_PER_DEMO_FRAME,
// which makes it go into slow motion when recording
if ( writeDemo ) {
int fixedTic = USERCMD_PER_DEMO_FRAME ;
// we should have waited long enough
if ( numCmdsToRun < fixedTic ) {
common - > Error ( " idSessionLocal::Frame: numCmdsToRun < fixedTic " ) ;
}
// we may need to dump older commands
lastGameTic = latchedTicNumber - fixedTic ;
} else if ( com_fixedTic . GetInteger ( ) > 0 ) {
// this may cause commands run in a previous frame to
// be run again if we are going at above the real time rate
lastGameTic = latchedTicNumber - com_fixedTic . GetInteger ( ) ;
} else if ( aviCaptureMode ) {
lastGameTic = latchedTicNumber - com_aviDemoTics . GetInteger ( ) ;
}
// force only one game frame update this frame. the game code requests this after skipping cinematics
// so we come back immediately after the cinematic is done instead of a few frames later which can
// cause sounds played right after the cinematic to not play.
if ( syncNextGameFrame ) {
lastGameTic = latchedTicNumber - 1 ;
syncNextGameFrame = false ;
}
// create client commands, which will be sent directly
// to the game
2020-12-11 01:43:15 +00:00
/*if ( com_showTics.GetBool() ) {
2020-10-10 18:51:03 +00:00
common - > Printf ( " Tics to run: %i " , latchedTicNumber - lastGameTic ) ;
2020-12-11 01:43:15 +00:00
} */
2020-09-08 22:10:45 +00:00
int gameTicsToRun = latchedTicNumber - lastGameTic ;
2020-10-10 18:51:03 +00:00
2020-11-28 15:20:28 +00:00
// DrBeef's "smoothing out" logic, dodgy, but seems to do the trick
//
// This is here because, for example, if we are running at 60hz, then the game tic interval is
// 16ms, which actually means 63 tics per second, so every half second or so we get an extra tic.
// This extra tic results is a movement glitch (subtle, but annoying when you are aware of it)
// because you move two tics worth of distance compared to the other frames, which is more obvious in VR.
//
// The solution is to just skip these extra tics, however if we skip all extra tics and only process
// one per frame then if the fps drop due to a lot of action, the whole game slows down, which isn't desriable.
// Therefore we only want to skip isolated instances of a single extra tic if we are maintaining almost max frame rate
int fps = calcFPS ( ) ;
bool skipTics = false ;
if ( com_skipTics . GetBool ( ) & & gameTicsToRun > 1 )
{
int refresh = renderSystem - > GetRefresh ( ) ;
//Skip extra tics if we are maintaining 95% of the intended refresh rate
skipTics = ( fps > = ( refresh * 0.95F ) ) ;
}
2020-09-08 22:10:45 +00:00
int i ;
2020-10-10 18:51:03 +00:00
for ( i = 0 ; i < gameTicsToRun ; i + + )
{
2020-09-08 22:10:45 +00:00
RunGameTic ( ) ;
if ( ! mapSpawned ) {
// exited game play
break ;
}
2020-10-10 18:51:03 +00:00
2020-11-28 15:20:28 +00:00
if ( syncNextGameFrame | | skipTics ) {
// Do this in case skipTics is true but this flag isn't, since RunGameTic will reset the
// syncNextGameFrame flag
syncNextGameFrame = true ;
2020-09-08 22:10:45 +00:00
// long game frame, so break out and continue executing as if there was no hitch
break ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : RunGameTic
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : RunGameTic ( ) {
logCmd_t logCmd ;
usercmd_t cmd ;
// if we are doing a command demo, read or write from the file
if ( cmdDemoFile ) {
if ( ! cmdDemoFile - > Read ( & logCmd , sizeof ( logCmd ) ) ) {
common - > Printf ( " Command demo completed at logIndex %i \n " , logIndex ) ;
fileSystem - > CloseFile ( cmdDemoFile ) ;
cmdDemoFile = NULL ;
if ( aviCaptureMode ) {
EndAVICapture ( ) ;
Shutdown ( ) ;
}
// we fall out of the demo to normal commands
// the impulse and chat character toggles may not be correct, and the view
// angle will definitely be wrong
} else {
cmd = logCmd . cmd ;
cmd . ByteSwap ( ) ;
logCmd . consistencyHash = LittleInt ( logCmd . consistencyHash ) ;
}
}
// if we didn't get one from the file, get it locally
if ( ! cmdDemoFile ) {
// get a locally created command
if ( com_asyncInput . GetBool ( ) ) {
cmd = usercmdGen - > TicCmd ( lastGameTic ) ;
} else {
cmd = usercmdGen - > GetDirectUsercmd ( ) ;
}
lastGameTic + + ;
}
// run the game logic every player move
int start = Sys_Milliseconds ( ) ;
gameReturn_t ret = game - > RunFrame ( & cmd ) ;
2020-11-15 18:52:37 +00:00
for ( int h = 0 ; h < 2 ; h + + ) {
common - > Vibrate ( h , ret . vibrationLow [ h ] , ret . vibrationHigh [ h ] ) ;
}
2020-09-08 22:10:45 +00:00
int end = Sys_Milliseconds ( ) ;
time_gameFrame + = end - start ; // note time used for com_speeds
// check for constency failure from a recorded command
if ( cmdDemoFile ) {
if ( ret . consistencyHash ! = logCmd . consistencyHash ) {
common - > Printf ( " Consistency failure on logIndex %i \n " , logIndex ) ;
Stop ( ) ;
return ;
}
}
// save the cmd for cmdDemo archiving
if ( logIndex < MAX_LOGGED_USERCMDS ) {
loggedUsercmds [ logIndex ] . cmd = cmd ;
// save the consistencyHash for demo playback verification
loggedUsercmds [ logIndex ] . consistencyHash = ret . consistencyHash ;
if ( logIndex % 30 = = 0 & & statIndex < MAX_LOGGED_STATS ) {
loggedStats [ statIndex ] . health = ret . health ;
loggedStats [ statIndex ] . heartRate = ret . heartRate ;
loggedStats [ statIndex ] . stamina = ret . stamina ;
loggedStats [ statIndex ] . combat = ret . combat ;
statIndex + + ;
}
logIndex + + ;
}
syncNextGameFrame = ret . syncNextGameFrame ;
if ( ret . sessionCommand [ 0 ] ) {
idCmdArgs args ;
args . TokenizeString ( ret . sessionCommand , false ) ;
if ( ! idStr : : Icmp ( args . Argv ( 0 ) , " map " ) ) {
// get current player states
for ( int i = 0 ; i < numClients ; i + + ) {
mapSpawnData . persistentPlayerInfo [ i ] = game - > GetPersistentPlayerInfo ( i ) ;
}
// clear the devmap key on serverinfo, so player spawns
// won't get the map testing items
mapSpawnData . serverInfo . Delete ( " devmap " ) ;
// go to the next map
MoveToNewMap ( args . Argv ( 1 ) ) ;
} else if ( ! idStr : : Icmp ( args . Argv ( 0 ) , " devmap " ) ) {
mapSpawnData . serverInfo . Set ( " devmap " , " 1 " ) ;
MoveToNewMap ( args . Argv ( 1 ) ) ;
} else if ( ! idStr : : Icmp ( args . Argv ( 0 ) , " died " ) ) {
// restart on the same map
UnloadMap ( ) ;
SetGUI ( guiRestartMenu , NULL ) ;
} else if ( ! idStr : : Icmp ( args . Argv ( 0 ) , " disconnect " ) ) {
cmdSystem - > BufferCommandText ( CMD_EXEC_INSERT , " stoprecording ; disconnect " ) ;
}
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : Init
Called in an orderly fashion at system startup ,
so commands , cvars , files , etc are all available
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : Init ( ) {
common - > Printf ( " ----- Initializing Session ----- \n " ) ;
cmdSystem - > AddCommand ( " writePrecache " , Sess_WritePrecache_f , CMD_FL_SYSTEM | CMD_FL_CHEAT , " writes precache commands " ) ;
# ifndef ID_DEDICATED
cmdSystem - > AddCommand ( " map " , Session_Map_f , CMD_FL_SYSTEM , " loads a map " , idCmdSystem : : ArgCompletion_MapName ) ;
cmdSystem - > AddCommand ( " devmap " , Session_DevMap_f , CMD_FL_SYSTEM , " loads a map in developer mode " , idCmdSystem : : ArgCompletion_MapName ) ;
cmdSystem - > AddCommand ( " testmap " , Session_TestMap_f , CMD_FL_SYSTEM , " tests a map " , idCmdSystem : : ArgCompletion_MapName ) ;
cmdSystem - > AddCommand ( " writeCmdDemo " , Session_WriteCmdDemo_f , CMD_FL_SYSTEM , " writes a command demo " ) ;
cmdSystem - > AddCommand ( " playCmdDemo " , Session_PlayCmdDemo_f , CMD_FL_SYSTEM , " plays back a command demo " ) ;
cmdSystem - > AddCommand ( " timeCmdDemo " , Session_TimeCmdDemo_f , CMD_FL_SYSTEM , " times a command demo " ) ;
cmdSystem - > AddCommand ( " exitCmdDemo " , Session_ExitCmdDemo_f , CMD_FL_SYSTEM , " exits a command demo " ) ;
cmdSystem - > AddCommand ( " aviCmdDemo " , Session_AVICmdDemo_f , CMD_FL_SYSTEM , " writes AVIs for a command demo " ) ;
cmdSystem - > AddCommand ( " aviGame " , Session_AVIGame_f , CMD_FL_SYSTEM , " writes AVIs for the current game " ) ;
cmdSystem - > AddCommand ( " recordDemo " , Session_RecordDemo_f , CMD_FL_SYSTEM , " records a demo " ) ;
cmdSystem - > AddCommand ( " stopRecording " , Session_StopRecordingDemo_f , CMD_FL_SYSTEM , " stops demo recording " ) ;
cmdSystem - > AddCommand ( " playDemo " , Session_PlayDemo_f , CMD_FL_SYSTEM , " plays back a demo " , idCmdSystem : : ArgCompletion_DemoName ) ;
cmdSystem - > AddCommand ( " timeDemo " , Session_TimeDemo_f , CMD_FL_SYSTEM , " times a demo " , idCmdSystem : : ArgCompletion_DemoName ) ;
cmdSystem - > AddCommand ( " timeDemoQuit " , Session_TimeDemoQuit_f , CMD_FL_SYSTEM , " times a demo and quits " , idCmdSystem : : ArgCompletion_DemoName ) ;
cmdSystem - > AddCommand ( " aviDemo " , Session_AVIDemo_f , CMD_FL_SYSTEM , " writes AVIs for a demo " , idCmdSystem : : ArgCompletion_DemoName ) ;
cmdSystem - > AddCommand ( " compressDemo " , Session_CompressDemo_f , CMD_FL_SYSTEM , " compresses a demo file " , idCmdSystem : : ArgCompletion_DemoName ) ;
# endif
cmdSystem - > AddCommand ( " disconnect " , Session_Disconnect_f , CMD_FL_SYSTEM , " disconnects from a game " ) ;
cmdSystem - > AddCommand ( " demoShot " , Session_DemoShot_f , CMD_FL_SYSTEM , " writes a screenshot for a demo " ) ;
cmdSystem - > AddCommand ( " testGUI " , Session_TestGUI_f , CMD_FL_SYSTEM , " tests a gui " ) ;
# ifndef ID_DEDICATED
cmdSystem - > AddCommand ( " saveGame " , SaveGame_f , CMD_FL_SYSTEM | CMD_FL_CHEAT , " saves a game " ) ;
cmdSystem - > AddCommand ( " loadGame " , LoadGame_f , CMD_FL_SYSTEM | CMD_FL_CHEAT , " loads a game " , idCmdSystem : : ArgCompletion_SaveGame ) ;
# endif
cmdSystem - > AddCommand ( " takeViewNotes " , TakeViewNotes_f , CMD_FL_SYSTEM , " take notes about the current map from the current view " ) ;
cmdSystem - > AddCommand ( " takeViewNotes2 " , TakeViewNotes2_f , CMD_FL_SYSTEM , " extended take view notes " ) ;
cmdSystem - > AddCommand ( " rescanSI " , Session_RescanSI_f , CMD_FL_SYSTEM , " internal - rescan serverinfo cvars and tell game " ) ;
cmdSystem - > AddCommand ( " promptKey " , Session_PromptKey_f , CMD_FL_SYSTEM , " prompt and sets the CD Key " ) ;
cmdSystem - > AddCommand ( " hitch " , Session_Hitch_f , CMD_FL_SYSTEM | CMD_FL_CHEAT , " hitches the game " ) ;
// the same idRenderWorld will be used for all games
// and demos, insuring that level specific models
// will be freed
rw = renderSystem - > AllocRenderWorld ( ) ;
sw = soundSystem - > AllocSoundWorld ( rw ) ;
menuSoundWorld = soundSystem - > AllocSoundWorld ( rw ) ;
// we have a single instance of the main menu
guiMainMenu = uiManager - > FindGui ( " guis/mainmenu.gui " , true , false , true ) ;
if ( ! guiMainMenu ) {
guiMainMenu = uiManager - > FindGui ( " guis/demo_mainmenu.gui " , true , false , true ) ;
demoversion = ( guiMainMenu ! = NULL ) ;
}
guiMainMenu_MapList = uiManager - > AllocListGUI ( ) ;
guiMainMenu_MapList - > Config ( guiMainMenu , " mapList " ) ;
idAsyncNetwork : : client . serverList . GUIConfig ( guiMainMenu , " serverList " ) ;
guiRestartMenu = uiManager - > FindGui ( " guis/restart.gui " , true , false , true ) ;
guiGameOver = uiManager - > FindGui ( " guis/gameover.gui " , true , false , true ) ;
guiMsg = uiManager - > FindGui ( " guis/msg.gui " , true , false , true ) ;
guiTakeNotes = uiManager - > FindGui ( " guis/takeNotes.gui " , true , false , true ) ;
guiIntro = uiManager - > FindGui ( " guis/intro.gui " , true , false , true ) ;
whiteMaterial = declManager - > FindMaterial ( " _white " ) ;
guiInGame = NULL ;
guiTest = NULL ;
guiActive = NULL ;
guiHandle = NULL ;
ReadCDKey ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetLocalClientNum
= = = = = = = = = = = = = = =
*/
int idSessionLocal : : GetLocalClientNum ( ) {
if ( idAsyncNetwork : : client . IsActive ( ) ) {
return idAsyncNetwork : : client . GetLocalClientNum ( ) ;
} else if ( idAsyncNetwork : : server . IsActive ( ) ) {
if ( idAsyncNetwork : : serverDedicated . GetInteger ( ) = = 0 ) {
return 0 ;
} else if ( idAsyncNetwork : : server . IsClientInGame ( idAsyncNetwork : : serverDrawClient . GetInteger ( ) ) ) {
return idAsyncNetwork : : serverDrawClient . GetInteger ( ) ;
} else {
return - 1 ;
}
} else {
return 0 ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : SetPlayingSoundWorld
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : SetPlayingSoundWorld ( ) {
if ( guiActive & & ( guiActive = = guiMainMenu | | guiActive = = guiIntro | | guiActive = = guiLoading | | ( guiActive = = guiMsg & & ! mapSpawned ) ) ) {
soundSystem - > SetPlayingSoundWorld ( menuSoundWorld ) ;
} else {
soundSystem - > SetPlayingSoundWorld ( sw ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : TimeHitch
this is used by the sound system when an OnDemand sound is loaded , so the game action
doesn ' t advance and get things out of sync
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : TimeHitch ( int msec ) {
timeHitch + = msec ;
}
/*
= = = = = = = = = = = = = = = = =
idSessionLocal : : ReadCDKey
= = = = = = = = = = = = = = = = =
*/
void idSessionLocal : : ReadCDKey ( void ) {
idStr filename ;
idFile * f ;
char buffer [ 32 ] ;
cdkey_state = CDKEY_UNKNOWN ;
filename = CDKEY_FILEPATH ;
f = fileSystem - > OpenExplicitFileRead ( fileSystem - > RelativePathToOSPath ( filename , " fs_configpath " ) ) ;
// try the install path, which is where the cd installer and steam put it
if ( ! f )
f = fileSystem - > OpenExplicitFileRead ( fileSystem - > RelativePathToOSPath ( filename , " fs_basepath " ) ) ;
if ( ! f ) {
common - > Printf ( " Couldn't read %s. \n " , filename . c_str ( ) ) ;
cdkey [ 0 ] = ' \0 ' ;
} else {
memset ( buffer , 0 , sizeof ( buffer ) ) ;
f - > Read ( buffer , CDKEY_BUF_LEN - 1 ) ;
fileSystem - > CloseFile ( f ) ;
idStr : : Copynz ( cdkey , buffer , CDKEY_BUF_LEN ) ;
}
xpkey_state = CDKEY_UNKNOWN ;
filename = XPKEY_FILEPATH ;
f = fileSystem - > OpenExplicitFileRead ( fileSystem - > RelativePathToOSPath ( filename , " fs_configpath " ) ) ;
// try the install path, which is where the cd installer and steam put it
if ( ! f )
f = fileSystem - > OpenExplicitFileRead ( fileSystem - > RelativePathToOSPath ( filename , " fs_basepath " ) ) ;
if ( ! f ) {
common - > Printf ( " Couldn't read %s. \n " , filename . c_str ( ) ) ;
xpkey [ 0 ] = ' \0 ' ;
} else {
memset ( buffer , 0 , sizeof ( buffer ) ) ;
f - > Read ( buffer , CDKEY_BUF_LEN - 1 ) ;
fileSystem - > CloseFile ( f ) ;
idStr : : Copynz ( xpkey , buffer , CDKEY_BUF_LEN ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : WriteCDKey
= = = = = = = = = = = = = = = =
*/
void idSessionLocal : : WriteCDKey ( void ) {
idStr filename ;
idFile * f ;
const char * OSPath ;
filename = CDKEY_FILEPATH ;
// OpenFileWrite advertises creating directories to the path if needed, but that won't work with a '..' in the path
// occasionally on windows, but mostly on Linux and OSX, the fs_configpath/base may not exist in full
OSPath = fileSystem - > BuildOSPath ( cvarSystem - > GetCVarString ( " fs_configpath " ) , BASE_GAMEDIR , CDKEY_FILE ) ;
fileSystem - > CreateOSPath ( OSPath ) ;
f = fileSystem - > OpenFileWrite ( filename , " fs_configpath " ) ;
if ( ! f ) {
common - > Printf ( " Couldn't write %s. \n " , filename . c_str ( ) ) ;
return ;
}
f - > Printf ( " %s%s " , cdkey , CDKEY_TEXT ) ;
fileSystem - > CloseFile ( f ) ;
filename = XPKEY_FILEPATH ;
f = fileSystem - > OpenFileWrite ( filename , " fs_configpath " ) ;
if ( ! f ) {
common - > Printf ( " Couldn't write %s. \n " , filename . c_str ( ) ) ;
return ;
}
f - > Printf ( " %s%s " , xpkey , CDKEY_TEXT ) ;
fileSystem - > CloseFile ( f ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : ClearKey
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : ClearCDKey ( bool valid [ 2 ] ) {
if ( ! valid [ 0 ] ) {
memset ( cdkey , 0 , CDKEY_BUF_LEN ) ;
cdkey_state = CDKEY_UNKNOWN ;
} else if ( cdkey_state = = CDKEY_CHECKING ) {
// if a key was in checking and not explicitely asked for clearing, put it back to ok
cdkey_state = CDKEY_OK ;
}
if ( ! valid [ 1 ] ) {
memset ( xpkey , 0 , CDKEY_BUF_LEN ) ;
xpkey_state = CDKEY_UNKNOWN ;
} else if ( xpkey_state = = CDKEY_CHECKING ) {
xpkey_state = CDKEY_OK ;
}
WriteCDKey ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : GetCDKey
= = = = = = = = = = = = = = = =
*/
const char * idSessionLocal : : GetCDKey ( bool xp ) {
if ( ! xp ) {
return cdkey ;
}
if ( xpkey_state = = CDKEY_OK | | xpkey_state = = CDKEY_CHECKING ) {
return xpkey ;
}
return NULL ;
}
// digits to letters table
# define CDKEY_DIGITS "TWSBJCGD7PA23RLH"
/*
= = = = = = = = = = = = = = =
idSessionLocal : : EmitGameAuth
we toggled some key state to CDKEY_CHECKING . send a standalone auth packet to validate
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : EmitGameAuth ( void ) {
// make sure the auth reply is empty, we use it to indicate an auth reply
authMsg . Empty ( ) ;
if ( idAsyncNetwork : : client . SendAuthCheck ( cdkey_state = = CDKEY_CHECKING ? cdkey : NULL , xpkey_state = = CDKEY_CHECKING ? xpkey : NULL ) ) {
authEmitTimeout = Sys_Milliseconds ( ) + CDKEY_AUTH_TIMEOUT ;
common - > DPrintf ( " authing with the master.. \n " ) ;
} else {
// net is not available
common - > DPrintf ( " sendAuthCheck failed \n " ) ;
if ( cdkey_state = = CDKEY_CHECKING ) {
cdkey_state = CDKEY_OK ;
}
if ( xpkey_state = = CDKEY_CHECKING ) {
xpkey_state = CDKEY_OK ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idSessionLocal : : CheckKey
the function will only modify keys to _OK or _CHECKING if the offline checks are passed
if the function returns false , the offline checks failed , and offline_valid holds which keys are bad
= = = = = = = = = = = = = = = =
*/
bool idSessionLocal : : CheckKey ( const char * key , bool netConnect , bool offline_valid [ 2 ] ) {
char lkey [ 2 ] [ CDKEY_BUF_LEN ] ;
char l_chk [ 2 ] [ 3 ] ;
char s_chk [ 3 ] ;
int imax , i_key ;
unsigned int checksum , chk8 ;
bool edited_key [ 2 ] ;
// make sure have a right input string
assert ( strlen ( key ) = = ( CDKEY_BUF_LEN - 1 ) * 2 + 4 + 3 + 4 ) ;
edited_key [ 0 ] = ( key [ 0 ] = = ' 1 ' ) ;
idStr : : Copynz ( lkey [ 0 ] , key + 2 , CDKEY_BUF_LEN ) ;
idStr : : ToUpper ( lkey [ 0 ] ) ;
idStr : : Copynz ( l_chk [ 0 ] , key + CDKEY_BUF_LEN + 2 , 3 ) ;
idStr : : ToUpper ( l_chk [ 0 ] ) ;
edited_key [ 1 ] = ( key [ CDKEY_BUF_LEN + 2 + 3 ] = = ' 1 ' ) ;
idStr : : Copynz ( lkey [ 1 ] , key + CDKEY_BUF_LEN + 7 , CDKEY_BUF_LEN ) ;
idStr : : ToUpper ( lkey [ 1 ] ) ;
idStr : : Copynz ( l_chk [ 1 ] , key + CDKEY_BUF_LEN * 2 + 7 , 3 ) ;
idStr : : ToUpper ( l_chk [ 1 ] ) ;
if ( fileSystem - > HasD3XP ( ) ) {
imax = 2 ;
} else {
imax = 1 ;
}
offline_valid [ 0 ] = offline_valid [ 1 ] = true ;
for ( i_key = 0 ; i_key < imax ; i_key + + ) {
// check that the characters are from the valid set
int i ;
for ( i = 0 ; i < CDKEY_BUF_LEN - 1 ; i + + ) {
if ( ! strchr ( CDKEY_DIGITS , lkey [ i_key ] [ i ] ) ) {
offline_valid [ i_key ] = false ;
continue ;
}
}
if ( edited_key [ i_key ] ) {
// verify the checksum for edited keys only
checksum = CRC32_BlockChecksum ( lkey [ i_key ] , CDKEY_BUF_LEN - 1 ) ;
chk8 = ( checksum & 0xff ) ^ ( ( ( checksum & 0xff00 ) > > 8 ) ^ ( ( ( checksum & 0xff0000 ) > > 16 ) ^ ( ( checksum & 0xff000000 ) > > 24 ) ) ) ;
idStr : : snPrintf ( s_chk , 3 , " %02X " , chk8 ) ;
if ( idStr : : Icmp ( l_chk [ i_key ] , s_chk ) ! = 0 ) {
offline_valid [ i_key ] = false ;
continue ;
}
}
}
if ( ! offline_valid [ 0 ] | | ! offline_valid [ 1 ] ) {
return false ;
}
// offline checks passed, we'll return true and optionally emit key check requests
// the function should only modify the key states if the offline checks passed successfully
// set the keys, don't send a game auth if we are net connecting
idStr : : Copynz ( cdkey , lkey [ 0 ] , CDKEY_BUF_LEN ) ;
netConnect ? cdkey_state = CDKEY_OK : cdkey_state = CDKEY_CHECKING ;
if ( fileSystem - > HasD3XP ( ) ) {
idStr : : Copynz ( xpkey , lkey [ 1 ] , CDKEY_BUF_LEN ) ;
netConnect ? xpkey_state = CDKEY_OK : xpkey_state = CDKEY_CHECKING ;
} else {
xpkey_state = CDKEY_NA ;
}
if ( ! netConnect ) {
EmitGameAuth ( ) ;
}
SetCDKeyGuiVars ( ) ;
return true ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : CDKeysAreValid
checking that the key is present and uses only valid characters
if d3xp is installed , check for a valid xpkey as well
emit an auth packet to the master if possible and needed
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : CDKeysAreValid ( bool strict ) {
int i ;
bool emitAuth = false ;
if ( cdkey_state = = CDKEY_UNKNOWN ) {
if ( strlen ( cdkey ) ! = CDKEY_BUF_LEN - 1 ) {
cdkey_state = CDKEY_INVALID ;
} else {
for ( i = 0 ; i < CDKEY_BUF_LEN - 1 ; i + + ) {
if ( ! strchr ( CDKEY_DIGITS , cdkey [ i ] ) ) {
cdkey_state = CDKEY_INVALID ;
break ;
}
}
}
if ( cdkey_state = = CDKEY_UNKNOWN ) {
cdkey_state = CDKEY_CHECKING ;
emitAuth = true ;
}
}
if ( xpkey_state = = CDKEY_UNKNOWN ) {
if ( fileSystem - > HasD3XP ( ) ) {
if ( strlen ( xpkey ) ! = CDKEY_BUF_LEN - 1 ) {
xpkey_state = CDKEY_INVALID ;
} else {
for ( i = 0 ; i < CDKEY_BUF_LEN - 1 ; i + + ) {
if ( ! strchr ( CDKEY_DIGITS , xpkey [ i ] ) ) {
xpkey_state = CDKEY_INVALID ;
}
}
}
if ( xpkey_state = = CDKEY_UNKNOWN ) {
xpkey_state = CDKEY_CHECKING ;
emitAuth = true ;
}
} else {
xpkey_state = CDKEY_NA ;
}
}
if ( emitAuth ) {
EmitGameAuth ( ) ;
}
// make sure to keep the mainmenu gui up to date in case we made state changes
SetCDKeyGuiVars ( ) ;
if ( strict ) {
return cdkey_state = = CDKEY_OK & & ( xpkey_state = = CDKEY_OK | | xpkey_state = = CDKEY_NA ) ;
} else {
return ( cdkey_state = = CDKEY_OK | | cdkey_state = = CDKEY_CHECKING ) & & ( xpkey_state = = CDKEY_OK | | xpkey_state = = CDKEY_CHECKING | | xpkey_state = = CDKEY_NA ) ;
}
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : WaitingForGameAuth
= = = = = = = = = = = = = = =
*/
bool idSessionLocal : : WaitingForGameAuth ( void ) {
return authEmitTimeout ! = 0 ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : CDKeysAuthReply
= = = = = = = = = = = = = = =
*/
void idSessionLocal : : CDKeysAuthReply ( bool valid , const char * auth_msg ) {
//assert( authEmitTimeout > 0 );
if ( authWaitBox ) {
// close the wait box
StopBox ( ) ;
authWaitBox = false ;
}
if ( ! valid ) {
common - > DPrintf ( " auth key is invalid \n " ) ;
authMsg = auth_msg ;
if ( cdkey_state = = CDKEY_CHECKING ) {
cdkey_state = CDKEY_INVALID ;
}
if ( xpkey_state = = CDKEY_CHECKING ) {
xpkey_state = CDKEY_INVALID ;
}
} else {
common - > DPrintf ( " client is authed in \n " ) ;
if ( cdkey_state = = CDKEY_CHECKING ) {
cdkey_state = CDKEY_OK ;
}
if ( xpkey_state = = CDKEY_CHECKING ) {
xpkey_state = CDKEY_OK ;
}
}
authEmitTimeout = 0 ;
SetCDKeyGuiVars ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetCurrentMapName
= = = = = = = = = = = = = = =
*/
const char * idSessionLocal : : GetCurrentMapName ( ) {
return currentMapName . c_str ( ) ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetSaveGameVersion
= = = = = = = = = = = = = = =
*/
int idSessionLocal : : GetSaveGameVersion ( void ) {
return savegameVersion ;
}
/*
= = = = = = = = = = = = = = =
idSessionLocal : : GetAuthMsg
= = = = = = = = = = = = = = =
*/
const char * idSessionLocal : : GetAuthMsg ( void ) {
return authMsg . c_str ( ) ;
}