/* =============== idCommonLocal::WriteConfiguration Writes key bindings and archived cvars to config file if modified =============== */ void idCommonLocal::WriteConfiguration() { // if we are quiting without fully initializing, make sure // we don't write out anything if ( !com_fullyInitialized ) { return; } if ( !( cvarSystem->GetModifiedFlags() & CVAR_ARCHIVE ) ) { return; } cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE ); // save to the profile idLocalUser * user = session->GetSignInManager().GetMasterLocalUser(); if ( user != NULL ) { user->SaveProfileSettings(); } #ifdef CONFIG_FILE // disable printing out the "Writing to:" message bool developer = com_developer.GetBool(); com_developer.SetBool( false ); WriteConfigToFile( CONFIG_FILE ); // restore the developer cvar com_developer.SetBool( developer ); #endif }
/* =============== Posix_InitConsoleInput =============== */ void Posix_InitConsoleInput( void ) { struct termios tc; if ( in_tty.GetBool() ) { if ( isatty( STDIN_FILENO ) != 1 ) { Sys_Printf( "terminal support disabled: stdin is not a tty\n" ); in_tty.SetBool( false ); return; } if ( tcgetattr( 0, &tty_tc ) == -1 ) { Sys_Printf( "tcgetattr failed. disabling terminal support: %s\n", strerror( errno ) ); in_tty.SetBool( false ); return; } // make the input non blocking if ( fcntl( STDIN_FILENO, F_SETFL, fcntl( STDIN_FILENO, F_GETFL, 0 ) | O_NONBLOCK ) == -1 ) { Sys_Printf( "fcntl STDIN non blocking failed. disabling terminal support: %s\n", strerror( errno ) ); in_tty.SetBool( false ); return; } tc = tty_tc; /* ECHO: don't echo input characters ICANON: enable canonical mode. This enables the special characters EOF, EOL, EOL2, ERASE, KILL, REPRINT, STATUS, and WERASE, and buffers by lines. ISIG: when any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate the corresponding signal */ tc.c_lflag &= ~(ECHO | ICANON); /* ISTRIP strip off bit 8 INPCK enable input parity checking */ tc.c_iflag &= ~(ISTRIP | INPCK); tc.c_cc[VMIN] = 1; tc.c_cc[VTIME] = 0; if ( tcsetattr( 0, TCSADRAIN, &tc ) == -1 ) { Sys_Printf( "tcsetattr failed: %s\n", strerror( errno ) ); Sys_Printf( "terminal support may not work correctly. Use +set in_tty 0 to disable it\n" ); } #if 0 // make the output non blocking if ( fcntl( STDOUT_FILENO, F_SETFL, fcntl( STDOUT_FILENO, F_GETFL, 0 ) | O_NONBLOCK ) == -1 ) { Sys_Printf( "fcntl STDOUT non blocking failed: %s\n", strerror( errno ) ); } #endif tty_enabled = true; // check the terminal type for the supported ones char *term = getenv( "TERM" ); if ( term ) { if ( strcmp( term, "linux" ) && strcmp( term, "xterm" ) && strcmp( term, "xterm-color" ) && strcmp( term, "screen" ) ) { Sys_Printf( "WARNING: terminal type '%s' is unknown. terminal support may not work correctly\n", term ); } } Sys_Printf( "terminal support enabled ( use +set in_tty 0 to disabled )\n" ); } else { Sys_Printf( "terminal support disabled\n" ); } }
/* ======================== idMenuScreen_Shell_Controls::idMenuDataSource_AudioSettings::CommitData ======================== */ void idMenuScreen_Shell_Controls::idMenuDataSource_ControlSettings::CommitData() { in_mouseInvertLook.SetBool( fields[ CONTROLS_FIELD_INVERT_MOUSE ].ToBool() ); float mouseSpeed = 0.25f + ( ( 4.0f - 0.25 ) * ( fields[ CONTROLS_FIELD_MOUSE_SENS ].ToFloat() / 100.0f ) ); in_mouseSpeed.SetFloat( mouseSpeed ); in_useJoystick.SetBool( fields[ CONTROLS_FIELD_GAMEPAD_ENABLED ].ToBool() ); cvarSystem->SetModifiedFlags( CVAR_ARCHIVE ); // make the committed fields into the backup fields originalFields = fields; }
/* ================== idCommonLocal::CloseLogFile ================== */ void idCommonLocal::CloseLogFile() { if ( logFile ) { com_logFile.SetBool( false ); // make sure no further VPrintf attempts to open the log file again fileSystem->CloseFile( logFile ); logFile = NULL; } }
// // Toggle messages on/off // void M_ChangeGPad(int choice) { // warning: unused parameter `int choice' choice = 0; in_useJoystick.SetBool( !in_useJoystick.GetBool() ); ::g->message_dontfuckwithme = true; }
/* ======================== idMenuScreen_Shell_Gamepad::idMenuDataSource_AudioSettings::CommitData ======================== */ void idMenuScreen_Shell_Gamepad::idMenuDataSource_GamepadSettings::CommitData() { in_invertLook.SetBool( fields[ GAMEPAD_FIELD_INVERT ].ToBool() ); in_joystickRumble.SetBool( fields[ GAMEPAD_FIELD_VIBRATE ].ToBool() ); joy_yawSpeed.SetFloat( ( ( fields[ GAMEPAD_FIELD_HOR_SENS ].ToFloat() / 100.0f ) * 400.0f ) + 0.0f ); joy_pitchSpeed.SetFloat( ( ( fields[ GAMEPAD_FIELD_VERT_SENS ].ToFloat() / 100.0f ) * 260.0f ) + 0.0f); joy_gammaLook.SetBool( fields[ GAMEPAD_FIELD_ACCELERATION ].ToBool() ); joy_mergedThreshold.SetBool( fields[ GAMEPAD_FIELD_THRESHOLD ].ToBool() ); idPlayerProfile * profile = session->GetProfileFromMasterLocalUser(); if ( profile != NULL ) { profile->SetLeftyFlip( fields[ GAMEPAD_FIELD_LEFTY ].ToBool() ); } cvarSystem->SetModifiedFlags( CVAR_ARCHIVE ); // make the committed fields into the backup fields originalFields = fields; }
void Sys_GrabMouseCursor( bool grabIt ) { #if defined( ID_DEDICATED ) return; #endif if ( !dpy ) { #ifdef XEVT_DBG common->DPrintf("Sys_GrabMouseCursor: !dpy\n"); #endif return; } if ( glConfig.isFullscreen ) { if ( !grabIt ) { return; // never ungrab while fullscreen } if ( in_nograb.GetBool() ) { common->DPrintf("forcing in_nograb 0 while running fullscreen\n"); in_nograb.SetBool( false ); } } if ( in_nograb.GetBool() ) { if ( in_dgamouse.GetBool() ) { common->DPrintf("in_nograb 1, forcing forcing DGA mouse off\n"); in_dgamouse.SetBool( false ); } if (grabIt) { mouse_active = true; } else { mouse_active = false; } return; } if ( grabIt && !mouse_active ) { Sys_XInstallGrabs(); } else if ( !grabIt && mouse_active ) { Sys_XUninstallGrabs(); } }
static void Sys_XInstallGrabs( void ) { assert( dpy ); XWarpPointer( dpy, None, win, 0, 0, 0, 0, glConfig.vidWidth / 2, glConfig.vidHeight / 2 ); XSync( dpy, False ); XDefineCursor( dpy, win, Sys_XCreateNullCursor( dpy, win ) ); XGrabPointer( dpy, win, False, MOUSE_MASK, GrabModeAsync, GrabModeAsync, win, None, CurrentTime ); XGetPointerControl( dpy, &mouse_accel_numerator, &mouse_accel_denominator, &mouse_threshold ); XChangePointerControl( dpy, True, True, 1, 1, 0 ); XSync( dpy, False ); mouse_reset_time = Sys_Milliseconds (); if ( in_dgamouse.GetBool() && !dga_found ) { common->Printf("XF86DGA not available, forcing DGA mouse off\n"); in_dgamouse.SetBool( false ); } if ( in_dgamouse.GetBool() ) { #if defined( ID_ENABLE_DGA ) XF86DGADirectVideo( dpy, DefaultScreen( dpy ), XF86DGADirectMouse ); XWarpPointer( dpy, None, win, 0, 0, 0, 0, 0, 0 ); #endif } else { mwx = glConfig.vidWidth / 2; mwy = glConfig.vidHeight / 2; mx = my = 0; } XGrabKeyboard( dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime ); XSync( dpy, False ); mouse_active = true; }
/* ======================== idMenuScreen_Shell_Stereoscopics::idMenuDataSource_StereoSettings::AdjustField ======================== */ void idMenuScreen_Shell_Stereoscopics::idMenuDataSource_StereoSettings::AdjustField( const int fieldIndex, const int adjustAmount ) { if( fieldIndex == STEREO_FIELD_ENABLE ) { int numOptions = NUM_STEREO_ENABLE; if( !renderSystem->HasQuadBufferSupport() ) { numOptions--; } int adjusted = fields[ fieldIndex ].ToInteger() + adjustAmount; adjusted += numOptions; adjusted %= numOptions; fields[fieldIndex].SetInteger( adjusted ); renderSystem->EnableStereoScopicRendering( ( stereo3DMode_t )adjusted ); gameLocal.Shell_ClearRepeater(); } else if( fieldIndex == STEREO_FIELD_SWAP_EYES ) { fields[ fieldIndex ].SetBool( !fields[ fieldIndex ].ToBool() ); stereoRender_swapEyes.SetBool( fields[ fieldIndex ].ToBool() ); } else if( fieldIndex == STEREO_FIELD_SEPERATION ) { float newValue = idMath::ClampFloat( 0.0f, 100.0f, fields[ fieldIndex ].ToFloat() + adjustAmount ); fields[ fieldIndex ].SetFloat( newValue ); stereoRender_interOccularCentimeters.SetFloat( ( fields[ STEREO_FIELD_SEPERATION ].ToFloat() / 100.0f ) * MAX_INTEROCCULAR_DISTANCE ); } // do this so we don't save every time we modify a setting. Only save once when we leave the screen cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE ); }
/* ======================== idMenuScreen_Shell_GameOptions::idMenuDataSource_AudioSettings::CommitData ======================== */ void idMenuScreen_Shell_GameOptions::idMenuDataSource_GameSettings::CommitData() { g_fov.SetFloat( fields[ GAME_FIELD_FOV ].ToFloat() ); g_gun_x.SetFloat( Lerp( MIN_FOV_GUN, MAX_FOV_GUN, ( fields[ GAME_FIELD_FOV ].ToFloat() - MIN_FOV ) / ( MAX_FOV - MIN_FOV ) ) ); g_checkpoints.SetBool( fields[ GAME_FIELD_CHECKPOINTS ].ToBool() ); ui_autoSwitch.SetBool( fields[ GAME_FIELD_AUTO_SWITCH ].ToBool() ); ui_autoReload.SetBool( fields[ GAME_FIELD_AUTO_RELOAD ].ToBool() ); aa_targetAimAssistEnable.SetBool( fields[ GAME_FIELD_AIM_ASSIST ].ToBool() ); in_alwaysRun.SetBool( fields[ GAME_FIELD_ALWAYS_SPRINT ].ToBool() ); g_weaponShadows.SetBool( fields[ GAME_FIELD_FLASHLIGHT_SHADOWS ].ToBool() ); cvarSystem->SetModifiedFlags( CVAR_ARCHIVE ); // make the committed fields into the backup fields originalFields = fields; }
/* ======================== idMenuScreen_Shell_PartyLobby::HandleAction h ======================== */ bool idMenuScreen_Shell_PartyLobby::HandleAction( idWidgetAction& action, const idWidgetEvent& event, idMenuWidget* widget, bool forceHandled ) { if( menuData == NULL ) { return true; } if( menuData->ActiveScreen() != SHELL_AREA_PARTY_LOBBY ) { return false; } widgetAction_t actionType = action.GetType(); const idSWFParmList& parms = action.GetParms(); switch( actionType ) { case WIDGET_ACTION_JOY4_ON_PRESS: { idLobbyBase& activeLobby = session->GetPartyLobbyBase(); lobbyUserID_t luid; if( CanKickSelectedPlayer( luid ) ) { activeLobby.KickLobbyUser( luid ); } return true; } case WIDGET_ACTION_GO_BACK: { class idSWFScriptFunction_Accept : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Accept() { } idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ) { common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_MAIN ); session->Cancel(); return idSWFScriptVar(); } }; class idSWFScriptFunction_Cancel : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Cancel() { } idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ) { common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_MAIN ); return idSWFScriptVar(); } }; idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase(); if( activeLobby.GetNumActiveLobbyUsers() > 1 ) { common->Dialog().AddDialog( GDM_LEAVE_LOBBY_RET_MAIN, DIALOG_ACCEPT_CANCEL, new( TAG_SWF ) idSWFScriptFunction_Accept(), new( TAG_SWF ) idSWFScriptFunction_Cancel(), false ); } else { session->Cancel(); } return true; } case WIDGET_ACTION_MUTE_PLAYER: { if( parms.Num() != 1 ) { return true; } int index = parms[0].ToInteger(); idLobbyBase& activeLobby = session->GetPartyLobbyBase(); lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( index ); if( luid.IsValid() ) { session->ToggleLobbyUserVoiceMute( luid ); } return true; } case WIDGET_ACTION_COMMAND: { if( options == NULL ) { return true; } int selectionIndex = options->GetFocusIndex(); if( parms.Num() > 1 ) { selectionIndex = parms[1].ToInteger(); } if( selectionIndex != options->GetFocusIndex() ) { options->SetViewIndex( options->GetViewOffset() + selectionIndex ); options->SetFocusIndex( selectionIndex ); } switch( parms[0].ToInteger() ) { case PARTY_CMD_QUICK: { idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() ); // Reset these to random for quick match. matchParameters.gameMap = GAME_MAP_RANDOM; matchParameters.gameMode = GAME_MODE_RANDOM; // Always a public match. matchParameters.matchFlags &= ~MATCH_INVITE_ONLY; session->UpdatePartyParms( matchParameters ); // Update flags for game lobby. matchParameters.matchFlags = DefaultPartyFlags | DefaultPublicGameFlags; cvarSystem->MoveCVarsToDict( CVAR_SERVERINFO, matchParameters.serverInfo ); // Force a default value for the si_timelimit and si_fraglimit for quickmatch matchParameters.serverInfo.SetInt( "si_timelimit", 15 ); matchParameters.serverInfo.SetInt( "si_fraglimit", 10 ); session->FindOrCreateMatch( matchParameters ); break; } case PARTY_CMD_FIND: { menuData->SetNextScreen( SHELL_AREA_MODE_SELECT, MENU_TRANSITION_SIMPLE ); break; } case PARTY_CMD_CREATE: { idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() ); const bool isInviteOnly = MatchTypeInviteOnly( matchParameters.matchFlags ); matchParameters.matchFlags = DefaultPartyFlags | DefaultPrivateGameFlags; if( isInviteOnly ) { matchParameters.matchFlags |= MATCH_INVITE_ONLY; } int mode = idMath::ClampInt( -1, GAME_COUNT - 1, si_mode.GetInteger() ); const idList< mpMap_t > maps = common->GetMapList(); int map = idMath::ClampInt( -1, maps.Num() - 1, si_map.GetInteger() ); matchParameters.gameMap = map; matchParameters.gameMode = mode; cvarSystem->MoveCVarsToDict( CVAR_SERVERINFO, matchParameters.serverInfo ); session->CreateMatch( matchParameters ); break; } case PARTY_CMD_PWF: { menuData->SetNextScreen( SHELL_AREA_BROWSER, MENU_TRANSITION_SIMPLE ); break; } case PARTY_CMD_LEADERBOARDS: { ShowLeaderboards(); break; } case PARTY_CMD_TOGGLE_PRIVACY: { idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() ); matchParameters.matchFlags ^= MATCH_INVITE_ONLY; session->UpdatePartyParms( matchParameters ); int bitSet = ( matchParameters.matchFlags & MATCH_INVITE_ONLY ); net_inviteOnly.SetBool( bitSet != 0 ? true : false ); break; } case PARTY_CMD_SHOW_PARTY_GAMES: { session->ShowPartySessions(); break; } case PARTY_CMD_INVITE: { if( session->GetPartyLobbyBase().IsLobbyFull() ) { common->Dialog().AddDialog( GDM_CANNOT_INVITE_LOBBY_FULL, DIALOG_CONTINUE, NULL, NULL, true, __FUNCTION__, __LINE__, false ); return true; } InvitePartyOrFriends(); break; } } return true; } case WIDGET_ACTION_START_REPEATER: { if( options == NULL ) { return true; } if( parms.Num() == 4 ) { int selectionIndex = parms[3].ToInteger(); if( selectionIndex != options->GetFocusIndex() ) { options->SetViewIndex( options->GetViewOffset() + selectionIndex ); options->SetFocusIndex( selectionIndex ); } } break; } case WIDGET_ACTION_SELECT_GAMERTAG: { int selectionIndex = lobby->GetFocusIndex(); if( parms.Num() > 0 ) { selectionIndex = parms[0].ToInteger(); } if( selectionIndex != lobby->GetFocusIndex() ) { lobby->SetViewIndex( lobby->GetViewOffset() + selectionIndex ); lobby->SetFocusIndex( selectionIndex ); return true; } idLobbyBase& activeLobby = session->GetPartyLobbyBase(); lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( selectionIndex ); if( luid.IsValid() ) { session->ShowLobbyUserGamerCardUI( luid ); } return true; } } return idMenuWidget::HandleAction( action, event, widget, forceHandled ); }
/* ======================== idMenuScreen_Shell_GameLobby::HandleAction h ======================== */ bool idMenuScreen_Shell_GameLobby::HandleAction( idWidgetAction& action, const idWidgetEvent& event, idMenuWidget* widget, bool forceHandled ) { if( menuData == NULL ) { return true; } if( menuData->ActiveScreen() != SHELL_AREA_GAME_LOBBY ) { return false; } widgetAction_t actionType = action.GetType(); const idSWFParmList& parms = action.GetParms(); switch( actionType ) { case WIDGET_ACTION_JOY4_ON_PRESS: { idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase(); lobbyUserID_t luid; if( CanKickSelectedPlayer( luid ) ) { activeLobby.KickLobbyUser( luid ); } return true; } case WIDGET_ACTION_GO_BACK: { class idSWFScriptFunction_Accept : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Accept() { } idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ) { common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_NEW_PARTY ); session->Cancel(); return idSWFScriptVar(); } }; class idSWFScriptFunction_Cancel : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Cancel() { } idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ) { common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_NEW_PARTY ); return idSWFScriptVar(); } }; idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase(); if( activeLobby.GetNumActiveLobbyUsers() > 1 ) { common->Dialog().AddDialog( GDM_LEAVE_LOBBY_RET_NEW_PARTY, DIALOG_ACCEPT_CANCEL, new( TAG_SWF ) idSWFScriptFunction_Accept(), new( TAG_SWF ) idSWFScriptFunction_Cancel(), false ); } else { session->Cancel(); } return true; } case WIDGET_ACTION_MUTE_PLAYER: { if( parms.Num() != 1 ) { return true; } int index = parms[0].ToInteger(); idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase(); lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( index ); if( luid.IsValid() ) { session->ToggleLobbyUserVoiceMute( luid ); } return true; } case WIDGET_ACTION_COMMAND: { if( options == NULL ) { return true; } int selectionIndex = options->GetFocusIndex(); if( parms.Num() > 1 ) { selectionIndex = parms[1].ToInteger(); } if( selectionIndex != options->GetFocusIndex() ) { options->SetViewIndex( options->GetViewOffset() + selectionIndex ); options->SetFocusIndex( selectionIndex ); } switch( parms[0].ToInteger() ) { case GAME_CMD_START: { idMenuHandler_Shell* handler = dynamic_cast< idMenuHandler_Shell* const >( menuData ); if( handler != NULL ) { handler->SetTimeRemaining( 0 ); } break; } case GAME_CMD_SETTINGS: { menuData->SetNextScreen( SHELL_AREA_MATCH_SETTINGS, MENU_TRANSITION_SIMPLE ); break; } case GAME_CMD_TOGGLE_PRIVACY: { idMatchParameters matchParameters = idMatchParameters( session->GetActivePlatformLobbyBase().GetMatchParms() ); matchParameters.matchFlags ^= MATCH_INVITE_ONLY; session->UpdateMatchParms( matchParameters ); int bitSet = ( matchParameters.matchFlags & MATCH_INVITE_ONLY ); net_inviteOnly.SetBool( bitSet != 0 ? true : false ); // Must update the party parameters too for Xbox JSIP to work in game lobbies. idMatchParameters partyParms = session->GetPartyLobbyBase().GetMatchParms(); if( MatchTypeInviteOnly( matchParameters.matchFlags ) ) { partyParms.matchFlags |= MATCH_INVITE_ONLY; } else { partyParms.matchFlags &= ~MATCH_INVITE_ONLY; } session->UpdatePartyParms( partyParms ); break; } case GAME_CMD_INVITE: { if( session->GetActivePlatformLobbyBase().IsLobbyFull() ) { common->Dialog().AddDialog( GDM_CANNOT_INVITE_LOBBY_FULL, DIALOG_CONTINUE, NULL, NULL, true, __FUNCTION__, __LINE__, false ); return true; } InvitePartyOrFriends(); break; } } return true; } case WIDGET_ACTION_START_REPEATER: { if( options == NULL ) { return true; } if( parms.Num() == 4 ) { int selectionIndex = parms[3].ToInteger(); if( selectionIndex != options->GetFocusIndex() ) { options->SetViewIndex( options->GetViewOffset() + selectionIndex ); options->SetFocusIndex( selectionIndex ); } } break; } case WIDGET_ACTION_SELECT_GAMERTAG: { int selectionIndex = lobby->GetFocusIndex(); if( parms.Num() > 0 ) { selectionIndex = parms[0].ToInteger(); } if( selectionIndex != lobby->GetFocusIndex() ) { lobby->SetViewIndex( lobby->GetViewOffset() + selectionIndex ); lobby->SetFocusIndex( selectionIndex ); return true; } idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase(); lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( selectionIndex ); if( luid.IsValid() ) { session->ShowLobbyUserGamerCardUI( luid ); } return true; } } return idMenuWidget::HandleAction( action, event, widget, forceHandled ); }
void idCollisionModelManagerLocal::DebugOutput( const idVec3& origin ) { int i, k, t; char buf[128]; idVec3 end; idAngles boxAngles; idMat3 modelAxis, boxAxis; idBounds bounds; trace_t trace; if( !cm_testCollision.GetBool() ) { return; } testend = ( idVec3* ) Mem_Alloc( cm_testTimes.GetInteger() * sizeof( idVec3 ), TAG_COLLISION ); if( cm_testReset.GetBool() || ( cm_testWalk.GetBool() && !start.Compare( start ) ) ) { total_translation = total_rotation = 0; min_translation = min_rotation = 999999; max_translation = max_rotation = -999999; num_translation = num_rotation = 0; cm_testReset.SetBool( false ); } if( cm_testWalk.GetBool() ) { start = origin; cm_testOrigin.SetString( va( "%1.2f %1.2f %1.2f", start[0], start[1], start[2] ) ); } else { sscanf( cm_testOrigin.GetString(), "%f %f %f", &start[0], &start[1], &start[2] ); } sscanf( cm_testBox.GetString(), "%f %f %f %f %f %f", &bounds[0][0], &bounds[0][1], &bounds[0][2], &bounds[1][0], &bounds[1][1], &bounds[1][2] ); sscanf( cm_testBoxRotation.GetString(), "%f %f %f", &boxAngles[0], &boxAngles[1], &boxAngles[2] ); boxAxis = boxAngles.ToMat3(); modelAxis.Identity(); idTraceModel itm( bounds ); idRandom random( 0 ); idTimer timer; if( cm_testRandomMany.GetBool() ) { // if many traces in one random direction for( i = 0; i < 3; i++ ) { testend[0][i] = start[i] + random.CRandomFloat() * cm_testLength.GetFloat(); } for( k = 1; k < cm_testTimes.GetInteger(); k++ ) { testend[k] = testend[0]; } } else { // many traces each in a different random direction for( k = 0; k < cm_testTimes.GetInteger(); k++ ) { for( i = 0; i < 3; i++ ) { testend[k][i] = start[i] + random.CRandomFloat() * cm_testLength.GetFloat(); } } } // translational collision detection timer.Clear(); timer.Start(); for( i = 0; i < cm_testTimes.GetInteger(); i++ ) { Translation( &trace, start, testend[i], &itm, boxAxis, CONTENTS_SOLID | CONTENTS_PLAYERCLIP, cm_testModel.GetInteger(), vec3_origin, modelAxis ); } timer.Stop(); t = timer.Milliseconds(); if( t < min_translation ) min_translation = t; if( t > max_translation ) max_translation = t; num_translation++; total_translation += t; if( cm_testTimes.GetInteger() > 9999 ) { sprintf( buf, "%3dK", ( int )( cm_testTimes.GetInteger() / 1000 ) ); } else { sprintf( buf, "%4d", cm_testTimes.GetInteger() ); } common->Printf( "%s translations: %4d milliseconds, (min = %d, max = %d, av = %1.1f)\n", buf, t, min_translation, max_translation, ( float ) total_translation / num_translation ); if( cm_testRandomMany.GetBool() ) { // if many traces in one random direction for( i = 0; i < 3; i++ ) { testend[0][i] = start[i] + random.CRandomFloat() * cm_testRadius.GetFloat(); } for( k = 1; k < cm_testTimes.GetInteger(); k++ ) { testend[k] = testend[0]; } } else { // many traces each in a different random direction for( k = 0; k < cm_testTimes.GetInteger(); k++ ) { for( i = 0; i < 3; i++ ) { testend[k][i] = start[i] + random.CRandomFloat() * cm_testRadius.GetFloat(); } } } if( cm_testRotation.GetBool() ) { // rotational collision detection idVec3 vec( random.CRandomFloat(), random.CRandomFloat(), random.RandomFloat() ); vec.Normalize(); idRotation rotation( vec3_origin, vec, cm_testAngle.GetFloat() ); timer.Clear(); timer.Start(); for( i = 0; i < cm_testTimes.GetInteger(); i++ ) { rotation.SetOrigin( testend[i] ); Rotation( &trace, start, rotation, &itm, boxAxis, CONTENTS_SOLID | CONTENTS_PLAYERCLIP, cm_testModel.GetInteger(), vec3_origin, modelAxis ); } timer.Stop(); t = timer.Milliseconds(); if( t < min_rotation ) min_rotation = t; if( t > max_rotation ) max_rotation = t; num_rotation++; total_rotation += t; if( cm_testTimes.GetInteger() > 9999 ) { sprintf( buf, "%3dK", ( int )( cm_testTimes.GetInteger() / 1000 ) ); } else { sprintf( buf, "%4d", cm_testTimes.GetInteger() ); } common->Printf( "%s rotation: %4d milliseconds, (min = %d, max = %d, av = %1.1f)\n", buf, t, min_rotation, max_rotation, ( float ) total_rotation / num_rotation ); } Mem_Free( testend ); testend = NULL; }
/* ======================== idSnapShot::ReadDeltaForJob ======================== */ bool idSnapShot::ReadDeltaForJob( const char* deltaMem, int deltaSize, int visIndex, idSnapShot* templateStates ) { bool report = net_verboseSnapshotReport.GetBool(); net_verboseSnapshotReport.SetBool( false ); lzwCompressionData_t lzwData; idZeroRunLengthCompressor rleCompressor; idLZWCompressor lzwCompressor( &lzwData ); int bytesRead = 0; // how many uncompressed bytes we read in. Used to figure out compression ratio lzwCompressor.Start( ( uint8* )deltaMem, deltaSize ); // Skip past sequence and baseSequence int sequence = 0; int baseSequence = 0; lzwCompressor.ReadAgnostic( sequence ); lzwCompressor.ReadAgnostic( baseSequence ); lzwCompressor.ReadAgnostic( time ); bytesRead += sizeof( int ) * 3; int objectNum = 0; uint16 delta = 0; while( lzwCompressor.ReadAgnostic( delta, true ) == sizeof( delta ) ) { bytesRead += sizeof( delta ); objectNum += delta; if( objectNum >= 0xFFFF ) { // full delta if( net_verboseSnapshotCompression.GetBool() ) { float compRatio = static_cast<float>( deltaSize ) / static_cast<float>( bytesRead ); idLib::Printf( "Snapshot (%d/%d). ReadSize: %d DeltaSize: %d Ratio: %.3f\n", sequence, baseSequence, bytesRead, deltaSize, compRatio ); } return true; } objectState_t& state = FindOrCreateObjectByID( objectNum ); objectSize_t newsize = 0; lzwCompressor.ReadAgnostic( newsize ); bytesRead += sizeof( newsize ); if( newsize == SIZE_STALE ) { NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d goes stale\n", objectNum ); // sanity bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0; if( !oldVisible ) { NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected already stale\n" ); } state.visMask &= ~( 1 << visIndex ); state.stale = true; // We need to make sure we haven't freed stale objects. assert( state.buffer.Size() > 0 ); // no more data continue; } else if( newsize == SIZE_NOT_STALE ) { NET_VERBOSESNAPSHOT_PRINT( "read delta: object %d no longer stale\n", objectNum ); // sanity bool oldVisible = ( state.visMask & ( 1 << visIndex ) ) != 0; if( oldVisible ) { NET_VERBOSESNAPSHOT_PRINT( "ERROR: unexpected not stale\n" ); } state.visMask |= ( 1 << visIndex ); state.stale = false; // the latest state is packed in, get the new size and continue reading the new state lzwCompressor.ReadAgnostic( newsize ); bytesRead += sizeof( newsize ); } objectState_t* objTemplateState = templateStates->FindObjectByID( objectNum ); if( newsize == 0 ) { // object deleted: reset state now so next one to use it doesn't have old data state.deleted = false; state.stale = false; state.changedCount = 0; state.expectedSequence = 0; state.visMask = 0; state.buffer._Release(); state.createdFromTemplate = false; if( objTemplateState != NULL && objTemplateState->buffer.Size() && objTemplateState->expectedSequence < baseSequence ) { idLib::PrintfIf( net_ssTemplateDebug.GetBool(), "Clearing old template state[%d] [%d<%d]\n", objectNum, objTemplateState->expectedSequence, baseSequence ); objTemplateState->deleted = false; objTemplateState->stale = false; objTemplateState->changedCount = 0; objTemplateState->expectedSequence = 0; objTemplateState->visMask = 0; objTemplateState->buffer._Release(); } } else { // new state? bool debug = false; if( state.buffer.Size() == 0 ) { state.createdFromTemplate = true; // Brand new state if( objTemplateState != NULL && objTemplateState->buffer.Size() > 0 && sequence >= objTemplateState->expectedSequence ) { idLib::PrintfIf( net_ssTemplateDebug.GetBool(), "\nAdding basestate for new object %d (for SS %d/%d. obj base created in ss %d) deltaSize: %d\n", objectNum, sequence, baseSequence, objTemplateState->expectedSequence, deltaSize ); state.buffer = objTemplateState->buffer; if( net_ssTemplateDebug.GetBool() ) { state.Print( "SPAWN STATE" ); debug = true; PrintAlign( "DELTA STATE" ); } } else if( net_ssTemplateDebug.GetBool() ) { idLib::Printf( "\nNew snapobject[%d] in snapshot %d/%d but no basestate found locally so creating new\n", objectNum, sequence, baseSequence ); } } else { state.createdFromTemplate = false; } // the buffer shrank or stayed the same objectBuffer_t newbuffer( newsize ); rleCompressor.Start( NULL, &lzwCompressor, newsize ); objectSize_t compareSize = Min( state.buffer.Size(), newsize ); for( objectSize_t i = 0; i < compareSize; i++ ) { byte b = rleCompressor.ReadByte(); newbuffer[i] = state.buffer[i] + b; if( debug && InDebugRange( i ) ) { idLib::Printf( "%02X", b ); } } // Catch leftover if( newsize > compareSize ) { rleCompressor.ReadBytes( newbuffer.Ptr() + compareSize, newsize - compareSize ); if( debug ) { for( objectSize_t i = compareSize; i < newsize; i++ ) { if( InDebugRange( i ) ) { idLib::Printf( "%02X", newbuffer[i] ); } } } } state.buffer = newbuffer; state.changedCount = sequence; bytesRead += sizeof( byte ) * newsize; if( debug ) { idLib::Printf( "\n" ); state.Print( "NEW STATE" ); } if( report ) { idLib::Printf( " Obj %d Compressed: Size %d \n", objectNum, rleCompressor.CompressedSize() ); } } #ifdef SNAPSHOT_CHECKSUMS extern uint32 SnapObjChecksum( const uint8 * data, int length ); if( state.buffer.Size() > 0 ) { uint32 checksum = 0; lzwCompressor.ReadAgnostic( checksum ); bytesRead += sizeof( checksum ); if( !verify( checksum == SnapObjChecksum( state.buffer.Ptr(), state.buffer.Size() ) ) ) { idLib::Error( " Invalid snapshot checksum" ); } } #endif } // partial delta return false; }
void idLobby::SendSnapshotToPeer( idSnapShot& ss, int p ) { assert( lobbyType == GetActingGameStateLobbyType() ); peer_t& peer = peers[p]; if( net_forceDropSnap.GetBool() ) { net_forceDropSnap.SetBool( false ); return; } if( peer.pauseSnapshots ) { return; } int time = Sys_Milliseconds(); const int throttleMode = session->GetTitleStorageInt( "net_peer_throttle_mode", net_peer_throttle_mode.GetInteger() ); // Real peer throttling based on performance // -We throttle before sending to jobs rather than before sending if( ( throttleMode == 1 || throttleMode == 3 ) && peer.throttledSnapRate > 0 ) { if( time - peer.lastSnapJobTime < peer.throttledSnapRate / 1000 ) // fixme /1000 { // This peer is throttled, skip his snap shot NET_VERBOSESNAPSHOT_PRINT_LEVEL( 2, va( "NET: Throttling peer %d.Skipping snapshot. Time elapsed: %d peer snap rate: %d\n", p, ( time - peer.lastSnapJobTime ), peer.throttledSnapRate ) ); return; } } if( throttleMode != 0 ) { DetectSaturation( p ); } if( peer.maxSnapBps >= 0.0f && ( throttleMode == 2 || throttleMode == 3 ) ) { if( peer.packetProc->GetOutgoingRateBytes() > peer.maxSnapBps ) { return; } } // TrySetPendingSnapshot will try to set the new pending snap. // TrySetPendingSnapshot won't do anything until the last snap set was fully sent out. if( peer.snapProc->TrySetPendingSnapshot( ss ) ) { NET_VERBOSESNAPSHOT_PRINT_LEVEL( 2, va( " ^8Set next pending snapshot peer %d\n", 0 ) ); peer.numSnapsSent++; idSnapShot* baseState = peers[p].snapProc->GetBaseState(); if( verify( baseState != NULL ) ) { baseState->UpdateExpectedSeq( peers[p].snapProc->GetSnapSequence() ); } } else { NET_VERBOSESNAPSHOT_PRINT_LEVEL( 2, va( " ^2FAILED Set next pending snapshot peer %d\n", 0 ) ); } // We send out the pending snap, which could be the most recent, or an old one that hasn't fully been sent // We don't send immediately, since we have to coordinate sending snaps for all peers in same place considering jobs. peer.needToSubmitPendingSnap = true; }