2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2022-02-21 15:33:51 +00:00
# include <iostream>
2022-05-23 15:47:48 +00:00
# include <vector>
2011-08-31 11:56:04 +00:00
2022-03-27 11:31:07 +00:00
# include "base/system.h"
2020-09-26 19:41:58 +00:00
# include "gamecontext.h"
# include "teeinfo.h"
2020-03-11 00:58:50 +00:00
# include <antibot/antibot_data.h>
2022-04-22 23:04:48 +00:00
# include <base/logger.h>
2020-09-26 19:41:58 +00:00
# include <base/math.h>
2022-02-14 23:32:04 +00:00
# include <cstring>
2010-05-29 07:25:38 +00:00
# include <engine/console.h>
2018-06-19 12:45:53 +00:00
# include <engine/engine.h>
2020-09-26 19:41:58 +00:00
# include <engine/map.h>
2018-08-16 19:42:10 +00:00
# include <engine/server/server.h>
2020-09-26 19:41:58 +00:00
# include <engine/shared/config.h>
2015-07-14 20:08:29 +00:00
# include <engine/shared/datafile.h>
# include <engine/shared/linereader.h>
2021-01-09 13:40:30 +00:00
# include <engine/shared/memheap.h>
2015-07-14 20:08:29 +00:00
# include <engine/storage.h>
2010-05-29 07:25:38 +00:00
# include <game/collision.h>
2014-03-12 23:31:50 +00:00
# include <game/gamecore.h>
2020-09-26 19:41:58 +00:00
# include <game/version.h>
2008-08-14 18:42:47 +00:00
2020-04-16 08:46:43 +00:00
# include <game/generated/protocol7.h>
# include <game/generated/protocolglue.h>
2021-01-09 14:18:52 +00:00
# include "entities/character.h"
2011-04-09 06:41:31 +00:00
# include "gamemodes/DDRace.h"
2021-01-09 14:37:02 +00:00
# include "player.h"
2010-08-23 19:37:27 +00:00
# include "score.h"
2022-04-22 23:04:48 +00:00
// Not thread-safe!
class CClientChatLogger : public ILogger
{
CGameContext * m_pGameServer ;
int m_ClientID ;
2022-05-01 09:13:30 +00:00
ILogger * m_pOuterLogger ;
2022-04-22 23:04:48 +00:00
public :
2022-05-01 09:13:30 +00:00
CClientChatLogger ( CGameContext * pGameServer , int ClientID , ILogger * pOuterLogger ) :
2022-04-22 23:04:48 +00:00
m_pGameServer ( pGameServer ) ,
2022-05-01 09:13:30 +00:00
m_ClientID ( ClientID ) ,
m_pOuterLogger ( pOuterLogger )
2022-04-22 23:04:48 +00:00
{
}
void Log ( const CLogMessage * pMessage ) override ;
} ;
void CClientChatLogger : : Log ( const CLogMessage * pMessage )
{
2022-05-01 09:13:30 +00:00
if ( str_comp ( pMessage - > m_aSystem , " chatresp " ) = = 0 )
{
m_pGameServer - > SendChatTarget ( m_ClientID , pMessage - > Message ( ) ) ;
}
else
{
m_pOuterLogger - > Log ( pMessage ) ;
}
2022-04-22 23:04:48 +00:00
}
2010-05-29 07:25:38 +00:00
enum
{
RESET ,
NO_RESET
} ;
2008-08-14 18:42:47 +00:00
2010-05-29 07:25:38 +00:00
void CGameContext : : Construct ( int Resetting )
2008-08-14 18:42:47 +00:00
{
2021-07-22 19:49:26 +00:00
m_Resetting = false ;
2010-05-29 07:25:38 +00:00
m_pServer = 0 ;
2011-04-13 18:37:12 +00:00
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
pPlayer = 0 ;
2011-04-13 18:37:12 +00:00
2022-03-27 11:31:07 +00:00
mem_zero ( & m_aLastPlayerInput , sizeof ( m_aLastPlayerInput ) ) ;
mem_zero ( & m_aPlayerHasInput , sizeof ( m_aPlayerHasInput ) ) ;
2010-05-29 07:25:38 +00:00
m_pController = 0 ;
2021-07-22 19:49:26 +00:00
m_aVoteCommand [ 0 ] = 0 ;
2020-07-01 12:02:47 +00:00
m_VoteType = VOTE_TYPE_UNKNOWN ;
2010-05-29 07:25:38 +00:00
m_VoteCloseTime = 0 ;
m_pVoteOptionFirst = 0 ;
m_pVoteOptionLast = 0 ;
2011-03-26 21:06:29 +00:00
m_NumVoteOptions = 0 ;
2014-03-04 01:48:58 +00:00
m_LastMapVote = 0 ;
2010-05-29 07:25:38 +00:00
2020-06-21 22:45:17 +00:00
m_SqlRandomMapResult = nullptr ;
2021-06-29 20:32:21 +00:00
m_pScore = nullptr ;
m_NumMutes = 0 ;
m_NumVoteMutes = 0 ;
2020-09-26 19:41:58 +00:00
if ( Resetting = = NO_RESET )
2022-02-09 16:07:02 +00:00
{
m_NonEmptySince = 0 ;
2010-05-29 07:25:38 +00:00
m_pVoteOptionHeap = new CHeap ( ) ;
2022-02-09 16:07:02 +00:00
}
2021-06-29 20:32:21 +00:00
2015-07-14 20:08:29 +00:00
m_aDeleteTempfile [ 0 ] = 0 ;
2017-09-12 12:58:44 +00:00
m_TeeHistorianActive = false ;
2010-05-29 07:25:38 +00:00
}
2021-06-29 20:32:21 +00:00
void CGameContext : : Destruct ( int Resetting )
2010-05-29 07:25:38 +00:00
{
2021-06-29 20:32:21 +00:00
for ( auto & pPlayer : m_apPlayers )
delete pPlayer ;
if ( Resetting = = NO_RESET )
delete m_pVoteOptionHeap ;
if ( m_pScore )
{
delete m_pScore ;
m_pScore = nullptr ;
}
2010-05-29 07:25:38 +00:00
}
CGameContext : : CGameContext ( )
{
Construct ( NO_RESET ) ;
2008-09-23 07:43:41 +00:00
}
2021-07-22 19:49:26 +00:00
CGameContext : : CGameContext ( int Reset )
{
Construct ( Reset ) ;
}
2010-05-29 07:25:38 +00:00
CGameContext : : ~ CGameContext ( )
2008-09-23 07:43:41 +00:00
{
2021-07-22 19:49:26 +00:00
Destruct ( m_Resetting ? RESET : NO_RESET ) ;
2008-08-14 18:42:47 +00:00
}
2010-05-29 07:25:38 +00:00
void CGameContext : : Clear ( )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
CHeap * pVoteOptionHeap = m_pVoteOptionHeap ;
2011-03-26 16:44:34 +00:00
CVoteOptionServer * pVoteOptionFirst = m_pVoteOptionFirst ;
CVoteOptionServer * pVoteOptionLast = m_pVoteOptionLast ;
2011-03-26 21:06:29 +00:00
int NumVoteOptions = m_NumVoteOptions ;
2010-05-29 07:25:38 +00:00
CTuningParams Tuning = m_Tuning ;
2021-07-22 19:49:26 +00:00
m_Resetting = true ;
this - > ~ CGameContext ( ) ;
new ( this ) CGameContext ( RESET ) ;
2010-05-29 07:25:38 +00:00
m_pVoteOptionHeap = pVoteOptionHeap ;
m_pVoteOptionFirst = pVoteOptionFirst ;
m_pVoteOptionLast = pVoteOptionLast ;
2011-03-26 21:06:29 +00:00
m_NumVoteOptions = NumVoteOptions ;
2010-05-29 07:25:38 +00:00
m_Tuning = Tuning ;
2008-08-14 18:42:47 +00:00
}
2017-09-12 12:58:44 +00:00
void CGameContext : : TeeHistorianWrite ( const void * pData , int DataSize , void * pUser )
{
CGameContext * pSelf = ( CGameContext * ) pUser ;
2017-10-13 00:48:42 +00:00
aio_write ( pSelf - > m_pTeeHistorianFile , pData , DataSize ) ;
2017-09-12 12:58:44 +00:00
}
2017-09-13 20:35:09 +00:00
void CGameContext : : CommandCallback ( int ClientID , int FlagMask , const char * pCmd , IConsole : : IResult * pResult , void * pUser )
{
CGameContext * pSelf = ( CGameContext * ) pUser ;
if ( pSelf - > m_TeeHistorianActive )
{
pSelf - > m_TeeHistorian . RecordConsoleCommand ( ClientID , FlagMask , pCmd , pResult ) ;
}
}
2022-05-18 08:45:31 +00:00
CNetObj_PlayerInput CGameContext : : GetLastPlayerInput ( int ClientID ) const
{
dbg_assert ( 0 < = ClientID & & ClientID < MAX_CLIENTS , " invalid ClientID " ) ;
return m_aLastPlayerInput [ ClientID ] ;
}
2011-02-12 10:40:36 +00:00
class CCharacter * CGameContext : : GetPlayerChar ( int ClientID )
2008-10-20 23:00:46 +00:00
{
2011-02-12 10:40:36 +00:00
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | ! m_apPlayers [ ClientID ] )
2008-10-20 23:00:46 +00:00
return 0 ;
2011-02-12 10:40:36 +00:00
return m_apPlayers [ ClientID ] - > GetCharacter ( ) ;
2008-10-20 23:00:46 +00:00
}
2018-03-24 13:00:41 +00:00
bool CGameContext : : EmulateBug ( int Bug )
{
return m_MapBugs . Contains ( Bug ) ;
}
2020-05-13 20:27:49 +00:00
void CGameContext : : FillAntibot ( CAntibotRoundData * pData )
2020-03-11 00:58:50 +00:00
{
if ( ! pData - > m_Map . m_pTiles )
{
Collision ( ) - > FillAntibot ( & pData - > m_Map ) ;
}
pData - > m_Tick = Server ( ) - > Tick ( ) ;
mem_zero ( pData - > m_aCharacters , sizeof ( pData - > m_aCharacters ) ) ;
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
CAntibotCharacterData * pChar = & pData - > m_aCharacters [ i ] ;
2020-10-26 14:14:07 +00:00
for ( auto & LatestInput : pChar - > m_aLatestInputs )
2020-03-11 00:58:50 +00:00
{
2020-10-26 14:14:07 +00:00
LatestInput . m_TargetX = - 1 ;
LatestInput . m_TargetY = - 1 ;
2020-03-11 00:58:50 +00:00
}
pChar - > m_Alive = false ;
pChar - > m_Pause = false ;
pChar - > m_Team = - 1 ;
pChar - > m_Pos = vec2 ( - 1 , - 1 ) ;
pChar - > m_Vel = vec2 ( 0 , 0 ) ;
pChar - > m_Angle = - 1 ;
pChar - > m_HookedPlayer = - 1 ;
pChar - > m_SpawnTick = - 1 ;
pChar - > m_WeaponChangeTick = - 1 ;
if ( m_apPlayers [ i ] )
{
str_copy ( pChar - > m_aName , Server ( ) - > ClientName ( i ) , sizeof ( pChar - > m_aName ) ) ;
CCharacter * pGameChar = m_apPlayers [ i ] - > GetCharacter ( ) ;
pChar - > m_Alive = ( bool ) pGameChar ;
pChar - > m_Pause = m_apPlayers [ i ] - > IsPaused ( ) ;
pChar - > m_Team = m_apPlayers [ i ] - > GetTeam ( ) ;
if ( pGameChar )
{
pGameChar - > FillAntibot ( pChar ) ;
}
}
}
}
2021-06-23 05:05:49 +00:00
void CGameContext : : CreateDamageInd ( vec2 Pos , float Angle , int Amount , int64_t Mask )
2008-08-14 18:42:47 +00:00
{
2011-02-13 06:47:51 +00:00
float a = 3 * 3.14159f / 2 + Angle ;
2008-08-14 18:42:47 +00:00
//float a = get_angle(dir);
2020-09-26 19:41:58 +00:00
float s = a - pi / 3 ;
float e = a + pi / 3 ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < Amount ; i + + )
2008-08-14 18:42:47 +00:00
{
2020-09-26 19:41:58 +00:00
float f = mix ( s , e , float ( i + 1 ) / float ( Amount + 2 ) ) ;
2011-06-02 17:13:40 +00:00
CNetEvent_DamageInd * pEvent = ( CNetEvent_DamageInd * ) m_Events . Create ( NETEVENTTYPE_DAMAGEIND , sizeof ( CNetEvent_DamageInd ) , Mask ) ;
2011-02-12 10:40:36 +00:00
if ( pEvent )
2008-08-14 18:42:47 +00:00
{
2011-02-12 10:40:36 +00:00
pEvent - > m_X = ( int ) Pos . x ;
pEvent - > m_Y = ( int ) Pos . y ;
2020-09-26 19:41:58 +00:00
pEvent - > m_Angle = ( int ) ( f * 256.0f ) ;
2008-08-14 18:42:47 +00:00
}
}
}
2021-06-23 05:05:49 +00:00
void CGameContext : : CreateHammerHit ( vec2 Pos , int64_t Mask )
2008-10-17 11:23:21 +00:00
{
// create the event
2011-06-02 17:13:40 +00:00
CNetEvent_HammerHit * pEvent = ( CNetEvent_HammerHit * ) m_Events . Create ( NETEVENTTYPE_HAMMERHIT , sizeof ( CNetEvent_HammerHit ) , Mask ) ;
2011-02-12 10:40:36 +00:00
if ( pEvent )
2008-10-17 11:23:21 +00:00
{
2011-02-12 10:40:36 +00:00
pEvent - > m_X = ( int ) Pos . x ;
pEvent - > m_Y = ( int ) Pos . y ;
2008-10-17 11:23:21 +00:00
}
}
2021-06-23 05:05:49 +00:00
void CGameContext : : CreateExplosion ( vec2 Pos , int Owner , int Weapon , bool NoDamage , int ActivatedTeam , int64_t Mask )
2008-08-14 18:42:47 +00:00
{
// create the event
2011-06-02 17:13:40 +00:00
CNetEvent_Explosion * pEvent = ( CNetEvent_Explosion * ) m_Events . Create ( NETEVENTTYPE_EXPLOSION , sizeof ( CNetEvent_Explosion ) , Mask ) ;
2011-02-12 10:40:36 +00:00
if ( pEvent )
2008-08-14 18:42:47 +00:00
{
2011-02-12 10:40:36 +00:00
pEvent - > m_X = ( int ) Pos . x ;
pEvent - > m_Y = ( int ) Pos . y ;
2008-08-14 18:42:47 +00:00
}
2014-04-13 14:41:02 +00:00
2019-04-24 20:36:47 +00:00
// deal damage
CCharacter * apEnts [ MAX_CLIENTS ] ;
float Radius = 135.0f ;
float InnerRadius = 48.0f ;
2020-09-26 19:41:58 +00:00
int Num = m_World . FindEntities ( Pos , Radius , ( CEntity * * ) apEnts , MAX_CLIENTS , CGameWorld : : ENTTYPE_CHARACTER ) ;
2021-06-23 05:05:49 +00:00
int64_t TeamMask = - 1 ;
2019-04-24 20:36:47 +00:00
for ( int i = 0 ; i < Num ; i + + )
{
vec2 Diff = apEnts [ i ] - > m_Pos - Pos ;
2020-09-26 19:41:58 +00:00
vec2 ForceDir ( 0 , 1 ) ;
2019-04-24 20:36:47 +00:00
float l = length ( Diff ) ;
if ( l )
ForceDir = normalize ( Diff ) ;
2020-09-26 19:41:58 +00:00
l = 1 - clamp ( ( l - InnerRadius ) / ( Radius - InnerRadius ) , 0.0f , 1.0f ) ;
2019-04-24 20:36:47 +00:00
float Strength ;
2020-09-26 19:41:58 +00:00
if ( Owner = = - 1 | | ! m_apPlayers [ Owner ] | | ! m_apPlayers [ Owner ] - > m_TuneZone )
2019-04-24 20:36:47 +00:00
Strength = Tuning ( ) - > m_ExplosionStrength ;
else
Strength = TuningList ( ) [ m_apPlayers [ Owner ] - > m_TuneZone ] . m_ExplosionStrength ;
2018-04-04 17:48:46 +00:00
2019-04-24 20:36:47 +00:00
float Dmg = Strength * l ;
2020-09-26 19:41:58 +00:00
if ( ! ( int ) Dmg )
continue ;
2018-04-04 17:48:46 +00:00
2022-05-04 17:33:48 +00:00
if ( ( GetPlayerChar ( Owner ) ? ! ( GetPlayerChar ( Owner ) - > m_Hit & CCharacter : : DISABLE_HIT_GRENADE ) : g_Config . m_SvHit ) | | NoDamage | | Owner = = apEnts [ i ] - > GetPlayer ( ) - > GetCID ( ) )
2019-04-24 20:36:47 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Owner ! = - 1 & & apEnts [ i ] - > IsAlive ( ) & & ! apEnts [ i ] - > CanCollide ( Owner ) )
continue ;
if ( Owner = = - 1 & & ActivatedTeam ! = - 1 & & apEnts [ i ] - > IsAlive ( ) & & apEnts [ i ] - > Team ( ) ! = ActivatedTeam )
continue ;
2018-04-04 17:48:46 +00:00
2019-04-24 20:36:47 +00:00
// Explode at most once per team
2022-05-04 17:33:48 +00:00
int PlayerTeam = apEnts [ i ] - > Team ( ) ;
if ( ( GetPlayerChar ( Owner ) ? GetPlayerChar ( Owner ) - > m_Hit & CCharacter : : DISABLE_HIT_GRENADE : ! g_Config . m_SvHit ) | | NoDamage )
2019-04-24 20:36:47 +00:00
{
2020-09-26 19:41:58 +00:00
if ( ! CmaskIsSet ( TeamMask , PlayerTeam ) )
continue ;
2019-04-24 20:36:47 +00:00
TeamMask = CmaskUnset ( TeamMask , PlayerTeam ) ;
2018-04-04 18:03:05 +00:00
}
2008-08-14 18:42:47 +00:00
2020-09-26 19:41:58 +00:00
apEnts [ i ] - > TakeDamage ( ForceDir * Dmg * 2 , ( int ) Dmg , Owner , Weapon ) ;
2019-04-24 20:36:47 +00:00
}
2008-08-14 18:42:47 +00:00
}
2019-04-24 20:36:47 +00:00
}
2008-08-14 18:42:47 +00:00
2021-06-23 05:05:49 +00:00
void CGameContext : : CreatePlayerSpawn ( vec2 Pos , int64_t Mask )
2008-08-14 18:42:47 +00:00
{
// create the event
2011-06-02 17:13:40 +00:00
CNetEvent_Spawn * ev = ( CNetEvent_Spawn * ) m_Events . Create ( NETEVENTTYPE_SPAWN , sizeof ( CNetEvent_Spawn ) , Mask ) ;
2008-08-14 18:42:47 +00:00
if ( ev )
{
2011-02-12 10:40:36 +00:00
ev - > m_X = ( int ) Pos . x ;
ev - > m_Y = ( int ) Pos . y ;
2008-08-14 18:42:47 +00:00
}
}
2021-06-23 05:05:49 +00:00
void CGameContext : : CreateDeath ( vec2 Pos , int ClientID , int64_t Mask )
2008-08-14 18:42:47 +00:00
{
// create the event
2011-06-02 17:13:40 +00:00
CNetEvent_Death * pEvent = ( CNetEvent_Death * ) m_Events . Create ( NETEVENTTYPE_DEATH , sizeof ( CNetEvent_Death ) , Mask ) ;
2011-02-12 10:40:36 +00:00
if ( pEvent )
2008-08-14 18:42:47 +00:00
{
2011-02-12 10:40:36 +00:00
pEvent - > m_X = ( int ) Pos . x ;
pEvent - > m_Y = ( int ) Pos . y ;
pEvent - > m_ClientID = ClientID ;
2008-08-14 18:42:47 +00:00
}
}
2021-06-23 05:05:49 +00:00
void CGameContext : : CreateSound ( vec2 Pos , int Sound , int64_t Mask )
2008-08-14 18:42:47 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Sound < 0 )
2008-08-14 18:42:47 +00:00
return ;
// create a sound
2011-06-01 17:43:48 +00:00
CNetEvent_SoundWorld * pEvent = ( CNetEvent_SoundWorld * ) m_Events . Create ( NETEVENTTYPE_SOUNDWORLD , sizeof ( CNetEvent_SoundWorld ) , Mask ) ;
2011-02-12 10:40:36 +00:00
if ( pEvent )
2008-08-14 18:42:47 +00:00
{
2011-02-12 10:40:36 +00:00
pEvent - > m_X = ( int ) Pos . x ;
pEvent - > m_Y = ( int ) Pos . y ;
pEvent - > m_SoundID = Sound ;
2008-08-14 18:42:47 +00:00
}
}
2010-05-29 07:25:38 +00:00
void CGameContext : : CreateSoundGlobal ( int Sound , int Target )
2008-08-14 18:42:47 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Sound < 0 )
2008-08-14 18:42:47 +00:00
return ;
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_SoundGlobal Msg ;
2011-02-12 10:40:36 +00:00
Msg . m_SoundID = Sound ;
2011-12-29 12:56:24 +00:00
if ( Target = = - 2 )
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_NOSEND , - 1 ) ;
else
{
int Flag = MSGFLAG_VITAL ;
if ( Target ! = - 1 )
Flag | = MSGFLAG_NORECORD ;
Server ( ) - > SendPackMsg ( & Msg , Flag , Target ) ;
}
2008-08-14 18:42:47 +00:00
}
2020-08-04 17:14:37 +00:00
void CGameContext : : CallVote ( int ClientID , const char * pDesc , const char * pCmd , const char * pReason , const char * pChatmsg , const char * pSixupDesc )
2014-02-19 20:22:36 +00:00
{
// check if a vote is already running
if ( m_VoteCloseTime )
return ;
2021-06-23 05:05:49 +00:00
int64_t Now = Server ( ) - > Tick ( ) ;
2014-02-19 20:22:36 +00:00
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
2014-05-18 23:57:52 +00:00
if ( ! pPlayer )
return ;
2020-08-04 17:14:37 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , pChatmsg , - 1 , CHAT_SIX ) ;
if ( ! pSixupDesc )
pSixupDesc = pDesc ;
2020-09-30 14:48:42 +00:00
m_VoteCreator = ClientID ;
2020-08-04 17:14:37 +00:00
StartVote ( pDesc , pCmd , pReason , pSixupDesc ) ;
2014-02-19 20:22:36 +00:00
pPlayer - > m_Vote = 1 ;
pPlayer - > m_VotePos = m_VotePos = 1 ;
pPlayer - > m_LastVoteCall = Now ;
}
2020-06-22 15:08:08 +00:00
void CGameContext : : SendChatTarget ( int To , const char * pText , int Flags )
2009-01-11 14:28:35 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Chat Msg ;
Msg . m_Team = 0 ;
2011-02-12 10:40:36 +00:00
Msg . m_ClientID = - 1 ;
2010-05-29 07:25:38 +00:00
Msg . m_pMessage = pText ;
2020-06-24 15:50:22 +00:00
2020-06-24 16:22:41 +00:00
if ( g_Config . m_SvDemoChat )
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NOSEND , - 1 ) ;
2020-06-24 16:22:41 +00:00
2020-06-24 15:50:22 +00:00
if ( To = = - 1 )
{
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; i + + )
2020-06-24 15:50:22 +00:00
{
if ( ! ( ( Server ( ) - > IsSixup ( i ) & & ( Flags & CHAT_SIXUP ) ) | |
2020-09-26 19:41:58 +00:00
( ! Server ( ) - > IsSixup ( i ) & & ( Flags & CHAT_SIX ) ) ) )
2020-06-24 15:50:22 +00:00
continue ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2020-06-24 15:50:22 +00:00
}
}
2014-09-26 00:40:58 +00:00
else
2020-06-24 15:50:22 +00:00
{
if ( ! ( ( Server ( ) - > IsSixup ( To ) & & ( Flags & CHAT_SIXUP ) ) | |
2020-09-26 19:41:58 +00:00
( ! Server ( ) - > IsSixup ( To ) & & ( Flags & CHAT_SIX ) ) ) )
2020-06-24 15:50:22 +00:00
return ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , To ) ;
2020-06-24 15:50:22 +00:00
}
2009-01-11 14:28:35 +00:00
}
2014-07-26 12:46:31 +00:00
void CGameContext : : SendChatTeam ( int Team , const char * pText )
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
if ( ( ( CGameControllerDDRace * ) m_pController ) - > m_Teams . m_Core . Team ( i ) = = Team )
2014-07-26 12:46:31 +00:00
SendChatTarget ( i , pText ) ;
}
2020-06-12 13:25:58 +00:00
void CGameContext : : SendChat ( int ChatterClientID , int Team , const char * pText , int SpamProtectionClientID , int Flags )
2008-08-14 18:42:47 +00:00
{
2011-02-13 05:35:13 +00:00
if ( SpamProtectionClientID > = 0 & & SpamProtectionClientID < MAX_CLIENTS )
2011-02-23 21:39:53 +00:00
if ( ProcessSpamProtection ( SpamProtectionClientID ) )
2010-11-10 21:42:29 +00:00
return ;
2011-04-09 06:41:31 +00:00
char aBuf [ 256 ] , aText [ 256 ] ;
2010-11-19 16:57:53 +00:00
str_copy ( aText , pText , sizeof ( aText ) ) ;
2011-02-12 10:40:36 +00:00
if ( ChatterClientID > = 0 & & ChatterClientID < MAX_CLIENTS )
2011-02-13 05:35:13 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %d:%d:%s: %s " , ChatterClientID , Team , Server ( ) - > ClientName ( ChatterClientID ) , aText ) ;
else if ( ChatterClientID = = - 2 )
2010-11-19 16:57:53 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " ### %s " , aText ) ;
str_copy ( aText , aBuf , sizeof ( aText ) ) ;
2011-02-13 05:35:13 +00:00
ChatterClientID = - 1 ;
2010-11-19 16:57:53 +00:00
}
2008-08-14 18:42:47 +00:00
else
2010-11-19 16:57:53 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " *** %s " , aText ) ;
2020-09-26 19:41:58 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , Team ! = CHAT_ALL ? " teamchat " : " chat " , aBuf ) ;
2008-08-14 18:42:47 +00:00
2010-05-29 07:25:38 +00:00
if ( Team = = CHAT_ALL )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Chat Msg ;
Msg . m_Team = 0 ;
2011-02-12 10:40:36 +00:00
Msg . m_ClientID = ChatterClientID ;
2011-04-09 06:41:31 +00:00
Msg . m_pMessage = aText ;
2013-12-22 17:30:13 +00:00
// pack one for the recording only
2014-09-26 00:40:58 +00:00
if ( g_Config . m_SvDemoChat )
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NOSEND , - 1 ) ;
2013-12-22 17:30:13 +00:00
// send to the clients
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; i + + )
2013-12-22 17:30:13 +00:00
{
2020-06-30 15:57:49 +00:00
if ( ! m_apPlayers [ i ] )
continue ;
2020-06-12 19:22:54 +00:00
bool Send = ( Server ( ) - > IsSixup ( i ) & & ( Flags & CHAT_SIXUP ) ) | |
2020-09-26 19:41:58 +00:00
( ! Server ( ) - > IsSixup ( i ) & & ( Flags & CHAT_SIX ) ) ;
2020-06-12 19:22:54 +00:00
2020-06-30 15:57:49 +00:00
if ( ! m_apPlayers [ i ] - > m_DND & & Send )
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2013-12-22 17:30:13 +00:00
}
2008-08-14 18:42:47 +00:00
}
else
{
2020-09-26 19:41:58 +00:00
CTeamsCore * Teams = & ( ( CGameControllerDDRace * ) m_pController ) - > m_Teams . m_Core ;
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Chat Msg ;
Msg . m_Team = 1 ;
2011-02-12 10:40:36 +00:00
Msg . m_ClientID = ChatterClientID ;
2011-04-09 06:41:31 +00:00
Msg . m_pMessage = aText ;
2011-04-13 18:37:12 +00:00
2009-06-15 13:01:04 +00:00
// pack one for the recording only
2014-09-26 00:40:58 +00:00
if ( g_Config . m_SvDemoChat )
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NOSEND , - 1 ) ;
2011-01-29 00:59:50 +00:00
2009-06-15 13:01:04 +00:00
// send to the clients
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; i + + )
2008-08-14 18:42:47 +00:00
{
2020-09-26 19:41:58 +00:00
if ( m_apPlayers [ i ] ! = 0 )
{
if ( Team = = CHAT_SPEC )
{
if ( m_apPlayers [ i ] - > GetTeam ( ) = = CHAT_SPEC )
{
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2010-10-06 20:35:19 +00:00
}
2020-09-26 19:41:58 +00:00
}
else
{
if ( Teams - > Team ( i ) = = Team & & m_apPlayers [ i ] - > GetTeam ( ) ! = CHAT_SPEC )
{
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2010-10-06 20:35:19 +00:00
}
}
}
2008-08-14 18:42:47 +00:00
}
}
}
2021-12-21 22:22:26 +00:00
void CGameContext : : SendStartWarning ( int ClientID , const char * pMessage )
{
CCharacter * pChr = GetPlayerChar ( ClientID ) ;
if ( pChr & & pChr - > m_LastStartWarning < Server ( ) - > Tick ( ) - 3 * Server ( ) - > TickSpeed ( ) )
{
SendChatTarget ( ClientID , pMessage ) ;
2022-01-26 11:24:54 +00:00
pChr - > m_LastStartWarning = Server ( ) - > Tick ( ) ;
2021-12-21 22:22:26 +00:00
}
}
2011-02-12 10:40:36 +00:00
void CGameContext : : SendEmoticon ( int ClientID , int Emoticon )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Emoticon Msg ;
2011-02-12 10:40:36 +00:00
Msg . m_ClientID = ClientID ;
2010-05-29 07:25:38 +00:00
Msg . m_Emoticon = Emoticon ;
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , - 1 ) ;
2008-08-14 18:42:47 +00:00
}
2011-02-12 10:40:36 +00:00
void CGameContext : : SendWeaponPickup ( int ClientID , int Weapon )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_WeaponPickup Msg ;
Msg . m_Weapon = Weapon ;
2011-02-12 10:40:36 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2008-08-14 18:42:47 +00:00
}
2021-01-09 13:05:54 +00:00
void CGameContext : : SendMotd ( int ClientID )
{
CNetMsg_Sv_Motd Msg ;
Msg . m_pMessage = g_Config . m_SvMotd ;
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
}
void CGameContext : : SendSettings ( int ClientID )
{
if ( Server ( ) - > IsSixup ( ClientID ) )
{
protocol7 : : CNetMsg_Sv_ServerSettings Msg ;
Msg . m_KickVote = g_Config . m_SvVoteKick ;
Msg . m_KickMin = g_Config . m_SvVoteKickMin ;
Msg . m_SpecVote = g_Config . m_SvVoteSpectate ;
Msg . m_TeamLock = 0 ;
Msg . m_TeamBalance = 0 ;
Msg . m_PlayerSlots = g_Config . m_SvMaxClients - g_Config . m_SvSpectatorSlots ;
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
}
}
2018-03-07 16:22:41 +00:00
void CGameContext : : SendBroadcast ( const char * pText , int ClientID , bool IsImportant )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Broadcast Msg ;
Msg . m_pMessage = pText ;
2018-03-07 16:22:41 +00:00
2018-03-07 17:10:57 +00:00
if ( ClientID = = - 1 )
2018-03-07 16:22:41 +00:00
{
2018-08-22 20:27:01 +00:00
dbg_assert ( IsImportant , " broadcast messages to all players must be important " ) ;
2018-03-07 16:22:41 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2018-03-07 16:22:41 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
2018-03-07 16:22:41 +00:00
{
2020-10-26 14:14:07 +00:00
pPlayer - > m_LastBroadcastImportance = true ;
pPlayer - > m_LastBroadcast = Server ( ) - > Tick ( ) ;
2018-03-07 16:22:41 +00:00
}
}
return ;
}
2018-03-07 17:10:57 +00:00
if ( ! m_apPlayers [ ClientID ] )
2018-03-07 16:22:41 +00:00
return ;
2018-03-15 21:35:25 +00:00
if ( ! IsImportant & & m_apPlayers [ ClientID ] - > m_LastBroadcastImportance & & m_apPlayers [ ClientID ] - > m_LastBroadcast > Server ( ) - > Tick ( ) - Server ( ) - > TickSpeed ( ) * 10 )
2018-03-07 16:22:41 +00:00
return ;
2011-02-12 10:40:36 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2018-03-07 16:22:41 +00:00
m_apPlayers [ ClientID ] - > m_LastBroadcast = Server ( ) - > Tick ( ) ;
m_apPlayers [ ClientID ] - > m_LastBroadcastImportance = IsImportant ;
2008-08-14 18:42:47 +00:00
}
2020-08-04 17:14:37 +00:00
void CGameContext : : StartVote ( const char * pDesc , const char * pCommand , const char * pReason , const char * pSixupDesc )
2008-09-24 14:47:03 +00:00
{
// reset votes
2010-05-29 07:25:38 +00:00
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN ;
2011-12-26 09:15:43 +00:00
m_VoteEnforcer = - 1 ;
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2008-09-24 14:47:03 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
2010-05-29 07:25:38 +00:00
{
2020-10-26 14:14:07 +00:00
pPlayer - > m_Vote = 0 ;
pPlayer - > m_VotePos = 0 ;
2010-05-29 07:25:38 +00:00
}
2008-09-24 14:47:03 +00:00
}
2011-04-13 18:37:12 +00:00
2008-09-24 14:47:03 +00:00
// start vote
2014-05-19 00:23:01 +00:00
m_VoteCloseTime = time_get ( ) + time_freq ( ) * g_Config . m_SvVoteTime ;
2010-05-29 07:25:38 +00:00
str_copy ( m_aVoteDescription , pDesc , sizeof ( m_aVoteDescription ) ) ;
2020-08-04 17:14:37 +00:00
str_copy ( m_aSixupVoteDescription , pSixupDesc , sizeof ( m_aSixupVoteDescription ) ) ;
2010-05-29 07:25:38 +00:00
str_copy ( m_aVoteCommand , pCommand , sizeof ( m_aVoteCommand ) ) ;
2011-03-25 09:26:59 +00:00
str_copy ( m_aVoteReason , pReason , sizeof ( m_aVoteReason ) ) ;
2010-05-29 07:25:38 +00:00
SendVoteSet ( - 1 ) ;
m_VoteUpdate = true ;
2008-09-24 14:47:03 +00:00
}
2010-05-29 07:25:38 +00:00
void CGameContext : : EndVote ( )
2008-09-25 12:41:37 +00:00
{
2010-05-29 07:25:38 +00:00
m_VoteCloseTime = 0 ;
SendVoteSet ( - 1 ) ;
2008-09-25 12:41:37 +00:00
}
2011-02-12 10:40:36 +00:00
void CGameContext : : SendVoteSet ( int ClientID )
2008-09-24 14:47:03 +00:00
{
2020-07-01 12:02:47 +00:00
: : CNetMsg_Sv_VoteSet Msg6 ;
protocol7 : : CNetMsg_Sv_VoteSet Msg7 ;
Msg7 . m_ClientID = m_VoteCreator ;
2010-05-29 07:25:38 +00:00
if ( m_VoteCloseTime )
2008-09-24 14:47:03 +00:00
{
2020-09-26 19:41:58 +00:00
Msg6 . m_Timeout = Msg7 . m_Timeout = ( m_VoteCloseTime - time_get ( ) ) / time_freq ( ) ;
2020-08-04 17:14:37 +00:00
Msg6 . m_pDescription = m_aVoteDescription ;
Msg7 . m_pDescription = m_aSixupVoteDescription ;
2020-07-01 12:02:47 +00:00
Msg6 . m_pReason = Msg7 . m_pReason = m_aVoteReason ;
int & Type = ( Msg7 . m_Type = protocol7 : : VOTE_UNKNOWN ) ;
if ( IsKickVote ( ) )
Type = protocol7 : : VOTE_START_KICK ;
else if ( IsSpecVote ( ) )
Type = protocol7 : : VOTE_START_SPEC ;
else if ( IsOptionVote ( ) )
Type = protocol7 : : VOTE_START_OP ;
2008-09-24 14:47:03 +00:00
}
else
{
2020-07-01 12:02:47 +00:00
Msg6 . m_Timeout = Msg7 . m_Timeout = 0 ;
Msg6 . m_pDescription = Msg7 . m_pDescription = " " ;
Msg6 . m_pReason = Msg7 . m_pReason = " " ;
int & Type = ( Msg7 . m_Type = protocol7 : : VOTE_UNKNOWN ) ;
if ( m_VoteEnforce = = VOTE_ENFORCE_NO | | m_VoteEnforce = = VOTE_ENFORCE_NO_ADMIN )
Type = protocol7 : : VOTE_END_FAIL ;
else if ( m_VoteEnforce = = VOTE_ENFORCE_YES | | m_VoteEnforce = = VOTE_ENFORCE_YES_ADMIN )
Type = protocol7 : : VOTE_END_PASS ;
else if ( m_VoteEnforce = = VOTE_ENFORCE_ABORT )
Type = protocol7 : : VOTE_END_ABORT ;
if ( m_VoteEnforce = = VOTE_ENFORCE_NO_ADMIN | | m_VoteEnforce = = VOTE_ENFORCE_YES_ADMIN )
Msg7 . m_ClientID = - 1 ;
}
if ( ClientID = = - 1 )
{
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; i + + )
2020-07-01 12:02:47 +00:00
{
if ( ! m_apPlayers [ i ] )
continue ;
if ( ! Server ( ) - > IsSixup ( i ) )
Server ( ) - > SendPackMsg ( & Msg6 , MSGFLAG_VITAL , i ) ;
else
Server ( ) - > SendPackMsg ( & Msg7 , MSGFLAG_VITAL , i ) ;
}
}
else
{
if ( ! Server ( ) - > IsSixup ( ClientID ) )
Server ( ) - > SendPackMsg ( & Msg6 , MSGFLAG_VITAL , ClientID ) ;
else
Server ( ) - > SendPackMsg ( & Msg7 , MSGFLAG_VITAL , ClientID ) ;
2008-09-24 14:47:03 +00:00
}
}
2011-02-12 10:40:36 +00:00
void CGameContext : : SendVoteStatus ( int ClientID , int Total , int Yes , int No )
2008-09-24 14:47:03 +00:00
{
2021-02-07 14:46:58 +00:00
if ( ClientID = = - 1 )
{
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
if ( Server ( ) - > ClientIngame ( i ) )
SendVoteStatus ( i , Total , Yes , No ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( Total > VANILLA_MAX_CLIENTS & & m_apPlayers [ ClientID ] & & m_apPlayers [ ClientID ] - > GetClientVersion ( ) < = VERSION_DDRACE )
2014-01-02 20:23:27 +00:00
{
2022-02-14 16:36:54 +00:00
Yes = float ( Yes * VANILLA_MAX_CLIENTS ) / float ( Total ) ;
No = float ( No * VANILLA_MAX_CLIENTS ) / float ( Total ) ;
2014-01-02 20:23:27 +00:00
Total = VANILLA_MAX_CLIENTS ;
}
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_VoteStatus Msg = { 0 } ;
Msg . m_Total = Total ;
Msg . m_Yes = Yes ;
Msg . m_No = No ;
2020-09-26 19:41:58 +00:00
Msg . m_Pass = Total - ( Yes + No ) ;
2010-05-29 07:25:38 +00:00
2011-02-12 10:40:36 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-12 10:40:36 +00:00
void CGameContext : : AbortVoteKickOnDisconnect ( int ClientID )
2010-05-29 07:25:38 +00:00
{
2018-07-25 08:29:05 +00:00
if ( m_VoteCloseTime & & ( ( str_startswith ( m_aVoteCommand , " kick " ) & & str_toint ( & m_aVoteCommand [ 5 ] ) = = ClientID ) | |
2020-09-26 19:41:58 +00:00
( str_startswith ( m_aVoteCommand , " set_team " ) & & str_toint ( & m_aVoteCommand [ 9 ] ) = = ClientID ) ) )
2020-07-01 12:02:47 +00:00
m_VoteEnforce = VOTE_ENFORCE_ABORT ;
2010-05-29 07:25:38 +00:00
}
void CGameContext : : CheckPureTuning ( )
{
// might not be created yet during start up
if ( ! m_pController )
return ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( str_comp ( m_pController - > m_pGameType , " DM " ) = = 0 | |
str_comp ( m_pController - > m_pGameType , " TDM " ) = = 0 | |
str_comp ( m_pController - > m_pGameType , " CTF " ) = = 0 )
2008-09-24 14:47:03 +00:00
{
2011-01-29 00:59:50 +00:00
CTuningParams p ;
if ( mem_comp ( & p , & m_Tuning , sizeof ( p ) ) ! = 0 )
2008-09-24 14:47:03 +00:00
{
2010-08-17 22:06:00 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " resetting tuning due to pure server " ) ;
2011-01-29 00:59:50 +00:00
m_Tuning = p ;
2008-09-24 14:47:03 +00:00
}
2011-04-13 18:37:12 +00:00
}
2008-09-24 14:47:03 +00:00
}
2014-03-12 23:31:50 +00:00
void CGameContext : : SendTuningParams ( int ClientID , int Zone )
2008-10-21 17:26:32 +00:00
{
2020-09-26 19:41:58 +00:00
if ( ClientID = = - 1 )
2014-03-29 13:54:43 +00:00
{
2017-04-22 17:04:16 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
{
2020-09-26 19:41:58 +00:00
if ( m_apPlayers [ i ] )
2014-03-29 13:54:43 +00:00
{
2017-04-22 17:04:16 +00:00
if ( m_apPlayers [ i ] - > GetCharacter ( ) )
2014-03-29 13:54:43 +00:00
{
2020-09-26 19:41:58 +00:00
if ( m_apPlayers [ i ] - > GetCharacter ( ) - > m_TuneZone = = Zone )
2014-03-29 13:54:43 +00:00
SendTuningParams ( i , Zone ) ;
2017-04-22 17:04:16 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( m_apPlayers [ i ] - > m_TuneZone = = Zone )
2017-04-22 17:04:16 +00:00
{
SendTuningParams ( i , Zone ) ;
2014-03-29 13:54:43 +00:00
}
}
2017-04-22 17:04:16 +00:00
}
return ;
2014-03-29 13:54:43 +00:00
}
2015-07-09 00:08:14 +00:00
2010-05-29 07:25:38 +00:00
CheckPureTuning ( ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
CMsgPacker Msg ( NETMSGTYPE_SV_TUNEPARAMS ) ;
2014-03-12 23:31:50 +00:00
int * pParams = 0 ;
2020-09-26 19:41:58 +00:00
if ( Zone = = 0 )
2014-03-12 23:31:50 +00:00
pParams = ( int * ) & m_Tuning ;
else
2017-07-26 01:58:00 +00:00
pParams = ( int * ) & ( m_aTuningList [ Zone ] ) ;
2014-06-26 15:37:06 +00:00
2020-09-26 19:41:58 +00:00
unsigned int Last = sizeof ( m_Tuning ) / sizeof ( int ) ;
2020-05-22 15:58:41 +00:00
if ( m_apPlayers [ ClientID ] )
{
int ClientVersion = m_apPlayers [ ClientID ] - > GetClientVersion ( ) ;
if ( ClientVersion < VERSION_DDNET_EXTRATUNES )
Last = 33 ;
else if ( ClientVersion < VERSION_DDNET_HOOKDURATION_TUNE )
Last = 37 ;
else if ( ClientVersion < VERSION_DDNET_FIREDELAY_TUNE )
Last = 38 ;
}
2014-06-26 15:37:06 +00:00
2020-05-22 15:58:41 +00:00
for ( unsigned i = 0 ; i < Last ; i + + )
2017-04-22 17:04:16 +00:00
{
2020-09-26 19:41:58 +00:00
if ( m_apPlayers [ ClientID ] & & m_apPlayers [ ClientID ] - > GetCharacter ( ) )
2014-02-19 20:55:37 +00:00
{
2020-09-25 14:41:17 +00:00
if ( ( i = = 30 ) // laser_damage is removed from 0.7
& & ( Server ( ) - > IsSixup ( ClientID ) ) )
2020-09-25 14:25:59 +00:00
{
continue ;
}
2020-09-25 14:41:17 +00:00
else if ( ( i = = 31 ) // collision
& & ( m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_SOLO | | m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_NOCOLL ) )
2014-02-19 20:55:37 +00:00
{
2017-04-22 17:04:16 +00:00
Msg . AddInt ( 0 ) ;
}
2020-09-26 19:41:58 +00:00
else if ( ( i = = 32 ) // hooking
& & ( m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_SOLO | | m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_NOHOOK ) )
2017-04-22 17:04:16 +00:00
{
Msg . AddInt ( 0 ) ;
}
2020-09-26 19:41:58 +00:00
else if ( ( i = = 3 ) // ground jump impulse
& & m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_NOJUMP )
2017-04-22 17:04:16 +00:00
{
Msg . AddInt ( 0 ) ;
}
2020-09-26 19:41:58 +00:00
else if ( ( i = = 33 ) // jetpack
& & ! ( m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_JETPACK ) )
2017-04-22 17:04:16 +00:00
{
Msg . AddInt ( 0 ) ;
}
2020-09-26 19:41:58 +00:00
else if ( ( i = = 36 ) // hammer hit
& & m_apPlayers [ ClientID ] - > GetCharacter ( ) - > NeededFaketuning ( ) & FAKETUNE_NOHAMMER )
2017-04-22 17:04:16 +00:00
{
Msg . AddInt ( 0 ) ;
2014-02-19 21:30:57 +00:00
}
2014-02-19 20:55:37 +00:00
else
2017-04-22 17:04:16 +00:00
{
Msg . AddInt ( pParams [ i ] ) ;
}
2014-02-19 20:55:37 +00:00
}
2017-04-22 17:04:16 +00:00
else
Msg . AddInt ( pParams [ i ] ) ; // if everything is normal just send true tunings
}
Server ( ) - > SendMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2008-10-21 17:26:32 +00:00
}
2015-07-09 00:08:14 +00:00
2021-09-14 20:11:22 +00:00
void CGameContext : : OnPreTickTeehistorian ( )
{
2021-10-17 17:27:35 +00:00
if ( ! m_TeeHistorianActive )
return ;
2021-09-14 20:11:22 +00:00
auto * pController = ( ( CGameControllerDDRace * ) m_pController ) ;
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_apPlayers [ i ] ! = nullptr )
m_TeeHistorian . RecordPlayerTeam ( i , pController - > m_Teams . m_Core . Team ( i ) ) ;
2021-09-15 18:03:14 +00:00
else
m_TeeHistorian . RecordPlayerTeam ( i , 0 ) ;
2021-09-14 20:11:22 +00:00
}
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
m_TeeHistorian . RecordTeamPractice ( i , pController - > m_Teams . IsPractice ( i ) ) ;
}
}
2010-05-29 07:25:38 +00:00
void CGameContext : : OnTick ( )
2008-08-14 18:42:47 +00:00
{
2010-05-29 07:25:38 +00:00
// check tuning
CheckPureTuning ( ) ;
2017-09-12 12:58:44 +00:00
if ( m_TeeHistorianActive )
{
2017-10-13 00:48:42 +00:00
int Error = aio_error ( m_pTeeHistorianFile ) ;
2017-10-10 02:07:38 +00:00
if ( Error )
{
dbg_msg ( " teehistorian " , " error writing to file, err=%d " , Error ) ;
2017-10-13 00:25:50 +00:00
Server ( ) - > SetErrorShutdown ( " teehistorian io error " ) ;
2017-10-10 02:07:38 +00:00
}
2017-09-12 12:58:44 +00:00
if ( ! m_TeeHistorian . Starting ( ) )
{
m_TeeHistorian . EndInputs ( ) ;
m_TeeHistorian . EndTick ( ) ;
}
m_TeeHistorian . BeginTick ( Server ( ) - > Tick ( ) ) ;
m_TeeHistorian . BeginPlayers ( ) ;
}
2010-05-29 07:25:38 +00:00
// copy tuning
2014-04-29 01:34:23 +00:00
m_World . m_Core . m_Tuning [ 0 ] = m_Tuning ;
2010-05-29 07:25:38 +00:00
m_World . Tick ( ) ;
2008-08-14 18:42:47 +00:00
//if(world.paused) // make sure that the game object always updates
2010-05-29 07:25:38 +00:00
m_pController - > Tick ( ) ;
2011-04-13 18:37:12 +00:00
2008-08-14 18:42:47 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
2010-05-29 07:25:38 +00:00
if ( m_apPlayers [ i ] )
2011-03-10 09:08:14 +00:00
{
2014-10-26 18:39:42 +00:00
// send vote options
ProgressVoteOptions ( i ) ;
2010-05-29 07:25:38 +00:00
m_apPlayers [ i ] - > Tick ( ) ;
2011-03-10 09:08:14 +00:00
m_apPlayers [ i ] - > PostTick ( ) ;
}
2008-08-14 18:42:47 +00:00
}
2011-04-13 18:37:12 +00:00
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2016-03-04 21:55:12 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
pPlayer - > PostPostTick ( ) ;
2016-03-04 21:55:12 +00:00
}
2008-09-24 14:47:03 +00:00
// update voting
2010-05-29 07:25:38 +00:00
if ( m_VoteCloseTime )
2008-09-24 14:47:03 +00:00
{
2008-10-21 17:26:32 +00:00
// abort the kick-vote on player-leave
2020-07-01 12:02:47 +00:00
if ( m_VoteEnforce = = VOTE_ENFORCE_ABORT )
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , " Vote aborted " ) ;
EndVote ( ) ;
2008-10-21 17:26:32 +00:00
}
else
{
2010-05-29 07:25:38 +00:00
int Total = 0 , Yes = 0 , No = 0 ;
2015-07-08 15:03:22 +00:00
bool Veto = false , VetoStop = false ;
2010-05-29 07:25:38 +00:00
if ( m_VoteUpdate )
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
// count votes
2019-05-01 11:54:51 +00:00
char aaBuf [ MAX_CLIENTS ] [ NETADDR_MAXSTRSIZE ] = { { 0 } } , * pIP = NULL ;
bool SinglePlayer = true ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2019-05-01 11:54:51 +00:00
{
2010-05-29 07:25:38 +00:00
if ( m_apPlayers [ i ] )
2019-05-01 11:54:51 +00:00
{
2011-03-28 18:11:28 +00:00
Server ( ) - > GetClientAddr ( i , aaBuf [ i ] , NETADDR_MAXSTRSIZE ) ;
2019-05-01 11:54:51 +00:00
if ( ! pIP )
pIP = aaBuf [ i ] ;
2019-05-01 19:57:14 +00:00
else if ( SinglePlayer & & str_comp ( pIP , aaBuf [ i ] ) )
2019-05-01 11:54:51 +00:00
SinglePlayer = false ;
}
}
2020-12-23 09:00:38 +00:00
// remember checked players, only the first player with a specific ip will be handled
bool aVoteChecked [ MAX_CLIENTS ] = { false } ;
2021-06-23 05:05:49 +00:00
int64_t Now = Server ( ) - > Tick ( ) ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2008-10-21 17:26:32 +00:00
{
2020-12-23 09:00:38 +00:00
if ( ! m_apPlayers [ i ] | | aVoteChecked [ i ] )
2010-05-29 07:25:38 +00:00
continue ;
2011-04-09 06:41:31 +00:00
2020-07-01 12:02:47 +00:00
if ( ( IsKickVote ( ) | | IsSpecVote ( ) ) & & ( m_apPlayers [ i ] - > GetTeam ( ) = = TEAM_SPECTATORS | |
2020-09-26 19:41:58 +00:00
( GetPlayerChar ( m_VoteCreator ) & & GetPlayerChar ( i ) & &
GetPlayerChar ( m_VoteCreator ) - > Team ( ) ! = GetPlayerChar ( i ) - > Team ( ) ) ) )
2010-05-29 07:25:38 +00:00
continue ;
2011-04-13 18:37:12 +00:00
2015-07-08 14:04:54 +00:00
if ( m_apPlayers [ i ] - > m_Afk & & i ! = m_VoteCreator )
2013-08-18 01:27:30 +00:00
continue ;
2018-12-12 09:41:28 +00:00
// can't vote in kick and spec votes in the beginning after joining
2020-07-01 12:02:47 +00:00
if ( ( IsKickVote ( ) | | IsSpecVote ( ) ) & & Now < m_apPlayers [ i ] - > m_FirstVoteTick )
2018-12-11 09:29:34 +00:00
continue ;
2018-08-16 19:42:10 +00:00
// connecting clients with spoofed ips can clog slots without being ingame
2020-09-26 19:41:58 +00:00
if ( ( ( CServer * ) Server ( ) ) - > m_aClients [ i ] . m_State ! = CServer : : CClient : : STATE_INGAME )
2018-08-16 19:42:10 +00:00
continue ;
2016-09-05 09:38:11 +00:00
// don't count votes by blacklisted clients
2019-05-01 11:54:51 +00:00
if ( g_Config . m_SvDnsblVote & & ! m_pServer - > DnsblWhite ( i ) & & ! SinglePlayer )
2016-09-05 09:38:11 +00:00
continue ;
2022-04-01 16:32:51 +00:00
int CurVote = m_apPlayers [ i ] - > m_Vote ;
int CurVotePos = m_apPlayers [ i ] - > m_VotePos ;
2011-04-13 18:37:12 +00:00
2020-12-12 19:43:18 +00:00
// only allow IPs to vote once, but keep veto ability
2020-12-23 09:00:38 +00:00
// check for more players with the same ip (only use the vote of the one who voted first)
for ( int j = i + 1 ; j < MAX_CLIENTS ; j + + )
2010-05-29 07:25:38 +00:00
{
2020-12-23 09:00:38 +00:00
if ( ! m_apPlayers [ j ] | | aVoteChecked [ j ] | | str_comp ( aaBuf [ j ] , aaBuf [ i ] ) ! = 0 )
continue ;
2020-12-12 19:43:18 +00:00
2020-12-23 09:00:38 +00:00
// count the latest vote by this ip
2022-04-01 16:32:51 +00:00
if ( CurVotePos < m_apPlayers [ j ] - > m_VotePos )
2020-12-23 09:00:38 +00:00
{
2022-04-01 16:32:51 +00:00
CurVote = m_apPlayers [ j ] - > m_Vote ;
CurVotePos = m_apPlayers [ j ] - > m_VotePos ;
2010-05-29 07:25:38 +00:00
}
2020-12-23 09:00:38 +00:00
aVoteChecked [ j ] = true ;
2020-12-12 19:43:18 +00:00
}
2015-07-08 15:03:22 +00:00
2020-12-23 09:00:38 +00:00
Total + + ;
2022-04-01 16:32:51 +00:00
if ( CurVote > 0 )
2020-12-23 09:00:38 +00:00
Yes + + ;
2022-04-01 16:32:51 +00:00
else if ( CurVote < 0 )
2020-12-23 09:00:38 +00:00
No + + ;
2016-01-27 01:14:46 +00:00
// veto right for players who have been active on server for long and who're not afk
2020-12-23 09:00:38 +00:00
if ( ! IsKickVote ( ) & & ! IsSpecVote ( ) & & g_Config . m_SvVoteVetoTime )
2015-07-08 15:03:22 +00:00
{
2020-12-28 10:53:16 +00:00
// look through all players with same IP again, including the current player
for ( int j = i ; j < MAX_CLIENTS ; j + + )
2020-12-23 09:00:38 +00:00
{
2020-12-28 10:53:16 +00:00
// no need to check ip address of current player
if ( i ! = j & & ( ! m_apPlayers [ j ] | | str_comp ( aaBuf [ j ] , aaBuf [ i ] ) ! = 0 ) )
2020-12-23 09:00:38 +00:00
continue ;
if ( m_apPlayers [ j ] & & ! m_apPlayers [ j ] - > m_Afk & & m_apPlayers [ j ] - > GetTeam ( ) ! = TEAM_SPECTATORS & &
( ( Server ( ) - > Tick ( ) - m_apPlayers [ j ] - > m_JoinTick ) / ( Server ( ) - > TickSpeed ( ) * 60 ) > g_Config . m_SvVoteVetoTime | |
( m_apPlayers [ j ] - > GetCharacter ( ) & & m_apPlayers [ j ] - > GetCharacter ( ) - > m_DDRaceState = = DDRACE_STARTED & &
( Server ( ) - > Tick ( ) - m_apPlayers [ j ] - > GetCharacter ( ) - > m_StartTime ) / ( Server ( ) - > TickSpeed ( ) * 60 ) > g_Config . m_SvVoteVetoTime ) ) )
{
2022-04-01 16:32:51 +00:00
if ( CurVote = = 0 )
2020-12-23 09:00:38 +00:00
Veto = true ;
2022-04-01 16:32:51 +00:00
else if ( CurVote < 0 )
2020-12-23 09:00:38 +00:00
VetoStop = true ;
break ;
}
}
2015-07-08 15:03:22 +00:00
}
2008-10-21 17:26:32 +00:00
}
2010-05-29 07:25:38 +00:00
2014-08-12 11:41:57 +00:00
if ( g_Config . m_SvVoteMaxTotal & & Total > g_Config . m_SvVoteMaxTotal & &
2020-09-26 19:41:58 +00:00
( IsKickVote ( ) | | IsSpecVote ( ) ) )
2014-03-22 18:53:43 +00:00
Total = g_Config . m_SvVoteMaxTotal ;
2019-07-08 21:08:42 +00:00
if ( ( Yes > Total / ( 100.0f / g_Config . m_SvVoteYesPercentage ) ) & & ! Veto )
2018-01-13 21:22:55 +00:00
m_VoteEnforce = VOTE_ENFORCE_YES ;
2019-07-08 21:08:42 +00:00
else if ( No > = Total - Total / ( 100.0f / g_Config . m_SvVoteYesPercentage ) )
2010-05-29 07:25:38 +00:00
m_VoteEnforce = VOTE_ENFORCE_NO ;
2011-02-12 20:31:42 +00:00
2015-07-08 15:03:22 +00:00
if ( VetoStop )
m_VoteEnforce = VOTE_ENFORCE_NO ;
2019-07-08 21:08:42 +00:00
m_VoteWillPass = Yes > ( Yes + No ) / ( 100.0f / g_Config . m_SvVoteYesPercentage ) ;
2008-09-24 14:47:03 +00:00
}
2011-04-09 06:41:31 +00:00
2018-01-13 15:46:31 +00:00
if ( time_get ( ) > m_VoteCloseTime & & ! g_Config . m_SvVoteMajority )
2015-07-08 15:03:22 +00:00
m_VoteEnforce = ( m_VoteWillPass & & ! Veto ) ? VOTE_ENFORCE_YES : VOTE_ENFORCE_NO ;
2011-04-13 23:27:49 +00:00
2019-03-21 01:57:22 +00:00
// / Ensure minimum time for vote to end when moderating.
if ( m_VoteEnforce = = VOTE_ENFORCE_YES & & ! ( PlayerModerating ( ) & &
2020-09-26 19:41:58 +00:00
( IsKickVote ( ) | | IsSpecVote ( ) ) & & time_get ( ) < m_VoteCloseTime ) )
2010-05-29 07:25:38 +00:00
{
2019-03-21 01:57:22 +00:00
Server ( ) - > SetRconCID ( IServer : : RCON_CID_VOTE ) ;
Console ( ) - > ExecuteLine ( m_aVoteCommand ) ;
Server ( ) - > SetRconCID ( IServer : : RCON_CID_SERV ) ;
EndVote ( ) ;
2020-07-12 07:34:36 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , " Vote passed " , - 1 , CHAT_SIX ) ;
2019-03-21 01:57:22 +00:00
2020-07-01 12:02:47 +00:00
if ( m_apPlayers [ m_VoteCreator ] & & ! IsKickVote ( ) & & ! IsSpecVote ( ) )
2019-03-21 01:57:22 +00:00
m_apPlayers [ m_VoteCreator ] - > m_LastVoteCall = 0 ;
2010-05-29 07:25:38 +00:00
}
2010-10-11 11:10:39 +00:00
else if ( m_VoteEnforce = = VOTE_ENFORCE_YES_ADMIN )
{
char aBuf [ 64 ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Vote passed enforced by authorized player " ) ;
2011-11-08 11:06:09 +00:00
Console ( ) - > ExecuteLine ( m_aVoteCommand , m_VoteEnforcer ) ;
2020-07-12 07:34:36 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf , - 1 , CHAT_SIX ) ;
2010-10-11 11:10:39 +00:00
EndVote ( ) ;
}
else if ( m_VoteEnforce = = VOTE_ENFORCE_NO_ADMIN )
{
char aBuf [ 64 ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Vote failed enforced by authorized player " ) ;
2010-10-11 11:10:39 +00:00
EndVote ( ) ;
2020-07-12 07:34:36 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf , - 1 , CHAT_SIX ) ;
2010-10-11 11:10:39 +00:00
}
2011-04-09 06:41:31 +00:00
//else if(m_VoteEnforce == VOTE_ENFORCE_NO || time_get() > m_VoteCloseTime)
2011-02-12 20:31:42 +00:00
else if ( m_VoteEnforce = = VOTE_ENFORCE_NO | | ( time_get ( ) > m_VoteCloseTime & & g_Config . m_SvVoteMajority ) )
2010-05-29 07:25:38 +00:00
{
EndVote ( ) ;
2015-07-08 15:03:22 +00:00
if ( VetoStop | | ( m_VoteWillPass & & Veto ) )
2020-07-12 07:34:36 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , " Vote failed because of veto. Find an empty server instead " , - 1 , CHAT_SIX ) ;
2015-07-08 15:03:22 +00:00
else
2020-07-12 07:34:36 +00:00
SendChat ( - 1 , CGameContext : : CHAT_ALL , " Vote failed " , - 1 , CHAT_SIX ) ;
2010-05-29 07:25:38 +00:00
}
else if ( m_VoteUpdate )
{
m_VoteUpdate = false ;
2021-02-07 14:46:58 +00:00
SendVoteStatus ( - 1 , Total , Yes , No ) ;
2010-05-29 07:25:38 +00:00
}
}
}
2011-02-23 21:39:53 +00:00
for ( int i = 0 ; i < m_NumMutes ; i + + )
{
if ( m_aMutes [ i ] . m_Expire < = Server ( ) - > Tick ( ) )
{
m_NumMutes - - ;
m_aMutes [ i ] = m_aMutes [ m_NumMutes ] ;
}
}
2019-03-28 22:35:47 +00:00
for ( int i = 0 ; i < m_NumVoteMutes ; i + + )
{
if ( m_aVoteMutes [ i ] . m_Expire < = Server ( ) - > Tick ( ) )
{
m_NumVoteMutes - - ;
m_aVoteMutes [ i ] = m_aVoteMutes [ m_NumVoteMutes ] ;
}
}
2010-11-22 20:43:22 +00:00
2011-02-23 21:39:53 +00:00
if ( Server ( ) - > Tick ( ) % ( g_Config . m_SvAnnouncementInterval * Server ( ) - > TickSpeed ( ) * 60 ) = = 0 )
2010-11-22 20:43:22 +00:00
{
2017-06-06 03:51:12 +00:00
const char * Line = Server ( ) - > GetAnnouncementLine ( g_Config . m_SvAnnouncementFileName ) ;
2011-02-23 21:39:53 +00:00
if ( Line )
SendChat ( - 1 , CGameContext : : CHAT_ALL , Line ) ;
}
if ( Collision ( ) - > m_NumSwitchers > 0 )
2020-05-27 15:49:07 +00:00
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < Collision ( ) - > m_NumSwitchers + 1 ; + + i )
2010-11-22 20:43:22 +00:00
{
2020-09-26 19:41:58 +00:00
for ( int j = 0 ; j < MAX_CLIENTS ; + + j )
2010-11-22 20:43:22 +00:00
{
2011-02-23 21:39:53 +00:00
if ( Collision ( ) - > m_pSwitchers [ i ] . m_EndTick [ j ] < = Server ( ) - > Tick ( ) & & Collision ( ) - > m_pSwitchers [ i ] . m_Type [ j ] = = TILE_SWITCHTIMEDOPEN )
{
Collision ( ) - > m_pSwitchers [ i ] . m_Status [ j ] = false ;
Collision ( ) - > m_pSwitchers [ i ] . m_EndTick [ j ] = 0 ;
Collision ( ) - > m_pSwitchers [ i ] . m_Type [ j ] = TILE_SWITCHCLOSE ;
}
else if ( Collision ( ) - > m_pSwitchers [ i ] . m_EndTick [ j ] < = Server ( ) - > Tick ( ) & & Collision ( ) - > m_pSwitchers [ i ] . m_Type [ j ] = = TILE_SWITCHTIMEDCLOSE )
{
Collision ( ) - > m_pSwitchers [ i ] . m_Status [ j ] = true ;
Collision ( ) - > m_pSwitchers [ i ] . m_EndTick [ j ] = 0 ;
Collision ( ) - > m_pSwitchers [ i ] . m_Type [ j ] = TILE_SWITCHOPEN ;
}
2010-11-22 20:43:22 +00:00
}
}
2020-05-27 15:49:07 +00:00
}
2010-11-22 20:43:22 +00:00
2020-12-08 11:03:43 +00:00
if ( m_SqlRandomMapResult ! = nullptr & & m_SqlRandomMapResult - > m_Completed )
2020-06-21 22:45:17 +00:00
{
2020-12-08 11:03:43 +00:00
if ( m_SqlRandomMapResult - > m_Success )
2020-06-21 22:45:17 +00:00
{
if ( PlayerExists ( m_SqlRandomMapResult - > m_ClientID ) & & m_SqlRandomMapResult - > m_aMessage [ 0 ] ! = ' \0 ' )
SendChatTarget ( m_SqlRandomMapResult - > m_ClientID , m_SqlRandomMapResult - > m_aMessage ) ;
2021-09-13 09:47:47 +00:00
if ( m_SqlRandomMapResult - > m_aMap [ 0 ] ! = ' \0 ' )
2020-04-23 19:34:55 +00:00
Server ( ) - > ChangeMap ( m_SqlRandomMapResult - > m_aMap ) ;
2020-06-21 22:45:17 +00:00
else
m_LastMapVote = 0 ;
}
m_SqlRandomMapResult = nullptr ;
}
2010-05-29 07:25:38 +00:00
# ifdef CONF_DEBUG
if ( g_Config . m_DbgDummies )
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < g_Config . m_DbgDummies ; i + + )
2010-05-29 07:25:38 +00:00
{
CNetObj_PlayerInput Input = { 0 } ;
2020-09-26 19:41:58 +00:00
Input . m_Direction = ( i & 1 ) ? - 1 : 1 ;
m_apPlayers [ MAX_CLIENTS - i - 1 ] - > OnPredictedInput ( & Input ) ;
2010-05-29 07:25:38 +00:00
}
}
2011-04-13 18:37:12 +00:00
# endif
2021-08-14 10:40:11 +00:00
// Record player position at the end of the tick
if ( m_TeeHistorianActive )
{
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_apPlayers [ i ] & & m_apPlayers [ i ] - > GetCharacter ( ) )
{
CNetObj_CharacterCore Char ;
m_apPlayers [ i ] - > GetCharacter ( ) - > GetCore ( ) . Write ( & Char ) ;
m_TeeHistorian . RecordPlayer ( i , & Char ) ;
}
else
{
m_TeeHistorian . RecordDeadPlayer ( i ) ;
}
}
m_TeeHistorian . EndPlayers ( ) ;
m_TeeHistorian . BeginInputs ( ) ;
}
// Warning: do not put code in this function directly above or below this comment
2010-05-29 07:25:38 +00:00
}
// Server hooks
void CGameContext : : OnClientDirectInput ( int ClientID , void * pInput )
{
if ( ! m_World . m_Paused )
m_apPlayers [ ClientID ] - > OnDirectInput ( ( CNetObj_PlayerInput * ) pInput ) ;
2017-09-12 12:58:44 +00:00
2020-09-23 14:52:50 +00:00
int Flags = ( ( CNetObj_PlayerInput * ) pInput ) - > m_PlayerFlags ;
if ( ( Flags & 256 ) | | ( Flags & 512 ) )
{
Server ( ) - > Kick ( ClientID , " please update your client or use DDNet client " ) ;
}
2010-05-29 07:25:38 +00:00
}
void CGameContext : : OnClientPredictedInput ( int ClientID , void * pInput )
{
2022-03-27 11:31:07 +00:00
// early return if no input at all has been sent by a player
if ( pInput = = nullptr & & ! m_aPlayerHasInput [ ClientID ] )
return ;
// set to last sent input when no new input has been sent
CNetObj_PlayerInput * pApplyInput = ( CNetObj_PlayerInput * ) pInput ;
if ( pApplyInput = = nullptr )
{
pApplyInput = & m_aLastPlayerInput [ ClientID ] ;
}
2010-05-29 07:25:38 +00:00
if ( ! m_World . m_Paused )
2022-03-27 11:31:07 +00:00
m_apPlayers [ ClientID ] - > OnPredictedInput ( pApplyInput ) ;
2010-05-29 07:25:38 +00:00
}
2019-01-29 19:32:11 +00:00
void CGameContext : : OnClientPredictedEarlyInput ( int ClientID , void * pInput )
{
2022-03-27 11:31:07 +00:00
// early return if no input at all has been sent by a player
if ( pInput = = nullptr & & ! m_aPlayerHasInput [ ClientID ] )
return ;
// set to last sent input when no new input has been sent
CNetObj_PlayerInput * pApplyInput = ( CNetObj_PlayerInput * ) pInput ;
if ( pApplyInput = = nullptr )
{
pApplyInput = & m_aLastPlayerInput [ ClientID ] ;
}
else
{
// Store input in this function and not in `OnClientPredictedInput`,
// because this function is called on all inputs, while
// `OnClientPredictedInput` is only called on the first input of each
// tick.
mem_copy ( & m_aLastPlayerInput [ ClientID ] , pApplyInput , sizeof ( m_aLastPlayerInput [ ClientID ] ) ) ;
m_aPlayerHasInput [ ClientID ] = true ;
}
2019-01-29 19:32:11 +00:00
if ( ! m_World . m_Paused )
2022-03-27 11:31:07 +00:00
m_apPlayers [ ClientID ] - > OnPredictedEarlyInput ( pApplyInput ) ;
2021-01-28 21:12:39 +00:00
if ( m_TeeHistorianActive )
{
2022-03-27 11:31:07 +00:00
m_TeeHistorian . RecordPlayerInput ( ClientID , m_apPlayers [ ClientID ] - > GetUniqueCID ( ) , pApplyInput ) ;
2021-01-28 21:12:39 +00:00
}
2019-01-29 19:32:11 +00:00
}
2015-04-18 20:29:28 +00:00
struct CVoteOptionServer * CGameContext : : GetVoteOption ( int Index )
2014-10-26 18:39:42 +00:00
{
CVoteOptionServer * pCurrent ;
2020-09-26 19:41:58 +00:00
for ( pCurrent = m_pVoteOptionFirst ;
Index > 0 & & pCurrent ;
Index - - , pCurrent = pCurrent - > m_pNext )
;
2014-10-26 18:39:42 +00:00
2020-09-26 19:41:58 +00:00
if ( Index > 0 )
2014-10-26 18:39:42 +00:00
return 0 ;
return pCurrent ;
}
void CGameContext : : ProgressVoteOptions ( int ClientID )
{
CPlayer * pPl = m_apPlayers [ ClientID ] ;
2020-09-26 19:41:58 +00:00
if ( pPl - > m_SendVoteIndex = = - 1 )
2014-10-27 12:34:29 +00:00
return ; // we didn't start sending options yet
2014-10-26 18:39:42 +00:00
2020-09-26 19:41:58 +00:00
if ( pPl - > m_SendVoteIndex > m_NumVoteOptions )
2014-10-27 12:34:29 +00:00
return ; // shouldn't happen / fail silently
2014-10-26 18:39:42 +00:00
int VotesLeft = m_NumVoteOptions - pPl - > m_SendVoteIndex ;
2019-04-26 19:36:49 +00:00
int NumVotesToSend = minimum ( g_Config . m_SvSendVotesPerTick , VotesLeft ) ;
2014-10-26 18:39:42 +00:00
2020-09-26 19:41:58 +00:00
if ( ! VotesLeft )
2014-10-26 18:39:42 +00:00
{
// player has up to date vote option list
return ;
}
// build vote option list msg
int CurIndex = 0 ;
CNetMsg_Sv_VoteOptionListAdd OptionMsg ;
OptionMsg . m_pDescription0 = " " ;
OptionMsg . m_pDescription1 = " " ;
OptionMsg . m_pDescription2 = " " ;
OptionMsg . m_pDescription3 = " " ;
OptionMsg . m_pDescription4 = " " ;
OptionMsg . m_pDescription5 = " " ;
OptionMsg . m_pDescription6 = " " ;
OptionMsg . m_pDescription7 = " " ;
OptionMsg . m_pDescription8 = " " ;
OptionMsg . m_pDescription9 = " " ;
OptionMsg . m_pDescription10 = " " ;
OptionMsg . m_pDescription11 = " " ;
OptionMsg . m_pDescription12 = " " ;
OptionMsg . m_pDescription13 = " " ;
OptionMsg . m_pDescription14 = " " ;
// get current vote option by index
CVoteOptionServer * pCurrent = GetVoteOption ( pPl - > m_SendVoteIndex ) ;
2015-06-02 09:55:16 +00:00
while ( CurIndex < NumVotesToSend & & pCurrent ! = NULL )
2014-10-26 18:39:42 +00:00
{
switch ( CurIndex )
{
2020-09-26 19:41:58 +00:00
case 0 : OptionMsg . m_pDescription0 = pCurrent - > m_aDescription ; break ;
case 1 : OptionMsg . m_pDescription1 = pCurrent - > m_aDescription ; break ;
case 2 : OptionMsg . m_pDescription2 = pCurrent - > m_aDescription ; break ;
case 3 : OptionMsg . m_pDescription3 = pCurrent - > m_aDescription ; break ;
case 4 : OptionMsg . m_pDescription4 = pCurrent - > m_aDescription ; break ;
case 5 : OptionMsg . m_pDescription5 = pCurrent - > m_aDescription ; break ;
case 6 : OptionMsg . m_pDescription6 = pCurrent - > m_aDescription ; break ;
case 7 : OptionMsg . m_pDescription7 = pCurrent - > m_aDescription ; break ;
case 8 : OptionMsg . m_pDescription8 = pCurrent - > m_aDescription ; break ;
case 9 : OptionMsg . m_pDescription9 = pCurrent - > m_aDescription ; break ;
case 10 : OptionMsg . m_pDescription10 = pCurrent - > m_aDescription ; break ;
case 11 : OptionMsg . m_pDescription11 = pCurrent - > m_aDescription ; break ;
case 12 : OptionMsg . m_pDescription12 = pCurrent - > m_aDescription ; break ;
case 13 : OptionMsg . m_pDescription13 = pCurrent - > m_aDescription ; break ;
case 14 : OptionMsg . m_pDescription14 = pCurrent - > m_aDescription ; break ;
2014-10-26 18:39:42 +00:00
}
CurIndex + + ;
pCurrent = pCurrent - > m_pNext ;
}
// send msg
OptionMsg . m_NumOptions = NumVotesToSend ;
Server ( ) - > SendPackMsg ( & OptionMsg , MSGFLAG_VITAL , ClientID ) ;
pPl - > m_SendVoteIndex + = NumVotesToSend ;
}
2011-02-12 10:40:36 +00:00
void CGameContext : : OnClientEnter ( int ClientID )
2010-05-29 07:25:38 +00:00
{
2022-02-07 11:16:37 +00:00
if ( m_TeeHistorianActive )
{
m_TeeHistorian . RecordPlayerReady ( ClientID ) ;
}
2021-01-13 00:59:29 +00:00
m_pController - > OnPlayerConnect ( m_apPlayers [ ClientID ] ) ;
2020-06-16 15:54:01 +00:00
if ( Server ( ) - > IsSixup ( ClientID ) )
{
2020-06-21 14:22:38 +00:00
{
protocol7 : : CNetMsg_Sv_GameInfo Msg ;
Msg . m_GameFlags = protocol7 : : GAMEFLAG_RACE ;
Msg . m_MatchCurrent = 1 ;
Msg . m_MatchNum = 0 ;
Msg . m_ScoreLimit = 0 ;
Msg . m_TimeLimit = 0 ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-06-21 14:22:38 +00:00
}
// /team is essential
{
protocol7 : : CNetMsg_Sv_CommandInfoRemove Msg ;
Msg . m_Name = " team " ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-06-21 14:22:38 +00:00
}
2020-06-16 17:10:07 +00:00
for ( const IConsole : : CCommandInfo * pCmd = Console ( ) - > FirstCommandInfo ( IConsole : : ACCESS_LEVEL_USER , CFGFLAG_CHAT ) ;
pCmd ; pCmd = pCmd - > NextCommandInfo ( IConsole : : ACCESS_LEVEL_USER , CFGFLAG_CHAT ) )
{
2022-03-22 22:39:58 +00:00
if ( ! str_comp_nocase ( pCmd - > m_pName , " w " ) | | ! str_comp_nocase ( pCmd - > m_pName , " whisper " ) )
2020-06-21 14:22:38 +00:00
continue ;
const char * pName = pCmd - > m_pName ;
2022-03-22 22:39:58 +00:00
if ( ! str_comp_nocase ( pCmd - > m_pName , " r " ) )
2020-06-21 14:22:38 +00:00
pName = " rescue " ;
2020-06-16 17:10:07 +00:00
protocol7 : : CNetMsg_Sv_CommandInfo Msg ;
2020-06-21 14:22:38 +00:00
Msg . m_Name = pName ;
2020-06-16 17:10:07 +00:00
Msg . m_ArgsFormat = pCmd - > m_pParams ;
Msg . m_HelpText = pCmd - > m_pHelp ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-06-16 17:10:07 +00:00
}
2020-06-16 15:54:01 +00:00
}
2018-12-17 13:55:58 +00:00
{
int Empty = - 1 ;
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( ! Server ( ) - > ClientIngame ( i ) )
{
Empty = i ;
break ;
}
}
CNetMsg_Sv_Chat Msg ;
Msg . m_Team = 0 ;
Msg . m_ClientID = Empty ;
Msg . m_pMessage = " Do you know someone who uses a bot? Please report them to the moderators. " ;
m_apPlayers [ ClientID ] - > m_EligibleForFinishCheck = time_get ( ) ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2018-12-17 13:55:58 +00:00
}
2021-12-14 05:50:30 +00:00
IServer : : CClientInfo Info ;
Server ( ) - > GetClientInfo ( ClientID , & Info ) ;
if ( Info . m_GotDDNetVersion )
{
if ( OnClientDDNetVersionKnown ( ClientID ) )
return ; // kicked
}
2017-06-06 03:51:12 +00:00
if ( ! Server ( ) - > ClientPrevIngame ( ClientID ) )
2011-01-20 20:25:09 +00:00
{
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvWelcome [ 0 ] ! = 0 )
SendChatTarget ( ClientID , g_Config . m_SvWelcome ) ;
2011-12-31 17:16:40 +00:00
2022-03-03 21:56:32 +00:00
if ( g_Config . m_SvShowOthersDefault > SHOW_OTHERS_OFF )
2013-10-20 21:22:49 +00:00
{
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvShowOthers )
2016-05-20 16:36:32 +00:00
SendChatTarget ( ClientID , " You can see other players. To disable this use DDNet client and type /showothers . " ) ;
2013-10-20 21:22:49 +00:00
2020-09-20 10:16:25 +00:00
m_apPlayers [ ClientID ] - > m_ShowOthers = g_Config . m_SvShowOthersDefault ;
2013-10-20 21:22:49 +00:00
}
2011-01-20 20:25:09 +00:00
}
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true ;
2011-08-26 18:03:30 +00:00
2014-03-28 11:52:03 +00:00
// send active vote
if ( m_VoteCloseTime )
SendVoteSet ( ClientID ) ;
2019-11-04 14:33:17 +00:00
Server ( ) - > ExpireServerInfo ( ) ;
2020-03-29 02:36:38 +00:00
2020-06-10 16:12:10 +00:00
CPlayer * pNewPlayer = m_apPlayers [ ClientID ] ;
2022-03-27 11:31:07 +00:00
mem_zero ( & m_aLastPlayerInput [ ClientID ] , sizeof ( m_aLastPlayerInput [ ClientID ] ) ) ;
m_aPlayerHasInput [ ClientID ] = false ;
2020-06-15 13:37:09 +00:00
// new info for others
protocol7 : : CNetMsg_Sv_ClientInfo NewClientInfoMsg ;
NewClientInfoMsg . m_ClientID = ClientID ;
NewClientInfoMsg . m_Local = 0 ;
NewClientInfoMsg . m_Team = pNewPlayer - > GetTeam ( ) ;
NewClientInfoMsg . m_pName = Server ( ) - > ClientName ( ClientID ) ;
NewClientInfoMsg . m_pClan = Server ( ) - > ClientClan ( ClientID ) ;
NewClientInfoMsg . m_Country = Server ( ) - > ClientCountry ( ClientID ) ;
NewClientInfoMsg . m_Silent = false ;
for ( int p = 0 ; p < 6 ; p + + )
{
NewClientInfoMsg . m_apSkinPartNames [ p ] = pNewPlayer - > m_TeeInfos . m_apSkinPartNames [ p ] ;
NewClientInfoMsg . m_aUseCustomColors [ p ] = pNewPlayer - > m_TeeInfos . m_aUseCustomColors [ p ] ;
NewClientInfoMsg . m_aSkinPartColors [ p ] = pNewPlayer - > m_TeeInfos . m_aSkinPartColors [ p ] ;
}
2020-04-16 08:46:43 +00:00
// update client infos (others before local)
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; + + i )
2020-03-29 02:36:38 +00:00
{
if ( i = = ClientID | | ! m_apPlayers [ i ] | | ! Server ( ) - > ClientIngame ( i ) )
continue ;
2020-06-10 16:12:10 +00:00
CPlayer * pPlayer = m_apPlayers [ i ] ;
2020-04-13 12:19:07 +00:00
if ( Server ( ) - > IsSixup ( i ) )
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & NewClientInfoMsg , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2020-03-29 02:36:38 +00:00
if ( Server ( ) - > IsSixup ( ClientID ) )
{
// existing infos for new player
2020-06-14 17:32:14 +00:00
protocol7 : : CNetMsg_Sv_ClientInfo ClientInfoMsg ;
ClientInfoMsg . m_ClientID = i ;
ClientInfoMsg . m_Local = 0 ;
ClientInfoMsg . m_Team = pPlayer - > GetTeam ( ) ;
ClientInfoMsg . m_pName = Server ( ) - > ClientName ( i ) ;
ClientInfoMsg . m_pClan = Server ( ) - > ClientClan ( i ) ;
ClientInfoMsg . m_Country = Server ( ) - > ClientCountry ( i ) ;
ClientInfoMsg . m_Silent = 0 ;
for ( int p = 0 ; p < 6 ; p + + )
{
ClientInfoMsg . m_apSkinPartNames [ p ] = pPlayer - > m_TeeInfos . m_apSkinPartNames [ p ] ;
ClientInfoMsg . m_aUseCustomColors [ p ] = pPlayer - > m_TeeInfos . m_aUseCustomColors [ p ] ;
ClientInfoMsg . m_aSkinPartColors [ p ] = pPlayer - > m_TeeInfos . m_aSkinPartColors [ p ] ;
}
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & ClientInfoMsg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-03-29 02:36:38 +00:00
}
}
// local info
if ( Server ( ) - > IsSixup ( ClientID ) )
{
2020-06-15 13:37:09 +00:00
NewClientInfoMsg . m_Local = 1 ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & NewClientInfoMsg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-03-29 02:36:38 +00:00
}
2021-12-18 10:19:35 +00:00
// initial chat delay
if ( g_Config . m_SvChatInitialDelay ! = 0 & & m_apPlayers [ ClientID ] - > m_JoinTick > m_NonEmptySince + 10 * Server ( ) - > TickSpeed ( ) )
{
NETADDR Addr ;
Server ( ) - > GetClientAddr ( ClientID , & Addr ) ;
2021-12-20 22:20:46 +00:00
Mute ( & Addr , g_Config . m_SvChatInitialDelay , Server ( ) - > ClientName ( ClientID ) , " Initial chat delay " , true ) ;
2021-12-18 10:19:35 +00:00
}
2010-05-29 07:25:38 +00:00
}
2021-02-07 15:03:31 +00:00
bool CGameContext : : OnClientDataPersist ( int ClientID , void * pData )
2010-05-29 07:25:38 +00:00
{
2021-02-07 15:03:31 +00:00
CPersistentClientData * pPersistent = ( CPersistentClientData * ) pData ;
if ( ! m_apPlayers [ ClientID ] )
{
return false ;
}
pPersistent - > m_IsSpectator = m_apPlayers [ ClientID ] - > GetTeam ( ) = = TEAM_SPECTATORS ;
return true ;
}
void CGameContext : : OnClientConnected ( int ClientID , void * pData )
{
CPersistentClientData * pPersistentData = ( CPersistentClientData * ) pData ;
bool Spec = false ;
if ( pPersistentData )
{
Spec = pPersistentData - > m_IsSpectator ;
}
2016-01-19 22:52:28 +00:00
{
bool Empty = true ;
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2016-01-19 22:52:28 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
2016-01-19 22:52:28 +00:00
{
Empty = false ;
break ;
}
}
if ( Empty )
{
m_NonEmptySince = Server ( ) - > Tick ( ) ;
}
}
2010-05-29 07:25:38 +00:00
// Check which team the player should be on
2021-02-07 15:03:31 +00:00
const int StartTeam = ( Spec | | g_Config . m_SvTournamentMode ) ? TEAM_SPECTATORS : m_pController - > GetAutoTeam ( ClientID ) ;
2010-05-29 07:25:38 +00:00
2021-12-18 10:20:22 +00:00
if ( m_apPlayers [ ClientID ] )
2014-08-18 21:50:24 +00:00
delete m_apPlayers [ ClientID ] ;
2022-03-27 11:31:07 +00:00
m_apPlayers [ ClientID ] = new ( ClientID ) CPlayer ( this , NextUniqueClientID , ClientID , StartTeam ) ;
NextUniqueClientID + = 1 ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
# ifdef CONF_DEBUG
if ( g_Config . m_DbgDummies )
{
2020-09-26 19:41:58 +00:00
if ( ClientID > = MAX_CLIENTS - g_Config . m_DbgDummies )
2010-05-29 07:25:38 +00:00
return ;
}
# endif
2021-01-09 13:05:54 +00:00
SendMotd ( ClientID ) ;
SendSettings ( ClientID ) ;
2020-06-16 15:19:53 +00:00
2019-11-04 14:33:17 +00:00
Server ( ) - > ExpireServerInfo ( ) ;
2010-05-29 07:25:38 +00:00
}
2011-02-14 18:41:32 +00:00
void CGameContext : : OnClientDrop ( int ClientID , const char * pReason )
2010-05-29 07:25:38 +00:00
{
2011-02-12 10:40:36 +00:00
AbortVoteKickOnDisconnect ( ClientID ) ;
2021-01-12 20:03:20 +00:00
m_pController - > OnPlayerDisconnect ( m_apPlayers [ ClientID ] , pReason ) ;
2011-02-12 10:40:36 +00:00
delete m_apPlayers [ ClientID ] ;
m_apPlayers [ ClientID ] = 0 ;
2011-04-13 18:37:12 +00:00
2010-07-29 05:21:18 +00:00
//(void)m_pController->CheckTeamBalance();
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true ;
2011-03-10 09:08:14 +00:00
// update spectator modes
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2011-03-10 09:08:14 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer & & pPlayer - > m_SpectatorID = = ClientID )
pPlayer - > m_SpectatorID = SPEC_FREEVIEW ;
2011-03-10 09:08:14 +00:00
}
2013-10-18 09:42:35 +00:00
// update conversation targets
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2013-10-18 09:42:35 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer & & pPlayer - > m_LastWhisperTo = = ClientID )
pPlayer - > m_LastWhisperTo = - 1 ;
2013-10-18 09:42:35 +00:00
}
2019-11-04 14:33:17 +00:00
2020-06-16 16:24:43 +00:00
protocol7 : : CNetMsg_Sv_ClientDrop Msg ;
Msg . m_ClientID = ClientID ;
Msg . m_pReason = pReason ;
Msg . m_Silent = false ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , - 1 ) ;
2020-06-16 16:24:43 +00:00
2019-11-04 14:33:17 +00:00
Server ( ) - > ExpireServerInfo ( ) ;
2010-05-29 07:25:38 +00:00
}
2020-06-19 20:06:39 +00:00
void CGameContext : : OnClientEngineJoin ( int ClientID , bool Sixup )
2017-09-13 20:35:09 +00:00
{
if ( m_TeeHistorianActive )
{
2020-06-19 20:06:39 +00:00
m_TeeHistorian . RecordPlayerJoin ( ClientID , ! Sixup ? CTeeHistorian : : PROTOCOL_6 : CTeeHistorian : : PROTOCOL_7 ) ;
2017-09-13 20:35:09 +00:00
}
}
void CGameContext : : OnClientEngineDrop ( int ClientID , const char * pReason )
{
if ( m_TeeHistorianActive )
{
m_TeeHistorian . RecordPlayerDrop ( ClientID , pReason ) ;
}
}
2021-02-11 11:42:26 +00:00
bool CGameContext : : OnClientDDNetVersionKnown ( int ClientID )
2020-05-22 15:58:41 +00:00
{
IServer : : CClientInfo Info ;
Server ( ) - > GetClientInfo ( ClientID , & Info ) ;
int ClientVersion = Info . m_DDNetVersion ;
dbg_msg ( " ddnet " , " cid=%d version=%d " , ClientID , ClientVersion ) ;
if ( m_TeeHistorianActive )
{
if ( Info . m_pConnectionID & & Info . m_pDDNetVersionStr )
{
m_TeeHistorian . RecordDDNetVersion ( ClientID , * Info . m_pConnectionID , ClientVersion , Info . m_pDDNetVersionStr ) ;
}
else
{
m_TeeHistorian . RecordDDNetVersionOld ( ClientID , ClientVersion ) ;
}
}
2021-02-11 11:42:26 +00:00
// Autoban known bot versions.
if ( g_Config . m_SvBannedVersions [ 0 ] ! = ' \0 ' & & IsVersionBanned ( ClientVersion ) )
{
Server ( ) - > Kick ( ClientID , " unsupported client " ) ;
return true ;
}
2020-05-22 15:58:41 +00:00
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
if ( ClientVersion > = VERSION_DDNET_GAMETICK )
pPlayer - > m_TimerType = g_Config . m_SvDefaultTimerType ;
2020-05-27 17:45:30 +00:00
// First update the teams state.
2020-05-22 15:58:41 +00:00
( ( CGameControllerDDRace * ) m_pController ) - > m_Teams . SendTeamsState ( ClientID ) ;
2020-05-27 17:45:30 +00:00
// Then send records.
2020-05-22 15:58:41 +00:00
SendRecord ( ClientID ) ;
2020-05-27 17:45:30 +00:00
// And report correct tunings.
if ( ClientVersion > = VERSION_DDNET_EXTRATUNES )
2020-05-22 15:58:41 +00:00
SendTuningParams ( ClientID , pPlayer - > m_TuneZone ) ;
2020-05-27 17:45:30 +00:00
// Tell old clients to update.
if ( ClientVersion < VERSION_DDNET_UPDATER_FIXED & & g_Config . m_SvClientSuggestionOld [ 0 ] ! = ' \0 ' )
2020-05-22 15:58:41 +00:00
SendBroadcast ( g_Config . m_SvClientSuggestionOld , ClientID ) ;
2020-05-27 17:45:30 +00:00
// Tell known bot clients that they're botting and we know it.
if ( ( ( ClientVersion > = 15 & & ClientVersion < 100 ) | | ClientVersion = = 502 ) & & g_Config . m_SvClientSuggestionBot [ 0 ] ! = ' \0 ' )
2020-05-22 15:58:41 +00:00
SendBroadcast ( g_Config . m_SvClientSuggestionBot , ClientID ) ;
2021-02-11 11:42:26 +00:00
return false ;
2020-05-22 15:58:41 +00:00
}
2020-06-10 16:12:10 +00:00
void * CGameContext : : PreProcessMsg ( int * MsgID , CUnpacker * pUnpacker , int ClientID )
2010-05-29 07:25:38 +00:00
{
2020-12-23 00:25:04 +00:00
if ( Server ( ) - > IsSixup ( ClientID ) & & * MsgID < OFFSET_UUID )
2017-09-13 20:35:09 +00:00
{
2020-04-16 08:46:43 +00:00
void * pRawMsg = m_NetObjHandler7 . SecureUnpackMsg ( * MsgID , pUnpacker ) ;
2020-03-29 02:36:38 +00:00
if ( ! pRawMsg )
2020-04-16 08:46:43 +00:00
return 0 ;
2020-03-29 02:36:38 +00:00
2020-06-10 16:12:10 +00:00
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
static char s_aRawMsg [ 1024 ] ;
if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_SAY )
2017-10-13 14:25:26 +00:00
{
2020-06-10 16:12:10 +00:00
protocol7 : : CNetMsg_Cl_Say * pMsg7 = ( protocol7 : : CNetMsg_Cl_Say * ) pRawMsg ;
// Should probably use a placement new to start the lifetime of the object to avoid future weirdness
: : CNetMsg_Cl_Say * pMsg = ( : : CNetMsg_Cl_Say * ) s_aRawMsg ;
2020-04-16 08:46:43 +00:00
2020-06-12 13:14:56 +00:00
if ( pMsg7 - > m_Target > = 0 )
{
2020-07-12 22:28:47 +00:00
if ( ProcessSpamProtection ( ClientID ) )
return 0 ;
2020-06-12 13:14:56 +00:00
// Should we maybe recraft the message so that it can go through the usual path?
WhisperID ( ClientID , pMsg7 - > m_Target , pMsg7 - > m_pMessage ) ;
return 0 ;
}
2020-04-16 08:46:43 +00:00
2020-06-10 16:12:10 +00:00
pMsg - > m_Team = pMsg7 - > m_Mode = = protocol7 : : CHAT_TEAM ;
2020-04-16 08:46:43 +00:00
pMsg - > m_pMessage = pMsg7 - > m_pMessage ;
}
2020-06-10 16:12:10 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_STARTINFO )
{
protocol7 : : CNetMsg_Cl_StartInfo * pMsg7 = ( protocol7 : : CNetMsg_Cl_StartInfo * ) pRawMsg ;
: : CNetMsg_Cl_StartInfo * pMsg = ( : : CNetMsg_Cl_StartInfo * ) s_aRawMsg ;
pMsg - > m_pName = pMsg7 - > m_pName ;
pMsg - > m_pClan = pMsg7 - > m_pClan ;
pMsg - > m_Country = pMsg7 - > m_Country ;
CTeeInfo Info ( pMsg7 - > m_apSkinPartNames , pMsg7 - > m_aUseCustomColors , pMsg7 - > m_aSkinPartColors ) ;
Info . FromSixup ( ) ;
pPlayer - > m_TeeInfos = Info ;
2020-06-18 15:10:05 +00:00
str_copy ( s_aRawMsg + sizeof ( * pMsg ) , Info . m_SkinName , sizeof ( s_aRawMsg ) - sizeof ( * pMsg ) ) ;
pMsg - > m_pSkin = s_aRawMsg + sizeof ( * pMsg ) ;
pMsg - > m_UseCustomColor = pPlayer - > m_TeeInfos . m_UseCustomColor ;
pMsg - > m_ColorBody = pPlayer - > m_TeeInfos . m_ColorBody ;
pMsg - > m_ColorFeet = pPlayer - > m_TeeInfos . m_ColorFeet ;
2020-06-10 16:12:10 +00:00
}
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_SKINCHANGE )
{
protocol7 : : CNetMsg_Cl_SkinChange * pMsg = ( protocol7 : : CNetMsg_Cl_SkinChange * ) pRawMsg ;
if ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastChangeInfo & &
pPlayer - > m_LastChangeInfo + Server ( ) - > TickSpeed ( ) * g_Config . m_SvInfoChangeDelay > Server ( ) - > Tick ( ) )
2020-09-26 19:41:58 +00:00
return 0 ;
2020-06-10 16:12:10 +00:00
2020-06-24 13:25:35 +00:00
pPlayer - > m_LastChangeInfo = Server ( ) - > Tick ( ) ;
2020-06-10 16:12:10 +00:00
CTeeInfo Info ( pMsg - > m_apSkinPartNames , pMsg - > m_aUseCustomColors , pMsg - > m_aSkinPartColors ) ;
Info . FromSixup ( ) ;
pPlayer - > m_TeeInfos = Info ;
2020-04-16 08:46:43 +00:00
2020-06-14 17:32:14 +00:00
protocol7 : : CNetMsg_Sv_SkinChange Msg ;
Msg . m_ClientID = ClientID ;
for ( int p = 0 ; p < 6 ; p + + )
{
Msg . m_apSkinPartNames [ p ] = pMsg - > m_apSkinPartNames [ p ] ;
Msg . m_aSkinPartColors [ p ] = pMsg - > m_aSkinPartColors [ p ] ;
Msg . m_aUseCustomColors [ p ] = pMsg - > m_aUseCustomColors [ p ] ;
}
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , - 1 ) ;
2020-06-14 17:32:14 +00:00
2020-06-10 16:12:10 +00:00
return 0 ;
}
2020-06-12 20:53:41 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_SETSPECTATORMODE )
{
protocol7 : : CNetMsg_Cl_SetSpectatorMode * pMsg7 = ( protocol7 : : CNetMsg_Cl_SetSpectatorMode * ) pRawMsg ;
: : CNetMsg_Cl_SetSpectatorMode * pMsg = ( : : CNetMsg_Cl_SetSpectatorMode * ) s_aRawMsg ;
if ( pMsg7 - > m_SpecMode = = protocol7 : : SPEC_FREEVIEW )
pMsg - > m_SpectatorID = SPEC_FREEVIEW ;
else if ( pMsg7 - > m_SpecMode = = protocol7 : : SPEC_PLAYER )
pMsg - > m_SpectatorID = pMsg7 - > m_SpectatorID ;
else
pMsg - > m_SpectatorID = SPEC_FREEVIEW ; // Probably not needed
}
2020-06-16 15:19:53 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_SETTEAM )
{
protocol7 : : CNetMsg_Cl_SetTeam * pMsg7 = ( protocol7 : : CNetMsg_Cl_SetTeam * ) pRawMsg ;
: : CNetMsg_Cl_SetTeam * pMsg = ( : : CNetMsg_Cl_SetTeam * ) s_aRawMsg ;
pMsg - > m_Team = pMsg7 - > m_Team ;
}
2020-06-16 17:10:07 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_COMMAND )
{
protocol7 : : CNetMsg_Cl_Command * pMsg7 = ( protocol7 : : CNetMsg_Cl_Command * ) pRawMsg ;
: : CNetMsg_Cl_Say * pMsg = ( : : CNetMsg_Cl_Say * ) s_aRawMsg ;
str_format ( s_aRawMsg + sizeof ( * pMsg ) , sizeof ( s_aRawMsg ) - sizeof ( * pMsg ) , " /%s %s " , pMsg7 - > m_Name , pMsg7 - > m_Arguments ) ;
pMsg - > m_pMessage = s_aRawMsg + sizeof ( * pMsg ) ;
dbg_msg ( " debug " , " line='%s' " , s_aRawMsg + sizeof ( * pMsg ) ) ;
pMsg - > m_Team = 0 ;
* MsgID = NETMSGTYPE_CL_SAY ;
return s_aRawMsg ;
}
2020-06-20 11:22:46 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_CALLVOTE )
{
protocol7 : : CNetMsg_Cl_CallVote * pMsg7 = ( protocol7 : : CNetMsg_Cl_CallVote * ) pRawMsg ;
: : CNetMsg_Cl_CallVote * pMsg = ( : : CNetMsg_Cl_CallVote * ) s_aRawMsg ;
int Authed = Server ( ) - > GetAuthedState ( ClientID ) ;
if ( pMsg7 - > m_Force )
{
str_format ( s_aRawMsg , sizeof ( s_aRawMsg ) , " force_vote \" %s \" \" %s \" \" %s \" " , pMsg7 - > m_Type , pMsg7 - > m_Value , pMsg7 - > m_Reason ) ;
Console ( ) - > SetAccessLevel ( Authed = = AUTHED_ADMIN ? IConsole : : ACCESS_LEVEL_ADMIN : Authed = = AUTHED_MOD ? IConsole : : ACCESS_LEVEL_MOD : IConsole : : ACCESS_LEVEL_HELPER ) ;
Console ( ) - > ExecuteLine ( s_aRawMsg , ClientID , false ) ;
Console ( ) - > SetAccessLevel ( IConsole : : ACCESS_LEVEL_ADMIN ) ;
return 0 ;
}
pMsg - > m_Value = pMsg7 - > m_Value ;
pMsg - > m_Reason = pMsg7 - > m_Reason ;
pMsg - > m_Type = pMsg7 - > m_Type ;
}
2020-06-23 09:24:09 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_EMOTICON )
{
protocol7 : : CNetMsg_Cl_Emoticon * pMsg7 = ( protocol7 : : CNetMsg_Cl_Emoticon * ) pRawMsg ;
: : CNetMsg_Cl_Emoticon * pMsg = ( : : CNetMsg_Cl_Emoticon * ) s_aRawMsg ;
pMsg - > m_Emoticon = pMsg7 - > m_Emoticon ;
}
2020-07-07 10:16:53 +00:00
else if ( * MsgID = = protocol7 : : NETMSGTYPE_CL_VOTE )
{
protocol7 : : CNetMsg_Cl_Vote * pMsg7 = ( protocol7 : : CNetMsg_Cl_Vote * ) pRawMsg ;
: : CNetMsg_Cl_Vote * pMsg = ( : : CNetMsg_Cl_Vote * ) s_aRawMsg ;
pMsg - > m_Vote = pMsg7 - > m_Vote ;
}
2020-06-10 16:12:10 +00:00
2020-06-12 19:22:54 +00:00
* MsgID = Msg_SevenToSix ( * MsgID ) ;
2020-06-10 16:12:10 +00:00
return s_aRawMsg ;
2020-04-16 08:46:43 +00:00
}
2020-06-10 16:12:10 +00:00
else
2020-04-16 08:46:43 +00:00
return m_NetObjHandler . SecureUnpackMsg ( * MsgID , pUnpacker ) ;
}
2020-09-18 15:37:27 +00:00
void CGameContext : : CensorMessage ( char * pCensoredMessage , const char * pMessage , int Size )
{
str_copy ( pCensoredMessage , pMessage , Size ) ;
2022-05-23 20:35:21 +00:00
for ( auto & Item : m_vCensorlist )
2020-09-18 15:37:27 +00:00
{
2020-10-04 15:25:14 +00:00
char * pCurLoc = pCensoredMessage ;
do
{
2022-05-23 20:35:21 +00:00
pCurLoc = ( char * ) str_utf8_find_nocase ( pCurLoc , Item . c_str ( ) ) ;
2020-10-04 15:25:14 +00:00
if ( pCurLoc )
{
2022-05-23 20:35:21 +00:00
memset ( pCurLoc , ' * ' , Item . length ( ) ) ;
2020-10-04 15:25:14 +00:00
pCurLoc + + ;
}
} while ( pCurLoc ) ;
2020-09-18 15:37:27 +00:00
}
}
2020-04-16 08:46:43 +00:00
void CGameContext : : OnMessage ( int MsgID , CUnpacker * pUnpacker , int ClientID )
{
if ( m_TeeHistorianActive )
{
if ( m_NetObjHandler . TeeHistorianRecordMsg ( MsgID ) )
{
m_TeeHistorian . RecordPlayerMessage ( ClientID , pUnpacker - > CompleteData ( ) , pUnpacker - > CompleteSize ( ) ) ;
2017-10-13 14:25:26 +00:00
}
2017-09-13 20:35:09 +00:00
}
2020-06-10 16:12:10 +00:00
void * pRawMsg = PreProcessMsg ( & MsgID , pUnpacker , ClientID ) ;
2020-06-21 22:06:33 +00:00
if ( ! pRawMsg )
return ;
2020-04-16 08:46:43 +00:00
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
2013-03-23 14:59:27 +00:00
if ( Server ( ) - > ClientIngame ( ClientID ) )
2010-05-29 07:25:38 +00:00
{
2013-03-23 14:59:27 +00:00
if ( MsgID = = NETMSGTYPE_CL_SAY )
2010-05-29 07:25:38 +00:00
{
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_Say * pMsg = ( CNetMsg_Cl_Say * ) pRawMsg ;
2016-01-27 00:48:19 +00:00
if ( ! str_utf8_check ( pMsg - > m_pMessage ) )
2016-01-27 00:24:02 +00:00
{
return ;
}
2018-12-17 13:55:58 +00:00
bool Check = ! pPlayer - > m_NotEligibleForFinish & & pPlayer - > m_EligibleForFinishCheck + 10 * time_freq ( ) > = time_get ( ) ;
if ( Check & & str_comp ( pMsg - > m_pMessage , " xd sure chillerbot.png is lyfe " ) = = 0 & & pMsg - > m_Team = = 0 )
{
if ( m_TeeHistorianActive )
{
m_TeeHistorian . RecordPlayerMessage ( ClientID , pUnpacker - > CompleteData ( ) , pUnpacker - > CompleteSize ( ) ) ;
}
pPlayer - > m_NotEligibleForFinish = true ;
dbg_msg ( " hack " , " bot detected, cid=%d " , ClientID ) ;
return ;
}
2013-12-26 17:02:22 +00:00
int Team = pMsg - > m_Team ;
2013-12-27 03:09:45 +00:00
// trim right and set maximum length to 256 utf8-characters
2013-04-01 18:30:58 +00:00
int Length = 0 ;
const char * p = pMsg - > m_pMessage ;
const char * pEnd = 0 ;
while ( * p )
2015-07-09 00:08:14 +00:00
{
2013-04-01 18:30:58 +00:00
const char * pStrOld = p ;
int Code = str_utf8_decode ( & p ) ;
// check if unicode is not empty
2018-03-14 01:27:15 +00:00
if ( ! str_utf8_isspace ( Code ) )
2013-04-01 18:30:58 +00:00
{
pEnd = 0 ;
}
else if ( pEnd = = 0 )
pEnd = pStrOld ;
2011-04-13 18:37:12 +00:00
2013-12-27 03:09:45 +00:00
if ( + + Length > = 256 )
2013-04-01 18:30:58 +00:00
{
* ( const_cast < char * > ( p ) ) = 0 ;
break ;
}
2015-07-09 00:08:14 +00:00
}
2013-04-01 18:30:58 +00:00
if ( pEnd ! = 0 )
* ( const_cast < char * > ( pEnd ) ) = 0 ;
2011-04-09 06:41:31 +00:00
2014-01-01 21:06:46 +00:00
// drop empty and autocreated spam messages (more than 32 characters per second)
2020-09-26 19:41:58 +00:00
if ( Length = = 0 | | ( pMsg - > m_pMessage [ 0 ] ! = ' / ' & & ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastChat & & pPlayer - > m_LastChat + Server ( ) - > TickSpeed ( ) * ( ( 31 + Length ) / 32 ) > Server ( ) - > Tick ( ) ) ) )
2013-03-23 14:59:27 +00:00
return ;
2010-08-20 20:40:12 +00:00
2020-09-26 19:41:58 +00:00
int GameTeam = ( ( CGameControllerDDRace * ) m_pController ) - > m_Teams . m_Core . Team ( pPlayer - > GetCID ( ) ) ;
2013-12-26 17:02:22 +00:00
if ( Team )
2022-03-07 21:16:28 +00:00
Team = ( ( pPlayer - > GetTeam ( ) = = TEAM_SPECTATORS ) ? CHAT_SPEC : GameTeam ) ;
2013-12-26 17:02:22 +00:00
else
Team = CHAT_ALL ;
2020-09-26 19:41:58 +00:00
if ( pMsg - > m_pMessage [ 0 ] = = ' / ' )
2013-08-09 13:04:20 +00:00
{
2022-03-13 10:42:45 +00:00
if ( str_startswith ( pMsg - > m_pMessage + 1 , " w " ) )
2013-12-26 17:02:22 +00:00
{
2020-05-23 19:55:18 +00:00
char aWhisperMsg [ 256 ] ;
str_copy ( aWhisperMsg , pMsg - > m_pMessage + 3 , 256 ) ;
Whisper ( pPlayer - > GetCID ( ) , aWhisperMsg ) ;
2013-12-26 17:02:22 +00:00
}
2022-03-13 10:42:45 +00:00
else if ( str_startswith ( pMsg - > m_pMessage + 1 , " whisper " ) )
2013-12-26 17:02:22 +00:00
{
2020-05-23 19:55:18 +00:00
char aWhisperMsg [ 256 ] ;
str_copy ( aWhisperMsg , pMsg - > m_pMessage + 9 , 256 ) ;
Whisper ( pPlayer - > GetCID ( ) , aWhisperMsg ) ;
2013-12-26 17:02:22 +00:00
}
2022-03-13 10:42:45 +00:00
else if ( str_startswith ( pMsg - > m_pMessage + 1 , " c " ) )
2013-12-26 17:02:22 +00:00
{
2020-05-23 19:55:18 +00:00
char aWhisperMsg [ 256 ] ;
str_copy ( aWhisperMsg , pMsg - > m_pMessage + 3 , 256 ) ;
Converse ( pPlayer - > GetCID ( ) , aWhisperMsg ) ;
2013-12-26 17:02:22 +00:00
}
2022-03-13 10:42:45 +00:00
else if ( str_startswith ( pMsg - > m_pMessage + 1 , " converse " ) )
2013-12-26 17:02:22 +00:00
{
2020-05-23 19:55:18 +00:00
char aWhisperMsg [ 256 ] ;
str_copy ( aWhisperMsg , pMsg - > m_pMessage + 10 , 256 ) ;
Converse ( pPlayer - > GetCID ( ) , aWhisperMsg ) ;
2013-12-26 17:02:22 +00:00
}
else
{
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvSpamprotection & & ! str_startswith ( pMsg - > m_pMessage + 1 , " timeout " ) & & pPlayer - > m_LastCommands [ 0 ] & & pPlayer - > m_LastCommands [ 0 ] + Server ( ) - > TickSpeed ( ) > Server ( ) - > Tick ( ) & & pPlayer - > m_LastCommands [ 1 ] & & pPlayer - > m_LastCommands [ 1 ] + Server ( ) - > TickSpeed ( ) > Server ( ) - > Tick ( ) & & pPlayer - > m_LastCommands [ 2 ] & & pPlayer - > m_LastCommands [ 2 ] + Server ( ) - > TickSpeed ( ) > Server ( ) - > Tick ( ) & & pPlayer - > m_LastCommands [ 3 ] & & pPlayer - > m_LastCommands [ 3 ] + Server ( ) - > TickSpeed ( ) > Server ( ) - > Tick ( ) )
2013-12-26 17:02:22 +00:00
return ;
2010-08-06 19:03:38 +00:00
2021-06-23 05:05:49 +00:00
int64_t Now = Server ( ) - > Tick ( ) ;
2013-12-26 17:02:22 +00:00
pPlayer - > m_LastCommands [ pPlayer - > m_LastCommandPos ] = Now ;
pPlayer - > m_LastCommandPos = ( pPlayer - > m_LastCommandPos + 1 ) % 4 ;
Console ( ) - > SetFlagMask ( CFGFLAG_CHAT ) ;
2018-01-27 22:13:17 +00:00
int Authed = Server ( ) - > GetAuthedState ( ClientID ) ;
if ( Authed )
2019-03-02 10:50:33 +00:00
Console ( ) - > SetAccessLevel ( Authed = = AUTHED_ADMIN ? IConsole : : ACCESS_LEVEL_ADMIN : Authed = = AUTHED_MOD ? IConsole : : ACCESS_LEVEL_MOD : IConsole : : ACCESS_LEVEL_HELPER ) ;
2013-12-26 17:02:22 +00:00
else
Console ( ) - > SetAccessLevel ( IConsole : : ACCESS_LEVEL_USER ) ;
2022-04-22 23:04:48 +00:00
{
2022-05-01 09:13:30 +00:00
CClientChatLogger Logger ( this , ClientID , log_get_scope_logger ( ) ) ;
2022-04-22 23:04:48 +00:00
CLogScope Scope ( & Logger ) ;
Console ( ) - > ExecuteLine ( pMsg - > m_pMessage + 1 , ClientID , false ) ;
}
2017-01-04 17:14:08 +00:00
// m_apPlayers[ClientID] can be NULL, if the player used a
// timeout code and replaced another client.
2013-12-26 17:02:22 +00:00
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " %d used %s " , ClientID , pMsg - > m_pMessage ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " chat-command " , aBuf ) ;
Console ( ) - > SetAccessLevel ( IConsole : : ACCESS_LEVEL_ADMIN ) ;
Console ( ) - > SetFlagMask ( CFGFLAG_SERVER ) ;
}
2013-08-09 13:04:20 +00:00
}
2013-12-26 17:02:22 +00:00
else
2020-09-18 15:37:27 +00:00
{
2022-01-17 11:58:12 +00:00
pPlayer - > UpdatePlaytime ( ) ;
2020-09-18 15:37:27 +00:00
char aCensoredMessage [ 256 ] ;
CensorMessage ( aCensoredMessage , pMsg - > m_pMessage , sizeof ( aCensoredMessage ) ) ;
SendChat ( ClientID , Team , aCensoredMessage , ClientID ) ;
}
2010-05-29 07:25:38 +00:00
}
2013-03-23 14:59:27 +00:00
else if ( MsgID = = NETMSGTYPE_CL_CALLVOTE )
2010-05-29 07:25:38 +00:00
{
2020-07-01 12:02:47 +00:00
if ( RateLimitPlayerVote ( ClientID ) | | m_VoteCloseTime )
2016-01-19 22:52:28 +00:00
return ;
2018-04-18 17:26:49 +00:00
2020-10-07 21:24:48 +00:00
m_apPlayers [ ClientID ] - > UpdatePlaytime ( ) ;
2020-07-01 12:02:47 +00:00
m_VoteType = VOTE_TYPE_UNKNOWN ;
2013-03-23 14:59:27 +00:00
char aChatmsg [ 512 ] = { 0 } ;
char aDesc [ VOTE_DESC_LENGTH ] = { 0 } ;
2020-08-04 17:14:37 +00:00
char aSixupDesc [ VOTE_DESC_LENGTH ] = { 0 } ;
2013-03-23 14:59:27 +00:00
char aCmd [ VOTE_CMD_LENGTH ] = { 0 } ;
2016-01-19 13:59:16 +00:00
char aReason [ VOTE_REASON_LENGTH ] = " No reason given " ;
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_CallVote * pMsg = ( CNetMsg_Cl_CallVote * ) pRawMsg ;
2020-09-26 19:41:58 +00:00
if ( ! str_utf8_check ( pMsg - > m_Type ) | | ! str_utf8_check ( pMsg - > m_Reason ) | | ! str_utf8_check ( pMsg - > m_Value ) )
2016-01-27 00:24:02 +00:00
{
return ;
}
2016-01-19 13:59:16 +00:00
if ( pMsg - > m_Reason [ 0 ] )
{
str_copy ( aReason , pMsg - > m_Reason , sizeof ( aReason ) ) ;
}
2010-08-06 19:03:38 +00:00
2013-03-23 14:59:27 +00:00
if ( str_comp_nocase ( pMsg - > m_Type , " option " ) = = 0 )
2011-03-04 16:35:50 +00:00
{
2018-01-27 22:13:17 +00:00
int Authed = Server ( ) - > GetAuthedState ( ClientID ) ;
2013-03-23 14:59:27 +00:00
CVoteOptionServer * pOption = m_pVoteOptionFirst ;
while ( pOption )
{
if ( str_comp_nocase ( pMsg - > m_Value , pOption - > m_aDescription ) = = 0 )
{
2013-12-26 17:02:22 +00:00
if ( ! Console ( ) - > LineIsValid ( pOption - > m_aCommand ) )
{
SendChatTarget ( ClientID , " Invalid option " ) ;
return ;
}
2020-11-16 16:32:46 +00:00
if ( ( str_find ( pOption - > m_aCommand , " sv_map " ) ! = 0 | | str_find ( pOption - > m_aCommand , " change_map " ) ! = 0 | | str_find ( pOption - > m_aCommand , " random_map " ) ! = 0 | | str_find ( pOption - > m_aCommand , " random_unfinished_map " ) ! = 0 ) & & RateLimitPlayerMapVote ( ClientID ) )
2013-12-26 17:02:22 +00:00
{
return ;
}
2014-10-10 22:41:56 +00:00
2013-03-23 14:59:27 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' called vote to change server option '%s' (%s) " , Server ( ) - > ClientName ( ClientID ) ,
2020-09-26 19:41:58 +00:00
pOption - > m_aDescription , aReason ) ;
2013-03-23 14:59:27 +00:00
str_format ( aDesc , sizeof ( aDesc ) , " %s " , pOption - > m_aDescription ) ;
2014-10-10 22:41:56 +00:00
2020-11-16 16:32:46 +00:00
if ( ( str_endswith ( pOption - > m_aCommand , " random_map " ) | | str_endswith ( pOption - > m_aCommand , " random_unfinished_map " ) ) & & str_length ( aReason ) = = 1 & & aReason [ 0 ] > = ' 0 ' & & aReason [ 0 ] < = ' 5 ' )
2014-10-10 22:41:56 +00:00
{
2018-07-25 08:29:05 +00:00
int Stars = aReason [ 0 ] - ' 0 ' ;
str_format ( aCmd , sizeof ( aCmd ) , " %s %d " , pOption - > m_aCommand , Stars ) ;
2014-10-10 22:41:56 +00:00
}
else
{
str_format ( aCmd , sizeof ( aCmd ) , " %s " , pOption - > m_aCommand ) ;
}
2017-05-17 16:50:01 +00:00
m_LastMapVote = time_get ( ) ;
2013-03-23 14:59:27 +00:00
break ;
}
2011-04-13 18:37:12 +00:00
2013-03-23 14:59:27 +00:00
pOption = pOption - > m_pNext ;
}
2011-03-25 09:26:59 +00:00
2013-03-23 14:59:27 +00:00
if ( ! pOption )
2010-05-29 07:25:38 +00:00
{
2020-09-26 19:41:58 +00:00
if ( Authed ! = AUTHED_ADMIN ) // allow admins to call any vote they want
2011-01-21 13:40:39 +00:00
{
2013-12-26 17:02:22 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' isn't an option on this server " , pMsg - > m_Value ) ;
SendChatTarget ( ClientID , aChatmsg ) ;
2011-01-21 13:40:39 +00:00
return ;
}
2013-12-26 17:02:22 +00:00
else
2011-04-09 06:41:31 +00:00
{
2013-12-26 17:02:22 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' called vote to change server option '%s' " , Server ( ) - > ClientName ( ClientID ) , pMsg - > m_Value ) ;
str_format ( aDesc , sizeof ( aDesc ) , " %s " , pMsg - > m_Value ) ;
str_format ( aCmd , sizeof ( aCmd ) , " %s " , pMsg - > m_Value ) ;
}
2011-03-04 16:35:50 +00:00
}
2010-08-20 20:40:12 +00:00
2020-07-01 12:02:47 +00:00
m_VoteType = VOTE_TYPE_OPTION ;
2011-03-04 16:35:50 +00:00
}
2013-03-23 14:59:27 +00:00
else if ( str_comp_nocase ( pMsg - > m_Type , " kick " ) = = 0 )
2010-05-29 07:25:38 +00:00
{
2018-01-27 22:13:17 +00:00
int Authed = Server ( ) - > GetAuthedState ( ClientID ) ;
if ( ! Authed & & time_get ( ) < m_apPlayers [ ClientID ] - > m_Last_KickVote + ( time_freq ( ) * 5 ) )
2013-12-26 17:02:22 +00:00
return ;
2018-01-27 22:13:17 +00:00
else if ( ! Authed & & time_get ( ) < m_apPlayers [ ClientID ] - > m_Last_KickVote + ( time_freq ( ) * g_Config . m_SvVoteKickDelay ) )
2013-12-26 17:02:22 +00:00
{
2017-07-26 01:58:00 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " There's a %d second wait time between kick votes for each player please wait %d second(s) " ,
2020-09-26 19:41:58 +00:00
g_Config . m_SvVoteKickDelay ,
( int ) ( ( ( m_apPlayers [ ClientID ] - > m_Last_KickVote + ( m_apPlayers [ ClientID ] - > m_Last_KickVote * time_freq ( ) ) ) / time_freq ( ) ) - ( time_get ( ) / time_freq ( ) ) ) ) ;
2017-07-26 01:58:00 +00:00
SendChatTarget ( ClientID , aChatmsg ) ;
2013-12-26 17:02:22 +00:00
m_apPlayers [ ClientID ] - > m_Last_KickVote = time_get ( ) ;
return ;
}
//else if(!g_Config.m_SvVoteKick)
2018-01-27 22:13:17 +00:00
else if ( ! g_Config . m_SvVoteKick & & ! Authed ) // allow admins to call kick votes even if they are forbidden
2013-03-23 14:59:27 +00:00
{
SendChatTarget ( ClientID , " Server does not allow voting to kick players " ) ;
2013-12-26 17:02:22 +00:00
m_apPlayers [ ClientID ] - > m_Last_KickVote = time_get ( ) ;
2013-03-23 14:59:27 +00:00
return ;
}
2019-02-08 17:44:11 +00:00
if ( g_Config . m_SvVoteKickMin & & ! GetDDRaceTeam ( ClientID ) )
2013-03-23 14:59:27 +00:00
{
2018-03-18 19:53:05 +00:00
char aaAddresses [ MAX_CLIENTS ] [ NETADDR_MAXSTRSIZE ] = { { 0 } } ;
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_apPlayers [ i ] )
{
Server ( ) - > GetClientAddr ( i , aaAddresses [ i ] , NETADDR_MAXSTRSIZE ) ;
}
}
int NumPlayers = 0 ;
2013-03-23 14:59:27 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
2018-03-18 19:53:05 +00:00
{
2019-02-08 17:44:11 +00:00
if ( m_apPlayers [ i ] & & m_apPlayers [ i ] - > GetTeam ( ) ! = TEAM_SPECTATORS & & ! GetDDRaceTeam ( i ) )
2018-03-18 19:53:05 +00:00
{
NumPlayers + + ;
for ( int j = 0 ; j < i ; j + + )
{
2019-02-08 17:44:11 +00:00
if ( m_apPlayers [ j ] & & m_apPlayers [ j ] - > GetTeam ( ) ! = TEAM_SPECTATORS & & ! GetDDRaceTeam ( j ) )
2018-03-18 19:53:05 +00:00
{
if ( str_comp ( aaAddresses [ i ] , aaAddresses [ j ] ) = = 0 )
{
NumPlayers - - ;
break ;
}
}
}
}
}
2013-03-23 14:59:27 +00:00
2018-03-18 19:53:05 +00:00
if ( NumPlayers < g_Config . m_SvVoteKickMin )
2013-03-23 14:59:27 +00:00
{
2019-02-08 17:44:11 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " Kick voting requires %d players " , g_Config . m_SvVoteKickMin ) ;
2013-03-23 14:59:27 +00:00
SendChatTarget ( ClientID , aChatmsg ) ;
2011-04-09 06:41:31 +00:00
return ;
}
2010-05-29 07:25:38 +00:00
}
2013-03-23 14:59:27 +00:00
int KickID = str_toint ( pMsg - > m_Value ) ;
2013-12-31 17:25:40 +00:00
2013-03-23 14:59:27 +00:00
if ( KickID < 0 | | KickID > = MAX_CLIENTS | | ! m_apPlayers [ KickID ] )
{
SendChatTarget ( ClientID , " Invalid client id to kick " ) ;
return ;
}
if ( KickID = = ClientID )
{
SendChatTarget ( ClientID , " You can't kick yourself " ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( ! Server ( ) - > ReverseTranslate ( KickID , ClientID ) )
2015-08-12 13:54:03 +00:00
{
return ;
}
2018-01-27 22:13:17 +00:00
int KickedAuthed = Server ( ) - > GetAuthedState ( KickID ) ;
2019-02-08 15:57:39 +00:00
if ( KickedAuthed > Authed )
2013-03-23 14:59:27 +00:00
{
2018-04-07 14:51:17 +00:00
SendChatTarget ( ClientID , " You can't kick authorized players " ) ;
2013-12-26 17:02:22 +00:00
m_apPlayers [ ClientID ] - > m_Last_KickVote = time_get ( ) ;
2013-03-23 14:59:27 +00:00
char aBufKick [ 128 ] ;
str_format ( aBufKick , sizeof ( aBufKick ) , " '%s' called for vote to kick you " , Server ( ) - > ClientName ( ClientID ) ) ;
SendChatTarget ( KickID , aBufKick ) ;
return ;
}
2011-04-13 18:37:12 +00:00
2013-12-26 17:02:22 +00:00
// Don't allow kicking if a player has no character
if ( ! GetPlayerChar ( ClientID ) | | ! GetPlayerChar ( KickID ) | | GetDDRaceTeam ( ClientID ) ! = GetDDRaceTeam ( KickID ) )
2010-10-11 09:18:44 +00:00
{
2013-12-26 17:02:22 +00:00
SendChatTarget ( ClientID , " You can kick only your team member " ) ;
m_apPlayers [ ClientID ] - > m_Last_KickVote = time_get ( ) ;
2010-10-11 09:18:44 +00:00
return ;
}
2013-12-26 17:02:22 +00:00
2016-01-19 13:59:16 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' called for vote to kick '%s' (%s) " , Server ( ) - > ClientName ( ClientID ) , Server ( ) - > ClientName ( KickID ) , aReason ) ;
2020-08-04 17:14:37 +00:00
str_format ( aSixupDesc , sizeof ( aSixupDesc ) , " %2d: %s " , KickID , Server ( ) - > ClientName ( KickID ) ) ;
2017-04-25 17:10:22 +00:00
if ( ! GetDDRaceTeam ( ClientID ) )
{
2020-09-26 19:41:58 +00:00
if ( ! g_Config . m_SvVoteKickBantime )
2019-03-01 21:11:00 +00:00
{
2017-04-25 17:10:22 +00:00
str_format ( aCmd , sizeof ( aCmd ) , " kick %d Kicked by vote " , KickID ) ;
2019-03-01 21:11:00 +00:00
str_format ( aDesc , sizeof ( aDesc ) , " Kick '%s' " , Server ( ) - > ClientName ( KickID ) ) ;
}
2017-04-25 17:10:22 +00:00
else
{
char aAddrStr [ NETADDR_MAXSTRSIZE ] = { 0 } ;
Server ( ) - > GetClientAddr ( KickID , aAddrStr , sizeof ( aAddrStr ) ) ;
str_format ( aCmd , sizeof ( aCmd ) , " ban %s %d Banned by vote " , aAddrStr , g_Config . m_SvVoteKickBantime ) ;
2019-03-01 21:11:00 +00:00
str_format ( aDesc , sizeof ( aDesc ) , " Ban '%s' " , Server ( ) - > ClientName ( KickID ) ) ;
2017-04-25 17:10:22 +00:00
}
}
2010-10-11 09:18:44 +00:00
else
{
2019-03-01 21:11:00 +00:00
str_format ( aCmd , sizeof ( aCmd ) , " uninvite %d %d; set_team_ddr %d 0 " , KickID , GetDDRaceTeam ( KickID ) , KickID ) ;
str_format ( aDesc , sizeof ( aDesc ) , " Move '%s' to team 0 " , Server ( ) - > ClientName ( KickID ) ) ;
2010-10-11 09:18:44 +00:00
}
2011-02-13 05:35:13 +00:00
m_apPlayers [ ClientID ] - > m_Last_KickVote = time_get ( ) ;
2020-07-01 12:02:47 +00:00
m_VoteType = VOTE_TYPE_KICK ;
2018-03-01 18:46:04 +00:00
m_VoteVictim = KickID ;
2010-07-29 19:55:33 +00:00
}
2013-03-23 14:59:27 +00:00
else if ( str_comp_nocase ( pMsg - > m_Type , " spectate " ) = = 0 )
2008-10-21 17:26:32 +00:00
{
2013-03-23 14:59:27 +00:00
if ( ! g_Config . m_SvVoteSpectate )
{
SendChatTarget ( ClientID , " Server does not allow voting to move players to spectators " ) ;
return ;
}
2011-03-04 16:35:50 +00:00
2013-03-23 14:59:27 +00:00
int SpectateID = str_toint ( pMsg - > m_Value ) ;
2013-12-31 17:25:40 +00:00
2013-03-23 14:59:27 +00:00
if ( SpectateID < 0 | | SpectateID > = MAX_CLIENTS | | ! m_apPlayers [ SpectateID ] | | m_apPlayers [ SpectateID ] - > GetTeam ( ) = = TEAM_SPECTATORS )
{
SendChatTarget ( ClientID , " Invalid client id to move " ) ;
return ;
}
if ( SpectateID = = ClientID )
{
SendChatTarget ( ClientID , " You can't move yourself " ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( ! Server ( ) - > ReverseTranslate ( SpectateID , ClientID ) )
2015-08-12 13:54:03 +00:00
{
return ;
}
2011-03-04 16:35:50 +00:00
2013-12-26 17:02:22 +00:00
if ( ! GetPlayerChar ( ClientID ) | | ! GetPlayerChar ( SpectateID ) | | GetDDRaceTeam ( ClientID ) ! = GetDDRaceTeam ( SpectateID ) )
2011-03-04 16:35:50 +00:00
{
2021-01-06 17:16:30 +00:00
SendChatTarget ( ClientID , " You can only move your team member to spectators " ) ;
2011-03-04 16:35:50 +00:00
return ;
}
2011-04-13 18:37:12 +00:00
2020-08-04 17:14:37 +00:00
str_format ( aSixupDesc , sizeof ( aSixupDesc ) , " %2d: %s " , SpectateID , Server ( ) - > ClientName ( SpectateID ) ) ;
2013-12-26 17:02:22 +00:00
if ( g_Config . m_SvPauseable & & g_Config . m_SvVotePause )
{
2016-01-19 13:59:16 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' called for vote to pause '%s' for %d seconds (%s) " , Server ( ) - > ClientName ( ClientID ) , Server ( ) - > ClientName ( SpectateID ) , g_Config . m_SvVotePauseTime , aReason ) ;
2013-12-26 17:02:22 +00:00
str_format ( aDesc , sizeof ( aDesc ) , " Pause '%s' (%ds) " , Server ( ) - > ClientName ( SpectateID ) , g_Config . m_SvVotePauseTime ) ;
2019-03-01 21:11:00 +00:00
str_format ( aCmd , sizeof ( aCmd ) , " uninvite %d %d; force_pause %d %d " , SpectateID , GetDDRaceTeam ( SpectateID ) , SpectateID , g_Config . m_SvVotePauseTime ) ;
2013-12-26 17:02:22 +00:00
}
else
{
2016-01-19 13:59:16 +00:00
str_format ( aChatmsg , sizeof ( aChatmsg ) , " '%s' called for vote to move '%s' to spectators (%s) " , Server ( ) - > ClientName ( ClientID ) , Server ( ) - > ClientName ( SpectateID ) , aReason ) ;
2019-03-01 21:11:00 +00:00
str_format ( aDesc , sizeof ( aDesc ) , " Move '%s' to spectators " , Server ( ) - > ClientName ( SpectateID ) ) ;
str_format ( aCmd , sizeof ( aCmd ) , " uninvite %d %d; set_team %d -1 %d " , SpectateID , GetDDRaceTeam ( SpectateID ) , SpectateID , g_Config . m_SvVoteSpectateRejoindelay ) ;
2013-12-26 17:02:22 +00:00
}
2020-07-01 12:02:47 +00:00
m_VoteType = VOTE_TYPE_SPECTATE ;
2018-03-01 18:46:04 +00:00
m_VoteVictim = SpectateID ;
2010-05-29 07:25:38 +00:00
}
2013-03-23 14:59:27 +00:00
2022-03-22 22:39:58 +00:00
if ( aCmd [ 0 ] & & str_comp_nocase ( aCmd , " info " ) ! = 0 )
2020-08-27 16:47:21 +00:00
CallVote ( ClientID , aDesc , aCmd , aReason , aChatmsg , aSixupDesc [ 0 ] ? aSixupDesc : 0 ) ;
2013-03-23 14:59:27 +00:00
}
else if ( MsgID = = NETMSGTYPE_CL_VOTE )
{
if ( ! m_VoteCloseTime )
2010-06-02 02:42:17 +00:00
return ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastVoteTry & & pPlayer - > m_LastVoteTry + Server ( ) - > TickSpeed ( ) * 3 > Server ( ) - > Tick ( ) )
2014-05-19 00:17:18 +00:00
return ;
2011-04-09 06:41:31 +00:00
2021-06-23 05:05:49 +00:00
int64_t Now = Server ( ) - > Tick ( ) ;
2014-05-19 00:17:18 +00:00
pPlayer - > m_LastVoteTry = Now ;
2020-10-07 21:24:48 +00:00
pPlayer - > UpdatePlaytime ( ) ;
2014-05-19 00:17:18 +00:00
CNetMsg_Cl_Vote * pMsg = ( CNetMsg_Cl_Vote * ) pRawMsg ;
if ( ! pMsg - > m_Vote )
return ;
pPlayer - > m_Vote = pMsg - > m_Vote ;
pPlayer - > m_VotePos = + + m_VotePos ;
m_VoteUpdate = true ;
2010-05-29 07:25:38 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_SETTEAM & & ! m_World . m_Paused )
2011-03-26 15:56:59 +00:00
{
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_SetTeam * pMsg = ( CNetMsg_Cl_SetTeam * ) pRawMsg ;
2011-04-13 18:37:12 +00:00
2013-12-26 17:02:22 +00:00
if ( pPlayer - > GetTeam ( ) = = pMsg - > m_Team | | ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastSetTeam & & pPlayer - > m_LastSetTeam + Server ( ) - > TickSpeed ( ) * g_Config . m_SvTeamChangeDelay > Server ( ) - > Tick ( ) ) )
2011-03-26 15:56:59 +00:00
return ;
2011-04-13 18:37:12 +00:00
2014-09-22 14:12:01 +00:00
//Kill Protection
2017-03-21 10:24:44 +00:00
CCharacter * pChr = pPlayer - > GetCharacter ( ) ;
2014-09-22 16:57:56 +00:00
if ( pChr )
{
2014-09-22 14:12:01 +00:00
int CurrTime = ( Server ( ) - > Tick ( ) - pChr - > m_StartTime ) / Server ( ) - > TickSpeed ( ) ;
if ( g_Config . m_SvKillProtection ! = 0 & & CurrTime > = ( 60 * g_Config . m_SvKillProtection ) & & pChr - > m_DDRaceState = = DDRACE_STARTED )
{
2014-09-22 16:57:56 +00:00
SendChatTarget ( ClientID , " Kill Protection enabled. If you really want to join the spectators, first type /kill " ) ;
2014-09-22 14:12:01 +00:00
return ;
}
}
2013-03-23 14:59:27 +00:00
if ( pPlayer - > m_TeamChangeTick > Server ( ) - > Tick ( ) )
2013-07-11 00:54:54 +00:00
{
2013-03-23 14:59:27 +00:00
pPlayer - > m_LastSetTeam = Server ( ) - > Tick ( ) ;
2020-09-26 19:41:58 +00:00
int TimeLeft = ( pPlayer - > m_TeamChangeTick - Server ( ) - > Tick ( ) ) / Server ( ) - > TickSpeed ( ) ;
2020-10-18 21:33:45 +00:00
char aTime [ 32 ] ;
2021-06-23 05:05:49 +00:00
str_time ( ( int64_t ) TimeLeft * 100 , TIME_HOURS , aTime , sizeof ( aTime ) ) ;
2013-03-23 14:59:27 +00:00
char aBuf [ 128 ] ;
2020-10-18 21:33:45 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Time to wait before changing team: %s " , aTime ) ;
2013-03-23 14:59:27 +00:00
SendBroadcast ( aBuf , ClientID ) ;
2013-07-11 00:54:54 +00:00
return ;
}
2013-03-23 14:59:27 +00:00
// Switch team on given client and kill/respawn him
if ( m_pController - > CanJoinTeam ( pMsg - > m_Team , ClientID ) )
2011-06-06 20:18:37 +00:00
{
2017-04-08 22:20:41 +00:00
if ( pPlayer - > IsPaused ( ) )
2020-09-26 19:41:58 +00:00
SendChatTarget ( ClientID , " Use /pause first then you can kill " ) ;
2013-12-26 17:02:22 +00:00
else
2013-03-23 14:59:27 +00:00
{
if ( pPlayer - > GetTeam ( ) = = TEAM_SPECTATORS | | pMsg - > m_Team = = TEAM_SPECTATORS )
m_VoteUpdate = true ;
2021-01-12 20:01:00 +00:00
m_pController - > DoTeamChange ( pPlayer , pMsg - > m_Team ) ;
2013-03-23 14:59:27 +00:00
pPlayer - > m_TeamChangeTick = Server ( ) - > Tick ( ) ;
}
2011-06-06 20:18:37 +00:00
}
else
{
2013-03-23 14:59:27 +00:00
char aBuf [ 128 ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Only %d active players are allowed " , Server ( ) - > MaxClients ( ) - g_Config . m_SvSpectatorSlots ) ;
2013-03-23 14:59:27 +00:00
SendBroadcast ( aBuf , ClientID ) ;
2011-08-13 00:11:06 +00:00
}
2011-03-26 15:56:59 +00:00
}
2021-01-10 16:41:06 +00:00
else if ( MsgID = = NETMSGTYPE_CL_ISDDNETLEGACY )
2010-05-29 07:25:38 +00:00
{
2020-05-22 15:58:41 +00:00
IServer : : CClientInfo Info ;
Server ( ) - > GetClientInfo ( ClientID , & Info ) ;
if ( Info . m_GotDDNetVersion )
2014-01-30 15:49:15 +00:00
{
2020-05-22 15:58:41 +00:00
return ;
2013-12-26 17:02:22 +00:00
}
2020-05-22 15:58:41 +00:00
int DDNetVersion = pUnpacker - > GetInt ( ) ;
if ( pUnpacker - > Error ( ) | | DDNetVersion < 0 )
2019-02-04 19:46:42 +00:00
{
2020-05-22 15:58:41 +00:00
DDNetVersion = VERSION_DDRACE ;
2019-02-04 19:46:42 +00:00
}
2020-05-22 15:58:41 +00:00
Server ( ) - > SetClientDDNetVersion ( ClientID , DDNetVersion ) ;
OnClientDDNetVersionKnown ( ClientID ) ;
2014-01-02 01:13:10 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_SHOWOTHERSLEGACY )
2010-05-29 07:25:38 +00:00
{
2013-12-26 17:02:22 +00:00
if ( g_Config . m_SvShowOthers & & ! g_Config . m_SvShowOthersDefault )
2011-01-29 00:59:50 +00:00
{
2020-06-29 15:47:26 +00:00
CNetMsg_Cl_ShowOthersLegacy * pMsg = ( CNetMsg_Cl_ShowOthersLegacy * ) pRawMsg ;
pPlayer - > m_ShowOthers = pMsg - > m_Show ;
2011-01-29 00:59:50 +00:00
}
2010-05-29 07:25:38 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_SHOWOTHERS )
2020-06-28 08:09:25 +00:00
{
if ( g_Config . m_SvShowOthers & & ! g_Config . m_SvShowOthersDefault )
{
2020-06-29 15:47:26 +00:00
CNetMsg_Cl_ShowOthers * pMsg = ( CNetMsg_Cl_ShowOthers * ) pRawMsg ;
2020-06-28 08:09:25 +00:00
pPlayer - > m_ShowOthers = pMsg - > m_Show ;
}
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_SHOWDISTANCE )
2020-06-28 09:48:25 +00:00
{
CNetMsg_Cl_ShowDistance * pMsg = ( CNetMsg_Cl_ShowDistance * ) pRawMsg ;
pPlayer - > m_ShowDistance = vec2 ( pMsg - > m_X , pMsg - > m_Y ) ;
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_SETSPECTATORMODE & & ! m_World . m_Paused )
2010-05-29 07:25:38 +00:00
{
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_SetSpectatorMode * pMsg = ( CNetMsg_Cl_SetSpectatorMode * ) pRawMsg ;
2011-04-09 06:41:31 +00:00
2020-09-26 19:41:58 +00:00
pMsg - > m_SpectatorID = clamp ( pMsg - > m_SpectatorID , ( int ) SPEC_FOLLOW , MAX_CLIENTS - 1 ) ;
2018-12-11 08:23:12 +00:00
if ( pMsg - > m_SpectatorID > = 0 )
2020-09-26 19:41:58 +00:00
if ( ! Server ( ) - > ReverseTranslate ( pMsg - > m_SpectatorID , ClientID ) )
2013-12-31 17:25:40 +00:00
return ;
2020-09-26 19:41:58 +00:00
if ( ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastSetSpectatorMode & & pPlayer - > m_LastSetSpectatorMode + Server ( ) - > TickSpeed ( ) / 4 > Server ( ) - > Tick ( ) ) )
2010-05-29 07:25:38 +00:00
return ;
2011-04-09 06:41:31 +00:00
2013-03-23 14:59:27 +00:00
pPlayer - > m_LastSetSpectatorMode = Server ( ) - > Tick ( ) ;
2020-10-07 21:24:48 +00:00
pPlayer - > UpdatePlaytime ( ) ;
2018-12-11 08:23:12 +00:00
if ( pMsg - > m_SpectatorID > = 0 & & ( ! m_apPlayers [ pMsg - > m_SpectatorID ] | | m_apPlayers [ pMsg - > m_SpectatorID ] - > GetTeam ( ) = = TEAM_SPECTATORS ) )
2013-03-23 14:59:27 +00:00
SendChatTarget ( ClientID , " Invalid spectator id used " ) ;
else
pPlayer - > m_SpectatorID = pMsg - > m_SpectatorID ;
2008-09-25 12:23:44 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_CHANGEINFO )
2012-01-08 12:55:20 +00:00
{
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastChangeInfo & & pPlayer - > m_LastChangeInfo + Server ( ) - > TickSpeed ( ) * g_Config . m_SvInfoChangeDelay > Server ( ) - > Tick ( ) )
2013-03-23 14:59:27 +00:00
return ;
2011-04-09 06:41:31 +00:00
2020-06-24 15:14:15 +00:00
bool SixupNeedsUpdate = false ;
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_ChangeInfo * pMsg = ( CNetMsg_Cl_ChangeInfo * ) pRawMsg ;
2020-09-26 19:41:58 +00:00
if ( ! str_utf8_check ( pMsg - > m_pName ) | | ! str_utf8_check ( pMsg - > m_pClan ) | | ! str_utf8_check ( pMsg - > m_pSkin ) )
2016-01-27 00:24:02 +00:00
{
return ;
}
2013-03-23 14:59:27 +00:00
pPlayer - > m_LastChangeInfo = Server ( ) - > Tick ( ) ;
2020-10-07 21:24:48 +00:00
pPlayer - > UpdatePlaytime ( ) ;
2011-04-09 06:41:31 +00:00
2013-03-23 14:59:27 +00:00
// set infos
2020-10-14 14:42:35 +00:00
if ( Server ( ) - > WouldClientNameChange ( ClientID , pMsg - > m_pName ) & & ! ProcessSpamProtection ( ClientID ) )
2010-10-30 14:22:35 +00:00
{
2020-12-18 22:18:55 +00:00
char aOldName [ MAX_NAME_LENGTH ] ;
str_copy ( aOldName , Server ( ) - > ClientName ( ClientID ) , sizeof ( aOldName ) ) ;
2020-10-14 14:42:35 +00:00
Server ( ) - > SetClientName ( ClientID , pMsg - > m_pName ) ;
2013-12-26 17:02:22 +00:00
2013-03-23 14:59:27 +00:00
char aChatText [ 256 ] ;
str_format ( aChatText , sizeof ( aChatText ) , " '%s' changed name to '%s' " , aOldName , Server ( ) - > ClientName ( ClientID ) ) ;
SendChat ( - 1 , CGameContext : : CHAT_ALL , aChatText ) ;
2013-12-26 17:02:22 +00:00
// reload scores
Score ( ) - > PlayerData ( ClientID ) - > Reset ( ) ;
2020-06-04 15:33:10 +00:00
m_apPlayers [ ClientID ] - > m_Score = - 9999 ;
Score ( ) - > LoadPlayerData ( ClientID ) ;
2020-06-24 15:14:15 +00:00
SixupNeedsUpdate = true ;
2010-10-30 14:22:35 +00:00
}
2020-06-24 15:14:15 +00:00
if ( str_comp ( Server ( ) - > ClientClan ( ClientID ) , pMsg - > m_pClan ) )
SixupNeedsUpdate = true ;
2013-03-23 14:59:27 +00:00
Server ( ) - > SetClientClan ( ClientID , pMsg - > m_pClan ) ;
2020-06-24 15:14:15 +00:00
if ( Server ( ) - > ClientCountry ( ClientID ) ! = pMsg - > m_Country )
SixupNeedsUpdate = true ;
2013-03-23 14:59:27 +00:00
Server ( ) - > SetClientCountry ( ClientID , pMsg - > m_Country ) ;
2020-06-24 15:14:15 +00:00
2013-03-23 14:59:27 +00:00
str_copy ( pPlayer - > m_TeeInfos . m_SkinName , pMsg - > m_pSkin , sizeof ( pPlayer - > m_TeeInfos . m_SkinName ) ) ;
pPlayer - > m_TeeInfos . m_UseCustomColor = pMsg - > m_UseCustomColor ;
pPlayer - > m_TeeInfos . m_ColorBody = pMsg - > m_ColorBody ;
pPlayer - > m_TeeInfos . m_ColorFeet = pMsg - > m_ColorFeet ;
2020-06-18 15:10:05 +00:00
if ( ! Server ( ) - > IsSixup ( ClientID ) )
pPlayer - > m_TeeInfos . ToSixup ( ) ;
2019-11-03 00:07:10 +00:00
2020-06-24 15:14:15 +00:00
if ( SixupNeedsUpdate )
2020-06-14 17:32:14 +00:00
{
2020-06-24 15:14:15 +00:00
protocol7 : : CNetMsg_Sv_ClientDrop Drop ;
Drop . m_ClientID = ClientID ;
Drop . m_pReason = " " ;
Drop . m_Silent = true ;
protocol7 : : CNetMsg_Sv_ClientInfo Info ;
Info . m_ClientID = ClientID ;
Info . m_pName = Server ( ) - > ClientName ( ClientID ) ;
Info . m_Country = pMsg - > m_Country ;
Info . m_pClan = pMsg - > m_pClan ;
Info . m_Local = 0 ;
Info . m_Silent = true ;
Info . m_Team = pPlayer - > GetTeam ( ) ;
for ( int p = 0 ; p < 6 ; p + + )
{
Info . m_apSkinPartNames [ p ] = pPlayer - > m_TeeInfos . m_apSkinPartNames [ p ] ;
Info . m_aSkinPartColors [ p ] = pPlayer - > m_TeeInfos . m_aSkinPartColors [ p ] ;
Info . m_aUseCustomColors [ p ] = pPlayer - > m_TeeInfos . m_aUseCustomColors [ p ] ;
}
2022-02-21 15:33:51 +00:00
for ( int i = 0 ; i < Server ( ) - > MaxClients ( ) ; i + + )
2020-06-24 15:14:15 +00:00
{
if ( i ! = ClientID )
{
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Drop , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
Server ( ) - > SendPackMsg ( & Info , MSGFLAG_VITAL | MSGFLAG_NORECORD , i ) ;
2020-06-24 15:14:15 +00:00
}
}
}
else
{
protocol7 : : CNetMsg_Sv_SkinChange Msg ;
Msg . m_ClientID = ClientID ;
for ( int p = 0 ; p < 6 ; p + + )
{
Msg . m_apSkinPartNames [ p ] = pPlayer - > m_TeeInfos . m_apSkinPartNames [ p ] ;
Msg . m_aSkinPartColors [ p ] = pPlayer - > m_TeeInfos . m_aSkinPartColors [ p ] ;
Msg . m_aUseCustomColors [ p ] = pPlayer - > m_TeeInfos . m_aUseCustomColors [ p ] ;
}
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , - 1 ) ;
2020-06-14 17:32:14 +00:00
}
2019-11-03 00:07:10 +00:00
Server ( ) - > ExpireServerInfo ( ) ;
2010-10-30 14:22:35 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_EMOTICON & & ! m_World . m_Paused )
2013-02-02 13:08:02 +00:00
{
2013-03-23 14:59:27 +00:00
CNetMsg_Cl_Emoticon * pMsg = ( CNetMsg_Cl_Emoticon * ) pRawMsg ;
2011-04-13 18:37:12 +00:00
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastEmote & & pPlayer - > m_LastEmote + Server ( ) - > TickSpeed ( ) * g_Config . m_SvEmoticonDelay > Server ( ) - > Tick ( ) )
2013-03-23 14:59:27 +00:00
return ;
2010-05-29 07:25:38 +00:00
2013-03-23 14:59:27 +00:00
pPlayer - > m_LastEmote = Server ( ) - > Tick ( ) ;
2020-10-07 21:24:48 +00:00
pPlayer - > UpdatePlaytime ( ) ;
2011-03-15 08:58:57 +00:00
2013-03-23 14:59:27 +00:00
SendEmoticon ( ClientID , pMsg - > m_Emoticon ) ;
2017-03-21 10:24:44 +00:00
CCharacter * pChr = pPlayer - > GetCharacter ( ) ;
2021-01-12 19:11:42 +00:00
if ( pChr & & g_Config . m_SvEmotionalTees & & pPlayer - > m_EyeEmoteEnabled )
2010-05-29 07:25:38 +00:00
{
2021-01-12 18:44:12 +00:00
int EmoteType = EMOTE_NORMAL ;
2013-12-26 17:02:22 +00:00
switch ( pMsg - > m_Emoticon )
2011-03-26 21:06:29 +00:00
{
2013-12-26 17:02:22 +00:00
case EMOTICON_EXCLAMATION :
case EMOTICON_GHOST :
case EMOTICON_QUESTION :
case EMOTICON_WTF :
2021-01-12 18:44:12 +00:00
EmoteType = EMOTE_SURPRISE ;
2020-09-26 19:41:58 +00:00
break ;
2013-12-26 17:02:22 +00:00
case EMOTICON_DOTDOT :
case EMOTICON_DROP :
case EMOTICON_ZZZ :
2021-01-12 18:44:12 +00:00
EmoteType = EMOTE_BLINK ;
2020-09-26 19:41:58 +00:00
break ;
2013-12-26 17:02:22 +00:00
case EMOTICON_EYES :
case EMOTICON_HEARTS :
case EMOTICON_MUSIC :
2021-01-12 18:44:12 +00:00
EmoteType = EMOTE_HAPPY ;
2020-09-26 19:41:58 +00:00
break ;
2013-12-26 17:02:22 +00:00
case EMOTICON_OOP :
case EMOTICON_SORRY :
case EMOTICON_SUSHI :
2021-01-12 18:44:12 +00:00
EmoteType = EMOTE_PAIN ;
2020-09-26 19:41:58 +00:00
break ;
2013-12-26 17:02:22 +00:00
case EMOTICON_DEVILTEE :
case EMOTICON_SPLATTEE :
case EMOTICON_ZOMG :
2021-01-12 18:44:12 +00:00
EmoteType = EMOTE_ANGRY ;
2020-09-26 19:41:58 +00:00
break ;
default :
break ;
2011-03-26 21:06:29 +00:00
}
2021-01-12 18:44:12 +00:00
pChr - > SetEmote ( EmoteType , Server ( ) - > Tick ( ) + 2 * Server ( ) - > TickSpeed ( ) ) ;
2010-05-29 07:25:38 +00:00
}
2011-03-26 21:06:29 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( MsgID = = NETMSGTYPE_CL_KILL & & ! m_World . m_Paused )
2010-05-29 07:25:38 +00:00
{
2020-07-01 12:02:47 +00:00
if ( m_VoteCloseTime & & m_VoteCreator = = ClientID & & GetDDRaceTeam ( ClientID ) & & ( IsKickVote ( ) | | IsSpecVote ( ) ) )
2013-12-26 17:02:22 +00:00
{
SendChatTarget ( ClientID , " You are running a vote please try again after the vote is done! " ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( pPlayer - > m_LastKill & & pPlayer - > m_LastKill + Server ( ) - > TickSpeed ( ) * g_Config . m_SvKillDelay > Server ( ) - > Tick ( ) )
2013-12-26 17:02:22 +00:00
return ;
2017-04-08 22:20:41 +00:00
if ( pPlayer - > IsPaused ( ) )
2013-03-23 14:59:27 +00:00
return ;
2011-06-07 15:05:07 +00:00
2017-03-21 10:24:44 +00:00
CCharacter * pChr = pPlayer - > GetCharacter ( ) ;
2014-08-25 09:35:55 +00:00
if ( ! pChr )
return ;
2014-08-24 21:24:33 +00:00
//Kill Protection
2014-08-25 09:35:55 +00:00
int CurrTime = ( Server ( ) - > Tick ( ) - pChr - > m_StartTime ) / Server ( ) - > TickSpeed ( ) ;
if ( g_Config . m_SvKillProtection ! = 0 & & CurrTime > = ( 60 * g_Config . m_SvKillProtection ) & & pChr - > m_DDRaceState = = DDRACE_STARTED )
2014-08-24 21:24:33 +00:00
{
2014-09-22 14:12:01 +00:00
SendChatTarget ( ClientID , " Kill Protection enabled. If you really want to kill, type /kill " ) ;
2014-08-24 21:24:33 +00:00
return ;
}
2013-03-23 14:59:27 +00:00
pPlayer - > m_LastKill = Server ( ) - > Tick ( ) ;
pPlayer - > KillCharacter ( WEAPON_SELF ) ;
2016-02-02 20:14:46 +00:00
pPlayer - > Respawn ( ) ;
2010-05-29 07:25:38 +00:00
}
}
2020-09-26 19:41:58 +00:00
if ( MsgID = = NETMSGTYPE_CL_STARTINFO )
2010-05-29 07:25:38 +00:00
{
2015-06-18 15:47:07 +00:00
if ( pPlayer - > m_IsReady )
2015-05-19 15:47:41 +00:00
return ;
2014-08-09 12:50:51 +00:00
2020-04-16 08:46:43 +00:00
CNetMsg_Cl_StartInfo * pMsg = ( CNetMsg_Cl_StartInfo * ) pRawMsg ;
2020-03-29 02:36:38 +00:00
2020-09-03 18:34:05 +00:00
if ( ! str_utf8_check ( pMsg - > m_pName ) )
2016-01-27 00:24:02 +00:00
{
2020-09-03 18:34:05 +00:00
Server ( ) - > Kick ( ClientID , " name is not valid utf8 " ) ;
2016-01-27 00:24:02 +00:00
return ;
}
2020-09-03 18:34:05 +00:00
if ( ! str_utf8_check ( pMsg - > m_pClan ) )
{
Server ( ) - > Kick ( ClientID , " clan is not valid utf8 " ) ;
return ;
}
if ( ! str_utf8_check ( pMsg - > m_pSkin ) )
{
Server ( ) - > Kick ( ClientID , " skin is not valid utf8 " ) ;
return ;
}
2014-08-09 12:50:51 +00:00
pPlayer - > m_LastChangeInfo = Server ( ) - > Tick ( ) ;
// set start infos
Server ( ) - > SetClientName ( ClientID , pMsg - > m_pName ) ;
2021-11-02 22:59:09 +00:00
// trying to set client name can delete the player object, check if it still exists
if ( ! m_apPlayers [ ClientID ] )
{
return ;
}
2014-08-09 12:50:51 +00:00
Server ( ) - > SetClientClan ( ClientID , pMsg - > m_pClan ) ;
Server ( ) - > SetClientCountry ( ClientID , pMsg - > m_Country ) ;
str_copy ( pPlayer - > m_TeeInfos . m_SkinName , pMsg - > m_pSkin , sizeof ( pPlayer - > m_TeeInfos . m_SkinName ) ) ;
pPlayer - > m_TeeInfos . m_UseCustomColor = pMsg - > m_UseCustomColor ;
pPlayer - > m_TeeInfos . m_ColorBody = pMsg - > m_ColorBody ;
pPlayer - > m_TeeInfos . m_ColorFeet = pMsg - > m_ColorFeet ;
2020-06-18 15:10:05 +00:00
if ( ! Server ( ) - > IsSixup ( ClientID ) )
pPlayer - > m_TeeInfos . ToSixup ( ) ;
2014-08-09 12:50:51 +00:00
2014-10-26 18:39:42 +00:00
// send clear vote options
2014-08-09 12:50:51 +00:00
CNetMsg_Sv_VoteClearOptions ClearMsg ;
Server ( ) - > SendPackMsg ( & ClearMsg , MSGFLAG_VITAL , ClientID ) ;
2014-10-26 18:39:42 +00:00
// begin sending vote options
pPlayer - > m_SendVoteIndex = 0 ;
2011-04-13 18:37:12 +00:00
2014-08-09 12:50:51 +00:00
// send tuning parameters to client
SendTuningParams ( ClientID , pPlayer - > m_TuneZone ) ;
2011-04-13 18:37:12 +00:00
2014-08-09 12:50:51 +00:00
// client is ready to enter
2020-12-19 09:20:18 +00:00
pPlayer - > m_IsReady = true ;
CNetMsg_Sv_ReadyToEnter m ;
Server ( ) - > SendPackMsg ( & m , MSGFLAG_VITAL | MSGFLAG_FLUSH , ClientID ) ;
2019-11-03 00:07:10 +00:00
Server ( ) - > ExpireServerInfo ( ) ;
2010-05-29 07:25:38 +00:00
}
}
2011-01-29 00:59:50 +00:00
2011-08-13 00:11:06 +00:00
void CGameContext : : ConTuneParam ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
const char * pParamName = pResult - > GetString ( 0 ) ;
float NewValue = pResult - > GetFloat ( 1 ) ;
if ( pSelf - > Tuning ( ) - > Set ( pParamName , NewValue ) )
{
2010-09-12 11:06:43 +00:00
char aBuf [ 256 ] ;
2010-08-17 22:06:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %s changed to %.2f " , pParamName , NewValue ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
2010-05-29 07:25:38 +00:00
pSelf - > SendTuningParams ( - 1 ) ;
}
else
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " No such tuning parameter " ) ;
2010-05-29 07:25:38 +00:00
}
2018-12-20 08:18:22 +00:00
void CGameContext : : ConToggleTuneParam ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
const char * pParamName = pResult - > GetString ( 0 ) ;
float OldValue ;
if ( ! pSelf - > Tuning ( ) - > Get ( pParamName , & OldValue ) )
{
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " No such tuning parameter " ) ;
return ;
}
2020-09-26 19:41:58 +00:00
float NewValue = fabs ( OldValue - pResult - > GetFloat ( 1 ) ) < 0.0001f ? pResult - > GetFloat ( 2 ) : pResult - > GetFloat ( 1 ) ;
2018-12-20 08:18:22 +00:00
pSelf - > Tuning ( ) - > Set ( pParamName , NewValue ) ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " %s changed to %.2f " , pParamName , NewValue ) ;
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
pSelf - > SendTuningParams ( - 1 ) ;
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConTuneReset ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2011-08-13 00:11:06 +00:00
/*CTuningParams TuningParams;
* pSelf - > Tuning ( ) = TuningParams ;
pSelf - > SendTuningParams ( - 1 ) ;
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " Tuning reset " ) ; */
2011-05-30 20:05:28 +00:00
pSelf - > ResetTuning ( ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " Tuning reset " ) ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConTuneDump ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < pSelf - > Tuning ( ) - > Num ( ) ; i + + )
{
float v ;
pSelf - > Tuning ( ) - > Get ( i , & v ) ;
2017-03-21 10:24:44 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %s %.2f " , pSelf - > Tuning ( ) - > ms_apNames [ i ] , v ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
}
2014-03-12 23:31:50 +00:00
void CGameContext : : ConTuneZone ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
int List = pResult - > GetInteger ( 0 ) ;
const char * pParamName = pResult - > GetString ( 1 ) ;
float NewValue = pResult - > GetFloat ( 2 ) ;
2015-07-09 00:08:14 +00:00
2020-09-26 19:41:58 +00:00
if ( List > = 0 & & List < NUM_TUNEZONES )
2014-03-12 23:31:50 +00:00
{
2014-03-23 17:56:07 +00:00
if ( pSelf - > TuningList ( ) [ List ] . Set ( pParamName , NewValue ) )
2014-03-12 23:31:50 +00:00
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " %s in zone %d changed to %.2f " , pParamName , List , NewValue ) ;
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
2014-03-29 13:54:43 +00:00
pSelf - > SendTuningParams ( - 1 , List ) ;
2014-03-12 23:31:50 +00:00
}
else
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " No such tuning parameter " ) ;
}
}
void CGameContext : : ConTuneDumpZone ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
int List = pResult - > GetInteger ( 0 ) ;
char aBuf [ 256 ] ;
2020-09-26 19:41:58 +00:00
if ( List > = 0 & & List < NUM_TUNEZONES )
2014-03-12 23:31:50 +00:00
{
2014-03-23 17:56:07 +00:00
for ( int i = 0 ; i < pSelf - > TuningList ( ) [ List ] . Num ( ) ; i + + )
{
float v ;
pSelf - > TuningList ( ) [ List ] . Get ( i , & v ) ;
2017-03-21 10:24:44 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " zone %d: %s %.2f " , List , pSelf - > TuningList ( ) [ List ] . ms_apNames [ i ] , v ) ;
2014-03-23 17:56:07 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
}
2014-03-12 23:31:50 +00:00
}
}
void CGameContext : : ConTuneResetZone ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
CTuningParams TuningParams ;
2020-09-26 19:41:58 +00:00
if ( pResult - > NumArguments ( ) )
2014-03-12 23:31:50 +00:00
{
int List = pResult - > GetInteger ( 0 ) ;
2020-09-26 19:41:58 +00:00
if ( List > = 0 & & List < NUM_TUNEZONES )
2014-03-12 23:31:50 +00:00
{
2014-03-23 17:56:07 +00:00
pSelf - > TuningList ( ) [ List ] = TuningParams ;
2014-03-12 23:31:50 +00:00
char aBuf [ 256 ] ;
2018-07-10 09:29:02 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Tunezone %d reset " , List ) ;
2014-03-12 23:31:50 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , aBuf ) ;
2014-03-29 13:54:43 +00:00
pSelf - > SendTuningParams ( - 1 , List ) ;
2014-03-12 23:31:50 +00:00
}
}
else
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < NUM_TUNEZONES ; i + + )
2014-03-29 13:54:43 +00:00
{
2020-09-26 19:41:58 +00:00
* ( pSelf - > TuningList ( ) + i ) = TuningParams ;
2014-03-29 13:54:43 +00:00
pSelf - > SendTuningParams ( - 1 , i ) ;
}
2018-07-10 09:29:02 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " tuning " , " All Tunezones reset " ) ;
2014-03-12 23:31:50 +00:00
}
}
void CGameContext : : ConTuneSetZoneMsgEnter ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2020-09-26 19:41:58 +00:00
if ( pResult - > NumArguments ( ) )
2014-03-12 23:31:50 +00:00
{
int List = pResult - > GetInteger ( 0 ) ;
2020-09-26 19:41:58 +00:00
if ( List > = 0 & & List < NUM_TUNEZONES )
2014-03-12 23:31:50 +00:00
{
2017-07-26 01:58:00 +00:00
str_copy ( pSelf - > m_aaZoneEnterMsg [ List ] , pResult - > GetString ( 1 ) , sizeof ( pSelf - > m_aaZoneEnterMsg [ List ] ) ) ;
2014-03-12 23:31:50 +00:00
}
}
}
void CGameContext : : ConTuneSetZoneMsgLeave ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2020-09-26 19:41:58 +00:00
if ( pResult - > NumArguments ( ) )
2014-03-12 23:31:50 +00:00
{
int List = pResult - > GetInteger ( 0 ) ;
2020-09-26 19:41:58 +00:00
if ( List > = 0 & & List < NUM_TUNEZONES )
2014-03-12 23:31:50 +00:00
{
2017-07-26 01:58:00 +00:00
str_copy ( pSelf - > m_aaZoneLeaveMsg [ List ] , pResult - > GetString ( 1 ) , sizeof ( pSelf - > m_aaZoneLeaveMsg [ List ] ) ) ;
2014-03-12 23:31:50 +00:00
}
}
}
2018-05-01 10:38:33 +00:00
void CGameContext : : ConMapbug ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
const char * pMapBugName = pResult - > GetString ( 0 ) ;
if ( pSelf - > m_pController )
{
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " mapbugs " , " can't add map bugs after the game started " ) ;
return ;
}
switch ( pSelf - > m_MapBugs . Update ( pMapBugName ) )
{
case MAPBUGUPDATE_OK :
break ;
case MAPBUGUPDATE_OVERRIDDEN :
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " mapbugs " , " map-internal setting overridden by database " ) ;
break ;
case MAPBUGUPDATE_NOTFOUND :
2020-09-26 19:41:58 +00:00
{
char aBuf [ 64 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " unknown map bug '%s', ignoring " , pMapBugName ) ;
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " mapbugs " , aBuf ) ;
}
break ;
2018-05-01 10:38:33 +00:00
default :
dbg_assert ( 0 , " unreachable " ) ;
}
}
2015-07-22 21:31:50 +00:00
void CGameContext : : ConSwitchOpen ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
int Switch = pResult - > GetInteger ( 0 ) ;
2020-09-26 19:41:58 +00:00
if ( pSelf - > Collision ( ) - > m_NumSwitchers > 0 & & Switch > = 0 & & Switch < pSelf - > Collision ( ) - > m_NumSwitchers + 1 )
2015-07-22 21:31:50 +00:00
{
pSelf - > Collision ( ) - > m_pSwitchers [ Switch ] . m_Initial = false ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " switch %d opened by default " , Switch ) ;
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
}
}
2012-01-09 23:49:31 +00:00
void CGameContext : : ConPause ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
pSelf - > m_World . m_Paused ^ = 1 ;
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConChangeMap ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2010-11-17 11:50:01 +00:00
pSelf - > m_pController - > ChangeMap ( pResult - > NumArguments ( ) ? pResult - > GetString ( 0 ) : " " ) ;
2010-05-29 07:25:38 +00:00
}
2013-12-06 23:15:56 +00:00
void CGameContext : : ConRandomMap ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2014-10-10 22:41:56 +00:00
2019-08-27 16:33:37 +00:00
int Stars = pResult - > NumArguments ( ) ? pResult - > GetInteger ( 0 ) : - 1 ;
2013-12-06 23:15:56 +00:00
2020-05-26 21:22:16 +00:00
pSelf - > m_pScore - > RandomMap ( pSelf - > m_VoteCreator , Stars ) ;
2013-12-06 23:15:56 +00:00
}
2014-06-20 20:40:23 +00:00
void CGameContext : : ConRandomUnfinishedMap ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2014-10-10 22:41:56 +00:00
2019-08-27 16:33:37 +00:00
int Stars = pResult - > NumArguments ( ) ? pResult - > GetInteger ( 0 ) : - 1 ;
2014-10-10 22:41:56 +00:00
2020-05-28 13:29:14 +00:00
pSelf - > m_pScore - > RandomUnfinishedMap ( pSelf - > m_VoteCreator , Stars ) ;
2014-06-20 20:40:23 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConRestart ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
if ( pResult - > NumArguments ( ) )
pSelf - > m_pController - > DoWarmup ( pResult - > GetInteger ( 0 ) ) ;
else
pSelf - > m_pController - > StartRound ( ) ;
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConBroadcast ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2014-04-18 22:40:21 +00:00
char aBuf [ 1024 ] ;
str_copy ( aBuf , pResult - > GetString ( 0 ) , sizeof ( aBuf ) ) ;
int i , j ;
for ( i = 0 , j = 0 ; aBuf [ i ] ; i + + , j + + )
{
2020-09-26 19:41:58 +00:00
if ( aBuf [ i ] = = ' \\ ' & & aBuf [ i + 1 ] = = ' n ' )
2014-04-18 22:40:21 +00:00
{
aBuf [ j ] = ' \n ' ;
i + + ;
}
2020-09-26 19:41:58 +00:00
else if ( i ! = j )
2014-04-18 22:40:21 +00:00
{
aBuf [ j ] = aBuf [ i ] ;
}
}
aBuf [ j ] = ' \0 ' ;
pSelf - > SendBroadcast ( aBuf , - 1 ) ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConSay ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
pSelf - > SendChat ( - 1 , CGameContext : : CHAT_ALL , pResult - > GetString ( 0 ) ) ;
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConSetTeam ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2020-09-26 19:41:58 +00:00
int ClientID = clamp ( pResult - > GetInteger ( 0 ) , 0 , ( int ) MAX_CLIENTS - 1 ) ;
2010-05-29 07:25:38 +00:00
int Team = clamp ( pResult - > GetInteger ( 1 ) , - 1 , 1 ) ;
2020-09-26 19:41:58 +00:00
int Delay = pResult - > NumArguments ( ) > 2 ? pResult - > GetInteger ( 2 ) : 0 ;
2011-12-30 21:47:26 +00:00
if ( ! pSelf - > m_apPlayers [ ClientID ] )
return ;
2011-04-13 18:37:12 +00:00
2010-08-17 22:06:00 +00:00
char aBuf [ 256 ] ;
2011-02-12 10:40:36 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " moved client %d to team %d " , ClientID , Team ) ;
2010-08-17 22:06:00 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-11-21 22:25:30 +00:00
2018-07-09 22:08:57 +00:00
pSelf - > m_apPlayers [ ClientID ] - > Pause ( CPlayer : : PAUSE_NONE , false ) ; // reset /spec and /pause to allow rejoin
2020-09-26 19:41:58 +00:00
pSelf - > m_apPlayers [ ClientID ] - > m_TeamChangeTick = pSelf - > Server ( ) - > Tick ( ) + pSelf - > Server ( ) - > TickSpeed ( ) * Delay * 60 ;
2021-01-12 20:01:00 +00:00
pSelf - > m_pController - > DoTeamChange ( pSelf - > m_apPlayers [ ClientID ] , Team ) ;
2013-07-28 21:43:27 +00:00
if ( Team = = TEAM_SPECTATORS )
2017-04-08 23:16:48 +00:00
pSelf - > m_apPlayers [ ClientID ] - > Pause ( CPlayer : : PAUSE_NONE , true ) ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConSetTeamAll ( IConsole : : IResult * pResult , void * pUserData )
2011-01-06 12:37:28 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
int Team = clamp ( pResult - > GetInteger ( 0 ) , - 1 , 1 ) ;
2011-04-13 18:37:12 +00:00
2011-01-06 12:37:28 +00:00
char aBuf [ 256 ] ;
2011-12-30 21:30:28 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " All players were moved to the %s " , pSelf - > m_pController - > GetTeamName ( Team ) ) ;
pSelf - > SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf ) ;
2011-04-13 18:37:12 +00:00
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : pSelf - > m_apPlayers )
if ( pPlayer )
2021-01-12 20:01:00 +00:00
pSelf - > m_pController - > DoTeamChange ( pPlayer , Team , false ) ;
2011-09-04 09:13:30 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConAddVote ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2011-03-25 08:49:21 +00:00
const char * pDescription = pResult - > GetString ( 0 ) ;
const char * pCommand = pResult - > GetString ( 1 ) ;
2011-03-26 21:06:29 +00:00
2020-10-17 22:05:59 +00:00
pSelf - > AddVote ( pDescription , pCommand ) ;
}
void CGameContext : : AddVote ( const char * pDescription , const char * pCommand )
{
if ( m_NumVoteOptions = = MAX_VOTE_OPTIONS )
2011-03-26 21:06:29 +00:00
{
2020-10-17 22:05:59 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " maximum number of vote options reached " ) ;
2011-03-26 21:06:29 +00:00
return ;
}
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
// check for valid option
2020-10-17 22:05:59 +00:00
if ( ! Console ( ) - > LineIsValid ( pCommand ) | | str_length ( pCommand ) > = VOTE_CMD_LENGTH )
2010-10-25 16:30:35 +00:00
{
char aBuf [ 256 ] ;
2011-03-26 16:44:34 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " skipped invalid command '%s' " , pCommand ) ;
2020-10-17 22:05:59 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2011-03-26 16:44:34 +00:00
return ;
}
2020-11-05 10:47:07 +00:00
while ( * pDescription = = ' ' )
2011-04-05 18:06:41 +00:00
pDescription + + ;
if ( str_length ( pDescription ) > = VOTE_DESC_LENGTH | | * pDescription = = 0 )
2011-03-26 16:44:34 +00:00
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " skipped invalid option '%s' " , pDescription ) ;
2020-10-17 22:05:59 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-10-25 16:30:35 +00:00
return ;
}
2011-04-13 18:37:12 +00:00
2011-03-25 08:49:21 +00:00
// check for duplicate entry
2020-10-17 22:05:59 +00:00
CVoteOptionServer * pOption = m_pVoteOptionFirst ;
2010-11-20 18:30:52 +00:00
while ( pOption )
{
2011-03-25 10:49:35 +00:00
if ( str_comp_nocase ( pDescription , pOption - > m_aDescription ) = = 0 )
2010-11-20 18:30:52 +00:00
{
char aBuf [ 256 ] ;
2011-03-25 08:49:21 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " option '%s' already exists " , pDescription ) ;
2020-10-17 22:05:59 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2010-11-20 18:30:52 +00:00
return ;
}
pOption = pOption - > m_pNext ;
}
2011-04-13 18:37:12 +00:00
2011-03-25 08:49:21 +00:00
// add the option
2020-10-17 22:05:59 +00:00
+ + m_NumVoteOptions ;
2011-03-25 08:49:21 +00:00
int Len = str_length ( pCommand ) ;
2011-04-13 18:37:12 +00:00
2021-05-27 17:35:20 +00:00
pOption = ( CVoteOptionServer * ) m_pVoteOptionHeap - > Allocate ( sizeof ( CVoteOptionServer ) + Len , alignof ( CVoteOptionServer ) ) ;
2010-05-29 07:25:38 +00:00
pOption - > m_pNext = 0 ;
2020-10-17 22:05:59 +00:00
pOption - > m_pPrev = m_pVoteOptionLast ;
2010-05-29 07:25:38 +00:00
if ( pOption - > m_pPrev )
pOption - > m_pPrev - > m_pNext = pOption ;
2020-10-17 22:05:59 +00:00
m_pVoteOptionLast = pOption ;
if ( ! m_pVoteOptionFirst )
m_pVoteOptionFirst = pOption ;
2011-04-13 18:37:12 +00:00
2011-03-25 08:49:21 +00:00
str_copy ( pOption - > m_aDescription , pDescription , sizeof ( pOption - > m_aDescription ) ) ;
2020-09-26 19:41:58 +00:00
mem_copy ( pOption - > m_aCommand , pCommand , Len + 1 ) ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConRemoveVote ( IConsole : : IResult * pResult , void * pUserData )
2011-03-25 10:49:35 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
const char * pDescription = pResult - > GetString ( 0 ) ;
2011-04-13 18:37:12 +00:00
2011-03-25 10:49:35 +00:00
// check for valid option
2011-03-26 16:44:34 +00:00
CVoteOptionServer * pOption = pSelf - > m_pVoteOptionFirst ;
2011-03-25 10:49:35 +00:00
while ( pOption )
{
if ( str_comp_nocase ( pDescription , pOption - > m_aDescription ) = = 0 )
break ;
pOption = pOption - > m_pNext ;
}
if ( ! pOption )
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " option '%s' does not exist " , pDescription ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2011-03-25 10:49:35 +00:00
return ;
}
2011-04-04 14:58:53 +00:00
2014-10-27 12:34:29 +00:00
// start reloading vote option list
// clear vote options
CNetMsg_Sv_VoteClearOptions VoteClearOptionsMsg ;
pSelf - > Server ( ) - > SendPackMsg ( & VoteClearOptionsMsg , MSGFLAG_VITAL , - 1 ) ;
// reset sending of vote options
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : pSelf - > m_apPlayers )
2014-10-27 12:34:29 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
pPlayer - > m_SendVoteIndex = 0 ;
2014-10-27 12:34:29 +00:00
}
2011-04-13 18:37:12 +00:00
2011-03-25 10:49:35 +00:00
// TODO: improve this
// remove the option
2011-03-26 21:06:29 +00:00
- - pSelf - > m_NumVoteOptions ;
2011-03-25 10:49:35 +00:00
2011-03-25 11:06:45 +00:00
CHeap * pVoteOptionHeap = new CHeap ( ) ;
2011-03-26 16:44:34 +00:00
CVoteOptionServer * pVoteOptionFirst = 0 ;
CVoteOptionServer * pVoteOptionLast = 0 ;
2011-03-26 21:06:29 +00:00
int NumVoteOptions = pSelf - > m_NumVoteOptions ;
2011-03-26 16:44:34 +00:00
for ( CVoteOptionServer * pSrc = pSelf - > m_pVoteOptionFirst ; pSrc ; pSrc = pSrc - > m_pNext )
2011-03-25 10:49:35 +00:00
{
if ( pSrc = = pOption )
continue ;
// copy option
int Len = str_length ( pSrc - > m_aCommand ) ;
2011-03-26 16:44:34 +00:00
CVoteOptionServer * pDst = ( CVoteOptionServer * ) pVoteOptionHeap - > Allocate ( sizeof ( CVoteOptionServer ) + Len ) ;
2011-03-25 10:49:35 +00:00
pDst - > m_pNext = 0 ;
pDst - > m_pPrev = pVoteOptionLast ;
if ( pDst - > m_pPrev )
pDst - > m_pPrev - > m_pNext = pDst ;
pVoteOptionLast = pDst ;
if ( ! pVoteOptionFirst )
pVoteOptionFirst = pDst ;
2011-04-13 18:37:12 +00:00
2011-03-25 10:49:35 +00:00
str_copy ( pDst - > m_aDescription , pSrc - > m_aDescription , sizeof ( pDst - > m_aDescription ) ) ;
2020-09-26 19:41:58 +00:00
mem_copy ( pDst - > m_aCommand , pSrc - > m_aCommand , Len + 1 ) ;
2011-03-25 11:06:45 +00:00
}
// clean up
delete pSelf - > m_pVoteOptionHeap ;
2011-03-25 10:49:35 +00:00
pSelf - > m_pVoteOptionHeap = pVoteOptionHeap ;
pSelf - > m_pVoteOptionFirst = pVoteOptionFirst ;
pSelf - > m_pVoteOptionLast = pVoteOptionLast ;
2011-03-26 21:06:29 +00:00
pSelf - > m_NumVoteOptions = NumVoteOptions ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConForceVote ( IConsole : : IResult * pResult , void * pUserData )
2011-03-25 11:06:45 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
const char * pType = pResult - > GetString ( 0 ) ;
const char * pValue = pResult - > GetString ( 1 ) ;
2011-03-26 15:24:12 +00:00
const char * pReason = pResult - > NumArguments ( ) > 2 & & pResult - > GetString ( 2 ) [ 0 ] ? pResult - > GetString ( 2 ) : " No reason given " ;
2011-03-25 11:06:45 +00:00
char aBuf [ 128 ] = { 0 } ;
if ( str_comp_nocase ( pType , " option " ) = = 0 )
{
2011-03-26 16:44:34 +00:00
CVoteOptionServer * pOption = pSelf - > m_pVoteOptionFirst ;
2011-03-25 11:06:45 +00:00
while ( pOption )
{
if ( str_comp_nocase ( pValue , pOption - > m_aDescription ) = = 0 )
{
2020-11-25 01:50:10 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " authorized player forced server option '%s' (%s) " , pValue , pReason ) ;
2020-07-12 07:34:36 +00:00
pSelf - > SendChatTarget ( - 1 , aBuf , CHAT_SIX ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > ExecuteLine ( pOption - > m_aCommand ) ;
2011-03-25 11:06:45 +00:00
break ;
}
pOption = pOption - > m_pNext ;
}
2011-04-13 18:37:12 +00:00
2011-03-25 11:06:45 +00:00
if ( ! pOption )
{
str_format ( aBuf , sizeof ( aBuf ) , " '%s' isn't an option on this server " , pValue ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
2011-03-25 11:06:45 +00:00
return ;
}
}
else if ( str_comp_nocase ( pType , " kick " ) = = 0 )
{
int KickID = str_toint ( pValue ) ;
if ( KickID < 0 | | KickID > = MAX_CLIENTS | | ! pSelf - > m_apPlayers [ KickID ] )
{
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " Invalid client id to kick " ) ;
2011-03-25 11:06:45 +00:00
return ;
}
2020-09-26 19:41:58 +00:00
if ( ! g_Config . m_SvVoteKickBantime )
2011-03-25 11:06:45 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " kick %d %s " , KickID , pReason ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > ExecuteLine ( aBuf ) ;
2011-03-25 11:06:45 +00:00
}
else
{
2011-03-28 18:11:28 +00:00
char aAddrStr [ NETADDR_MAXSTRSIZE ] = { 0 } ;
pSelf - > Server ( ) - > GetClientAddr ( KickID , aAddrStr , sizeof ( aAddrStr ) ) ;
str_format ( aBuf , sizeof ( aBuf ) , " ban %s %d %s " , aAddrStr , g_Config . m_SvVoteKickBantime , pReason ) ;
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > ExecuteLine ( aBuf ) ;
2011-03-25 11:06:45 +00:00
}
}
2011-03-26 15:56:59 +00:00
else if ( str_comp_nocase ( pType , " spectate " ) = = 0 )
{
int SpectateID = str_toint ( pValue ) ;
if ( SpectateID < 0 | | SpectateID > = MAX_CLIENTS | | ! pSelf - > m_apPlayers [ SpectateID ] | | pSelf - > m_apPlayers [ SpectateID ] - > GetTeam ( ) = = TEAM_SPECTATORS )
{
2011-08-13 00:11:06 +00:00
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " Invalid client id to move " ) ;
2011-03-26 15:56:59 +00:00
return ;
}
2011-04-13 18:37:12 +00:00
2019-02-27 18:46:01 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " '%s' was moved to spectator (%s) " , pSelf - > Server ( ) - > ClientName ( SpectateID ) , pReason ) ;
2011-07-10 11:02:13 +00:00
pSelf - > SendChatTarget ( - 1 , aBuf ) ;
2011-05-25 10:05:32 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " set_team %d -1 %d " , SpectateID , g_Config . m_SvVoteSpectateRejoindelay ) ;
2011-03-26 15:56:59 +00:00
pSelf - > Console ( ) - > ExecuteLine ( aBuf ) ;
}
2011-03-25 11:06:45 +00:00
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConClearVotes ( IConsole : : IResult * pResult , void * pUserData )
2011-01-21 19:46:00 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
CNetMsg_Sv_VoteClearOptions VoteClearOptionsMsg ;
pSelf - > Server ( ) - > SendPackMsg ( & VoteClearOptionsMsg , MSGFLAG_VITAL , - 1 ) ;
pSelf - > m_pVoteOptionHeap - > Reset ( ) ;
pSelf - > m_pVoteOptionFirst = 0 ;
pSelf - > m_pVoteOptionLast = 0 ;
2011-03-26 21:06:29 +00:00
pSelf - > m_NumVoteOptions = 0 ;
2014-10-26 18:39:42 +00:00
// reset sending of vote options
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : pSelf - > m_apPlayers )
2014-10-26 18:39:42 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
pPlayer - > m_SendVoteIndex = 0 ;
2014-10-26 18:39:42 +00:00
}
2011-01-21 19:46:00 +00:00
}
2020-10-17 22:05:59 +00:00
struct CMapNameItem
{
2021-09-13 08:06:34 +00:00
char m_aName [ IO_MAX_PATH_LENGTH - 4 ] ;
2020-10-17 22:05:59 +00:00
bool operator < ( const CMapNameItem & Other ) const { return str_comp_nocase ( m_aName , Other . m_aName ) < 0 ; }
} ;
void CGameContext : : ConAddMapVotes ( IConsole : : IResult * pResult , void * pUserData )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2022-05-23 15:47:48 +00:00
std : : vector < CMapNameItem > MapList ;
2020-10-17 22:05:59 +00:00
pSelf - > Storage ( ) - > ListDirectory ( IStorage : : TYPE_ALL , " maps " , MapScan , & MapList ) ;
2022-05-23 15:47:48 +00:00
std : : sort ( MapList . begin ( ) , MapList . end ( ) ) ;
2020-10-17 22:05:59 +00:00
2022-05-23 15:47:48 +00:00
for ( auto & Item : MapList )
2020-10-17 22:05:59 +00:00
{
char aDescription [ 64 ] ;
2022-05-23 15:47:48 +00:00
str_format ( aDescription , sizeof ( aDescription ) , " Map: %s " , Item . m_aName ) ;
2020-10-17 22:05:59 +00:00
2021-09-13 08:06:34 +00:00
char aCommand [ IO_MAX_PATH_LENGTH * 2 + 10 ] ;
char aMapEscaped [ IO_MAX_PATH_LENGTH * 2 ] ;
2020-10-26 10:28:04 +00:00
char * pDst = aMapEscaped ;
2022-05-23 15:47:48 +00:00
str_escape ( & pDst , Item . m_aName , aMapEscaped + sizeof ( aMapEscaped ) ) ;
2020-10-26 10:28:04 +00:00
str_format ( aCommand , sizeof ( aCommand ) , " change_map \" %s \" " , aMapEscaped ) ;
2020-10-17 22:05:59 +00:00
pSelf - > AddVote ( aDescription , aCommand ) ;
}
pSelf - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , " added maps to votes " ) ;
}
int CGameContext : : MapScan ( const char * pName , int IsDir , int DirType , void * pUserData )
{
if ( IsDir | | ! str_endswith ( pName , " .map " ) )
return 0 ;
CMapNameItem Item ;
2022-05-23 15:47:48 +00:00
str_truncate ( Item . m_aName , sizeof ( Item . m_aName ) , pName , str_length ( pName ) - str_length ( " .map " ) ) ;
static_cast < std : : vector < CMapNameItem > * > ( pUserData ) - > push_back ( Item ) ;
2020-10-17 22:05:59 +00:00
return 0 ;
}
2011-08-13 00:11:06 +00:00
void CGameContext : : ConVote ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2012-01-26 21:17:26 +00:00
2010-05-29 07:25:38 +00:00
if ( str_comp_nocase ( pResult - > GetString ( 0 ) , " yes " ) = = 0 )
2018-01-18 15:17:23 +00:00
pSelf - > ForceVote ( pResult - > m_ClientID , true ) ;
2010-05-29 07:25:38 +00:00
else if ( str_comp_nocase ( pResult - > GetString ( 0 ) , " no " ) = = 0 )
2018-01-18 15:17:23 +00:00
pSelf - > ForceVote ( pResult - > m_ClientID , false ) ;
2010-05-29 07:25:38 +00:00
}
void CGameContext : : ConchainSpecialMotdupdate ( IConsole : : IResult * pResult , void * pUserData , IConsole : : FCommandCallback pfnCallback , void * pCallbackUserData )
{
2011-08-13 00:11:06 +00:00
pfnCallback ( pResult , pCallbackUserData ) ;
2010-05-29 07:25:38 +00:00
if ( pResult - > NumArguments ( ) )
{
CGameContext * pSelf = ( CGameContext * ) pUserData ;
2021-01-09 13:05:54 +00:00
pSelf - > SendMotd ( - 1 ) ;
2010-05-29 07:25:38 +00:00
}
}
void CGameContext : : OnConsoleInit ( )
{
m_pServer = Kernel ( ) - > RequestInterface < IServer > ( ) ;
2021-01-10 12:47:07 +00:00
m_pConfig = Kernel ( ) - > RequestInterface < IConfigManager > ( ) - > Values ( ) ;
2010-05-29 07:25:38 +00:00
m_pConsole = Kernel ( ) - > RequestInterface < IConsole > ( ) ;
2018-06-19 12:45:53 +00:00
m_pEngine = Kernel ( ) - > RequestInterface < IEngine > ( ) ;
2017-10-13 00:25:50 +00:00
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
2010-09-16 22:40:44 +00:00
2020-09-26 19:41:58 +00:00
Console ( ) - > Register ( " tune " , " s[tuning] i[value] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConTuneParam , this , " Tune variable to value " ) ;
Console ( ) - > Register ( " toggle_tune " , " s[tuning] i[value 1] i[value 2] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConToggleTuneParam , this , " Toggle tune variable " ) ;
2020-10-17 15:29:33 +00:00
Console ( ) - > Register ( " tune_reset " , " " , CFGFLAG_SERVER , ConTuneReset , this , " Reset tuning " ) ;
2020-10-11 14:27:28 +00:00
Console ( ) - > Register ( " tune_dump " , " " , CFGFLAG_SERVER , ConTuneDump , this , " Dump tuning " ) ;
2020-09-26 19:41:58 +00:00
Console ( ) - > Register ( " tune_zone " , " i[zone] s[tuning] i[value] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConTuneZone , this , " Tune in zone a variable to value " ) ;
2020-10-11 14:27:28 +00:00
Console ( ) - > Register ( " tune_zone_dump " , " i[zone] " , CFGFLAG_SERVER , ConTuneDumpZone , this , " Dump zone tuning in zone x " ) ;
2020-10-17 15:29:33 +00:00
Console ( ) - > Register ( " tune_zone_reset " , " ?i[zone] " , CFGFLAG_SERVER , ConTuneResetZone , this , " reset zone tuning in zone x or in all zones " ) ;
2020-10-11 13:59:57 +00:00
Console ( ) - > Register ( " tune_zone_enter " , " i[zone] r[message] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConTuneSetZoneMsgEnter , this , " which message to display on zone enter; use 0 for normal area " ) ;
2020-10-17 15:29:33 +00:00
Console ( ) - > Register ( " tune_zone_leave " , " i[zone] r[message] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConTuneSetZoneMsgLeave , this , " which message to display on zone leave; use 0 for normal area " ) ;
2020-09-26 19:41:58 +00:00
Console ( ) - > Register ( " mapbug " , " s[mapbug] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConMapbug , this , " Enable map compatibility mode using the specified bug (example: grenade-doublexplosion@ddnet.tw) " ) ;
Console ( ) - > Register ( " switch_open " , " i[switch] " , CFGFLAG_SERVER | CFGFLAG_GAME , ConSwitchOpen , this , " Whether a switch is deactivated by default (otherwise activated) " ) ;
2012-04-12 00:09:31 +00:00
Console ( ) - > Register ( " pause_game " , " " , CFGFLAG_SERVER , ConPause , this , " Pause/unpause game " ) ;
2020-09-26 19:41:58 +00:00
Console ( ) - > Register ( " change_map " , " ?r[map] " , CFGFLAG_SERVER | CFGFLAG_STORE , ConChangeMap , this , " Change map " ) ;
2015-12-28 15:14:52 +00:00
Console ( ) - > Register ( " random_map " , " ?i[stars] " , CFGFLAG_SERVER , ConRandomMap , this , " Random map " ) ;
Console ( ) - > Register ( " random_unfinished_map " , " ?i[stars] " , CFGFLAG_SERVER , ConRandomUnfinishedMap , this , " Random unfinished map " ) ;
2020-09-26 19:41:58 +00:00
Console ( ) - > Register ( " restart " , " ?i[seconds] " , CFGFLAG_SERVER | CFGFLAG_STORE , ConRestart , this , " Restart in x seconds (0 = abort) " ) ;
2015-12-28 15:14:52 +00:00
Console ( ) - > Register ( " broadcast " , " r[message] " , CFGFLAG_SERVER , ConBroadcast , this , " Broadcast message " ) ;
Console ( ) - > Register ( " say " , " r[message] " , CFGFLAG_SERVER , ConSay , this , " Say in chat " ) ;
Console ( ) - > Register ( " set_team " , " i[id] i[team-id] ?i[delay in minutes] " , CFGFLAG_SERVER , ConSetTeam , this , " Set team of player to team " ) ;
Console ( ) - > Register ( " set_team_all " , " i[team-id] " , CFGFLAG_SERVER , ConSetTeamAll , this , " Set team of all players to team " ) ;
2011-07-14 20:07:21 +00:00
2015-12-28 15:14:52 +00:00
Console ( ) - > Register ( " add_vote " , " s[name] r[command] " , CFGFLAG_SERVER , ConAddVote , this , " Add a voting option " ) ;
2020-10-04 09:40:38 +00:00
Console ( ) - > Register ( " remove_vote " , " r[name] " , CFGFLAG_SERVER , ConRemoveVote , this , " remove a voting option " ) ;
2015-12-28 15:14:52 +00:00
Console ( ) - > Register ( " force_vote " , " s[name] s[command] ?r[reason] " , CFGFLAG_SERVER , ConForceVote , this , " Force a voting option " ) ;
2011-07-14 20:07:21 +00:00
Console ( ) - > Register ( " clear_votes " , " " , CFGFLAG_SERVER , ConClearVotes , this , " Clears the voting options " ) ;
2020-10-17 22:05:59 +00:00
Console ( ) - > Register ( " add_map_votes " , " " , CFGFLAG_SERVER , ConAddMapVotes , this , " Automatically adds voting options for all maps " ) ;
2015-12-28 15:14:52 +00:00
Console ( ) - > Register ( " vote " , " r['yes'|'no'] " , CFGFLAG_SERVER , ConVote , this , " Force a vote to yes/no " ) ;
2020-03-11 00:58:50 +00:00
Console ( ) - > Register ( " dump_antibot " , " " , CFGFLAG_SERVER , ConDumpAntibot , this , " Dumps the antibot status " ) ;
2010-05-29 07:25:38 +00:00
Console ( ) - > Chain ( " sv_motd " , ConchainSpecialMotdupdate , this ) ;
2010-10-10 22:40:07 +00:00
2020-09-26 19:41:58 +00:00
# define CONSOLE_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
# include <game/ddracecommands.h>
# define CHAT_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
2021-01-11 21:54:08 +00:00
# include <game/ddracechat.h>
2010-05-29 07:25:38 +00:00
}
void CGameContext : : OnInit ( /*class IKernel *pKernel*/ )
{
m_pServer = Kernel ( ) - > RequestInterface < IServer > ( ) ;
2021-01-10 12:47:07 +00:00
m_pConfig = Kernel ( ) - > RequestInterface < IConfigManager > ( ) - > Values ( ) ;
2010-05-29 07:25:38 +00:00
m_pConsole = Kernel ( ) - > RequestInterface < IConsole > ( ) ;
2018-06-19 12:45:53 +00:00
m_pEngine = Kernel ( ) - > RequestInterface < IEngine > ( ) ;
2017-10-13 00:25:50 +00:00
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
2020-05-13 20:27:49 +00:00
m_pAntibot = Kernel ( ) - > RequestInterface < IAntibot > ( ) ;
m_pAntibot - > RoundStart ( this ) ;
2010-05-29 07:25:38 +00:00
m_World . SetGameServer ( this ) ;
m_Events . SetGameServer ( this ) ;
2011-04-13 18:37:12 +00:00
2017-09-12 12:58:44 +00:00
m_GameUuid = RandomUuid ( ) ;
2017-09-13 20:35:09 +00:00
Console ( ) - > SetTeeHistorianCommandCallback ( CommandCallback , this ) ;
2017-09-12 12:58:44 +00:00
2021-06-23 05:05:49 +00:00
uint64_t aSeed [ 2 ] ;
2020-05-26 08:59:49 +00:00
secure_random_fill ( aSeed , sizeof ( aSeed ) ) ;
m_Prng . Seed ( aSeed ) ;
2020-05-25 13:08:24 +00:00
m_World . m_Core . m_pPrng = & m_Prng ;
2015-07-14 20:08:29 +00:00
DeleteTempfile ( ) ;
2010-05-29 07:25:38 +00:00
//if(!data) // only load once
2020-09-26 19:41:58 +00:00
//data = load_data_from_memory(internal_data);
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < NUM_NETOBJTYPES ; i + + )
Server ( ) - > SnapSetStaticsize ( i , m_NetObjHandler . GetObjSize ( i ) ) ;
m_Layers . Init ( Kernel ( ) ) ;
m_Collision . Init ( & m_Layers ) ;
2021-12-20 14:00:21 +00:00
char aMapName [ IO_MAX_PATH_LENGTH ] ;
2018-03-24 13:00:41 +00:00
int MapSize ;
2018-06-05 19:22:40 +00:00
SHA256_DIGEST MapSha256 ;
2018-03-24 13:00:41 +00:00
int MapCrc ;
2018-06-05 19:22:40 +00:00
Server ( ) - > GetMapInfo ( aMapName , sizeof ( aMapName ) , & MapSize , & MapSha256 , & MapCrc ) ;
2020-10-10 20:06:47 +00:00
m_MapBugs = GetMapBugs ( aMapName , MapSize , MapSha256 ) ;
2018-03-24 13:00:41 +00:00
2010-05-29 07:25:38 +00:00
// reset everything here
//world = new GAMEWORLD;
//players = new CPlayer[MAX_CLIENTS];
2014-03-12 23:31:50 +00:00
// Reset Tunezones
CTuningParams TuningParams ;
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < NUM_TUNEZONES ; i + + )
2014-03-12 23:31:50 +00:00
{
2014-03-23 18:31:28 +00:00
TuningList ( ) [ i ] = TuningParams ;
TuningList ( ) [ i ] . Set ( " gun_curvature " , 0 ) ;
TuningList ( ) [ i ] . Set ( " gun_speed " , 1400 ) ;
TuningList ( ) [ i ] . Set ( " shotgun_curvature " , 0 ) ;
TuningList ( ) [ i ] . Set ( " shotgun_speed " , 500 ) ;
TuningList ( ) [ i ] . Set ( " shotgun_speeddiff " , 0 ) ;
2014-03-12 23:31:50 +00:00
}
2014-03-23 18:31:28 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < NUM_TUNEZONES ; i + + )
2014-03-12 23:31:50 +00:00
{
2017-07-26 01:58:00 +00:00
// Send no text by default when changing tune zones.
m_aaZoneEnterMsg [ i ] [ 0 ] = 0 ;
m_aaZoneLeaveMsg [ i ] [ 0 ] = 0 ;
2014-03-12 23:31:50 +00:00
}
2011-05-30 20:05:28 +00:00
// Reset Tuning
2011-09-02 18:37:03 +00:00
if ( g_Config . m_SvTuneReset )
{
ResetTuning ( ) ;
}
2011-09-05 11:55:47 +00:00
else
{
Tuning ( ) - > Set ( " gun_speed " , 1400 ) ;
Tuning ( ) - > Set ( " gun_curvature " , 0 ) ;
Tuning ( ) - > Set ( " shotgun_speed " , 500 ) ;
Tuning ( ) - > Set ( " shotgun_speeddiff " , 0 ) ;
Tuning ( ) - > Set ( " shotgun_curvature " , 0 ) ;
}
2011-09-02 18:37:03 +00:00
if ( g_Config . m_SvDDRaceTuneReset )
{
g_Config . m_SvHit = 1 ;
g_Config . m_SvEndlessDrag = 0 ;
g_Config . m_SvOldLaser = 0 ;
2013-11-24 18:23:58 +00:00
g_Config . m_SvOldTeleportHook = 0 ;
g_Config . m_SvOldTeleportWeapons = 0 ;
2014-04-04 22:35:18 +00:00
g_Config . m_SvTeleportHoldHook = 0 ;
2022-02-19 14:20:32 +00:00
g_Config . m_SvTeam = SV_TEAM_ALLOWED ;
2022-03-03 21:56:32 +00:00
g_Config . m_SvShowOthersDefault = SHOW_OTHERS_OFF ;
2015-07-22 21:31:50 +00:00
if ( Collision ( ) - > m_NumSwitchers > 0 )
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < Collision ( ) - > m_NumSwitchers + 1 ; + + i )
2015-07-22 21:31:50 +00:00
Collision ( ) - > m_pSwitchers [ i ] . m_Initial = true ;
2011-09-02 18:37:03 +00:00
}
2011-05-30 20:05:28 +00:00
2016-05-02 19:35:32 +00:00
Console ( ) - > ExecuteFile ( g_Config . m_SvResetFile , - 1 ) ;
2013-07-21 21:42:08 +00:00
2015-07-15 12:02:21 +00:00
LoadMapSettings ( ) ;
2018-05-01 10:38:33 +00:00
m_MapBugs . Dump ( ) ;
2020-06-30 18:22:17 +00:00
if ( g_Config . m_SvSoloServer )
{
2022-02-19 14:20:32 +00:00
g_Config . m_SvTeam = SV_TEAM_FORCED_SOLO ;
2022-03-03 21:56:32 +00:00
g_Config . m_SvShowOthersDefault = SHOW_OTHERS_ON ;
2020-06-30 18:22:17 +00:00
Tuning ( ) - > Set ( " player_collision " , 0 ) ;
Tuning ( ) - > Set ( " player_hooking " , 0 ) ;
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < NUM_TUNEZONES ; i + + )
2020-06-30 18:22:17 +00:00
{
TuningList ( ) [ i ] . Set ( " player_collision " , 0 ) ;
TuningList ( ) [ i ] . Set ( " player_hooking " , 0 ) ;
}
}
2017-10-10 00:39:29 +00:00
m_pController = new CGameControllerDDRace ( this ) ;
2020-09-18 15:37:27 +00:00
const char * pCensorFilename = " censorlist.txt " ;
2021-12-17 20:58:28 +00:00
IOHANDLE File = Storage ( ) - > OpenFile ( pCensorFilename , IOFLAG_READ | IOFLAG_SKIP_BOM , IStorage : : TYPE_ALL ) ;
2020-09-18 15:37:27 +00:00
if ( ! File )
{
dbg_msg ( " censorlist " , " failed to open '%s' " , pCensorFilename ) ;
}
else
{
CLineReader LineReader ;
LineReader . Init ( File ) ;
char * pLine ;
while ( ( pLine = LineReader . Get ( ) ) )
{
2022-05-23 20:35:21 +00:00
m_vCensorlist . emplace_back ( pLine ) ;
2020-09-18 15:37:27 +00:00
}
io_close ( File ) ;
}
2017-09-12 12:58:44 +00:00
m_TeeHistorianActive = g_Config . m_SvTeeHistorian ;
if ( m_TeeHistorianActive )
{
char aGameUuid [ UUID_MAXSTRSIZE ] ;
FormatUuid ( m_GameUuid , aGameUuid , sizeof ( aGameUuid ) ) ;
2021-09-13 08:06:34 +00:00
char aFilename [ IO_MAX_PATH_LENGTH ] ;
2017-09-12 12:58:44 +00:00
str_format ( aFilename , sizeof ( aFilename ) , " teehistorian/%s.teehistorian " , aGameUuid ) ;
2022-03-20 11:57:50 +00:00
IOHANDLE THFile = Storage ( ) - > OpenFile ( aFilename , IOFLAG_WRITE , IStorage : : TYPE_SAVE ) ;
if ( ! THFile )
2017-09-12 12:58:44 +00:00
{
dbg_msg ( " teehistorian " , " failed to open '%s' " , aFilename ) ;
2017-10-13 00:25:50 +00:00
Server ( ) - > SetErrorShutdown ( " teehistorian open error " ) ;
return ;
2017-09-12 12:58:44 +00:00
}
else
{
dbg_msg ( " teehistorian " , " recording to '%s' " , aFilename ) ;
}
2022-03-20 11:57:50 +00:00
m_pTeeHistorianFile = aio_new ( THFile ) ;
2017-09-12 12:58:44 +00:00
char aVersion [ 128 ] ;
2018-03-01 15:50:29 +00:00
if ( GIT_SHORTREV_HASH )
{
str_format ( aVersion , sizeof ( aVersion ) , " %s (%s) " , GAME_VERSION , GIT_SHORTREV_HASH ) ;
}
else
{
str_format ( aVersion , sizeof ( aVersion ) , " %s " , GAME_VERSION ) ;
}
2017-09-12 12:58:44 +00:00
CTeeHistorian : : CGameInfo GameInfo ;
GameInfo . m_GameUuid = m_GameUuid ;
GameInfo . m_pServerVersion = aVersion ;
GameInfo . m_StartTime = time ( 0 ) ;
2020-05-25 13:08:24 +00:00
GameInfo . m_pPrngDescription = m_Prng . Description ( ) ;
2017-09-12 12:58:44 +00:00
GameInfo . m_pServerName = g_Config . m_SvName ;
2020-08-29 12:14:37 +00:00
GameInfo . m_ServerPort = Server ( ) - > Port ( ) ;
2017-09-27 17:38:54 +00:00
GameInfo . m_pGameType = m_pController - > m_pGameType ;
2017-09-12 12:58:44 +00:00
2017-09-13 20:35:09 +00:00
GameInfo . m_pConfig = & g_Config ;
GameInfo . m_pTuning = Tuning ( ) ;
2017-11-18 02:08:16 +00:00
GameInfo . m_pUuids = & g_UuidManager ;
2017-09-13 20:35:09 +00:00
2017-09-12 12:58:44 +00:00
GameInfo . m_pMapName = aMapName ;
2018-03-24 13:00:41 +00:00
GameInfo . m_MapSize = MapSize ;
2018-06-05 19:22:40 +00:00
GameInfo . m_MapSha256 = MapSha256 ;
2018-03-24 13:00:41 +00:00
GameInfo . m_MapCrc = MapCrc ;
2017-09-12 12:58:44 +00:00
m_TeeHistorian . Reset ( & GameInfo , TeeHistorianWrite , this ) ;
2018-01-28 02:13:05 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
int Level = Server ( ) - > GetAuthedState ( i ) ;
if ( Level )
{
m_TeeHistorian . RecordAuthInitial ( i , Level , Server ( ) - > GetAuthName ( i ) ) ;
}
}
2017-09-12 12:58:44 +00:00
}
2020-07-04 17:53:27 +00:00
if ( ! m_pScore )
{
m_pScore = new CScore ( this , ( ( CServer * ) Server ( ) ) - > DbPool ( ) ) ;
}
2011-04-09 06:41:31 +00:00
2010-05-29 07:25:38 +00:00
// setup core world
//for(int i = 0; i < MAX_CLIENTS; i++)
// game.players[i].core.world = &game.world.core;
2011-01-29 00:59:50 +00:00
2010-05-29 07:25:38 +00:00
// create all entities from the game layer
CMapItemLayerTilemap * pTileMap = m_Layers . GameLayer ( ) ;
CTile * pTiles = ( CTile * ) Kernel ( ) - > RequestInterface < IMap > ( ) - > GetData ( pTileMap - > m_Data ) ;
2011-04-13 18:37:12 +00:00
2010-11-13 13:22:19 +00:00
CTile * pFront = 0 ;
CSwitchTile * pSwitch = 0 ;
2010-10-10 22:40:07 +00:00
if ( m_Layers . FrontLayer ( ) )
2011-08-26 11:46:22 +00:00
pFront = ( CTile * ) Kernel ( ) - > RequestInterface < IMap > ( ) - > GetData ( m_Layers . FrontLayer ( ) - > m_Front ) ;
2010-11-13 13:22:19 +00:00
if ( m_Layers . SwitchLayer ( ) )
2011-08-26 11:46:22 +00:00
pSwitch = ( CSwitchTile * ) Kernel ( ) - > RequestInterface < IMap > ( ) - > GetData ( m_Layers . SwitchLayer ( ) - > m_Switch ) ;
2010-08-20 20:40:12 +00:00
2010-05-29 07:25:38 +00:00
for ( int y = 0 ; y < pTileMap - > m_Height ; y + + )
{
for ( int x = 0 ; x < pTileMap - > m_Width ; x + + )
{
2020-09-26 19:41:58 +00:00
int Index = pTiles [ y * pTileMap - > m_Width + x ] . m_Index ;
2011-04-13 18:37:12 +00:00
2010-12-01 22:45:04 +00:00
if ( Index = = TILE_OLDLASER )
2010-12-01 23:33:02 +00:00
{
2010-12-01 22:45:04 +00:00
g_Config . m_SvOldLaser = 1 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " game_layer " , " found old laser tile " ) ;
2010-12-01 23:33:02 +00:00
}
2010-12-01 22:45:04 +00:00
else if ( Index = = TILE_NPC )
2010-12-01 23:33:02 +00:00
{
2011-01-29 00:59:50 +00:00
m_Tuning . Set ( " player_collision " , 0 ) ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " game_layer " , " found no collision tile " ) ;
2010-12-01 23:33:02 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_EHOOK )
2010-12-01 23:33:02 +00:00
{
2010-08-28 19:34:21 +00:00
g_Config . m_SvEndlessDrag = 1 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " game_layer " , " found unlimited hook time tile " ) ;
2010-12-01 23:33:02 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_NOHIT )
2010-12-01 23:33:02 +00:00
{
2010-08-28 19:34:21 +00:00
g_Config . m_SvHit = 0 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " game_layer " , " found no weapons hitting others tile " ) ;
2010-12-01 23:33:02 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_NPH )
2010-12-01 23:33:02 +00:00
{
2011-01-29 00:59:50 +00:00
m_Tuning . Set ( " player_hooking " , 0 ) ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " game_layer " , " found no player hooking tile " ) ;
2010-12-01 23:33:02 +00:00
}
2011-04-09 06:41:31 +00:00
2010-05-29 07:25:38 +00:00
if ( Index > = ENTITY_OFFSET )
{
2020-09-26 19:41:58 +00:00
vec2 Pos ( x * 32.0f + 16.0f , y * 32.0f + 16.0f ) ;
2011-01-29 00:59:50 +00:00
m_pController - > OnEntity ( Index - ENTITY_OFFSET , Pos , LAYER_GAME , pTiles [ y * pTileMap - > m_Width + x ] . m_Flags ) ;
2010-08-20 20:40:12 +00:00
}
2011-04-09 06:41:31 +00:00
2010-10-10 22:40:07 +00:00
if ( pFront )
2010-08-20 20:40:12 +00:00
{
2011-01-29 00:59:50 +00:00
Index = pFront [ y * pTileMap - > m_Width + x ] . m_Index ;
2010-12-01 22:45:04 +00:00
if ( Index = = TILE_OLDLASER )
2011-01-29 00:59:50 +00:00
{
2010-12-01 22:45:04 +00:00
g_Config . m_SvOldLaser = 1 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " front_layer " , " found old laser tile " ) ;
2011-01-29 00:59:50 +00:00
}
2010-12-01 22:45:04 +00:00
else if ( Index = = TILE_NPC )
2011-01-29 00:59:50 +00:00
{
m_Tuning . Set ( " player_collision " , 0 ) ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " front_layer " , " found no collision tile " ) ;
2011-01-29 00:59:50 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_EHOOK )
2011-01-29 00:59:50 +00:00
{
2010-08-28 19:34:21 +00:00
g_Config . m_SvEndlessDrag = 1 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " front_layer " , " found unlimited hook time tile " ) ;
2011-01-29 00:59:50 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_NOHIT )
2011-01-29 00:59:50 +00:00
{
2010-08-28 19:34:21 +00:00
g_Config . m_SvHit = 0 ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " front_layer " , " found no weapons hitting others tile " ) ;
2011-01-29 00:59:50 +00:00
}
2010-10-10 22:40:07 +00:00
else if ( Index = = TILE_NPH )
2011-01-29 00:59:50 +00:00
{
m_Tuning . Set ( " player_hooking " , 0 ) ;
2020-10-26 08:57:41 +00:00
dbg_msg ( " front_layer " , " found no player hooking tile " ) ;
2011-01-29 00:59:50 +00:00
}
2010-08-27 23:30:50 +00:00
if ( Index > = ENTITY_OFFSET )
2010-08-20 20:40:12 +00:00
{
2020-09-26 19:41:58 +00:00
vec2 Pos ( x * 32.0f + 16.0f , y * 32.0f + 16.0f ) ;
m_pController - > OnEntity ( Index - ENTITY_OFFSET , Pos , LAYER_FRONT , pFront [ y * pTileMap - > m_Width + x ] . m_Flags ) ;
2010-11-13 13:22:19 +00:00
}
}
if ( pSwitch )
{
2020-09-26 19:41:58 +00:00
Index = pSwitch [ y * pTileMap - > m_Width + x ] . m_Type ;
2013-08-22 22:45:48 +00:00
// TODO: Add off by default door here
// if (Index == TILE_DOOR_OFF)
2010-11-13 13:22:19 +00:00
if ( Index > = ENTITY_OFFSET )
{
2020-09-26 19:41:58 +00:00
vec2 Pos ( x * 32.0f + 16.0f , y * 32.0f + 16.0f ) ;
m_pController - > OnEntity ( Index - ENTITY_OFFSET , Pos , LAYER_SWITCH , pSwitch [ y * pTileMap - > m_Width + x ] . m_Flags , pSwitch [ y * pTileMap - > m_Width + x ] . m_Number ) ;
2010-08-20 20:40:12 +00:00
}
2010-05-29 07:25:38 +00:00
}
}
}
2011-01-29 00:59:50 +00:00
//game.world.insert_entity(game.Controller);
2021-08-16 16:29:24 +00:00
if ( GIT_SHORTREV_HASH )
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " git-revision " , GIT_SHORTREV_HASH ) ;
2021-08-16 14:35:26 +00:00
2010-05-29 07:25:38 +00:00
# ifdef CONF_DEBUG
if ( g_Config . m_DbgDummies )
{
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < g_Config . m_DbgDummies ; i + + )
2010-05-29 07:25:38 +00:00
{
2021-02-07 15:03:31 +00:00
OnClientConnected ( MAX_CLIENTS - i - 1 , 0 ) ;
2010-05-29 07:25:38 +00:00
}
}
# endif
}
2015-07-14 20:08:29 +00:00
void CGameContext : : DeleteTempfile ( )
{
if ( m_aDeleteTempfile [ 0 ] ! = 0 )
{
2017-10-13 00:25:50 +00:00
Storage ( ) - > RemoveFile ( m_aDeleteTempfile , IStorage : : TYPE_SAVE ) ;
2015-07-14 20:08:29 +00:00
m_aDeleteTempfile [ 0 ] = 0 ;
}
}
void CGameContext : : OnMapChange ( char * pNewMapName , int MapNameSize )
{
2021-12-20 14:00:21 +00:00
char aConfig [ IO_MAX_PATH_LENGTH ] ;
2015-07-14 20:08:29 +00:00
str_format ( aConfig , sizeof ( aConfig ) , " maps/%s.cfg " , g_Config . m_SvMap ) ;
2021-12-17 20:58:28 +00:00
IOHANDLE File = Storage ( ) - > OpenFile ( aConfig , IOFLAG_READ | IOFLAG_SKIP_BOM , IStorage : : TYPE_ALL ) ;
2015-07-14 20:08:29 +00:00
if ( ! File )
{
// No map-specific config, just return.
return ;
}
CLineReader LineReader ;
LineReader . Init ( File ) ;
2022-05-23 21:03:52 +00:00
std : : vector < char * > vLines ;
2015-07-14 20:08:29 +00:00
char * pLine ;
int TotalLength = 0 ;
while ( ( pLine = LineReader . Get ( ) ) )
{
int Length = str_length ( pLine ) + 1 ;
2018-04-09 09:56:39 +00:00
char * pCopy = ( char * ) malloc ( Length ) ;
2015-07-14 20:08:29 +00:00
mem_copy ( pCopy , pLine , Length ) ;
2022-05-23 21:03:52 +00:00
vLines . push_back ( pCopy ) ;
2015-07-14 20:08:29 +00:00
TotalLength + = Length ;
}
2017-07-08 11:38:27 +00:00
io_close ( File ) ;
2015-07-14 20:08:29 +00:00
2020-10-12 14:07:29 +00:00
char * pSettings = ( char * ) malloc ( maximum ( 1 , TotalLength ) ) ;
2015-07-14 20:08:29 +00:00
int Offset = 0 ;
2022-05-23 21:03:52 +00:00
for ( auto & Line : vLines )
2015-07-14 20:08:29 +00:00
{
2022-05-23 21:03:52 +00:00
int Length = str_length ( Line ) + 1 ;
mem_copy ( pSettings + Offset , Line , Length ) ;
2015-07-15 09:38:42 +00:00
Offset + = Length ;
2022-05-23 21:03:52 +00:00
free ( Line ) ;
2015-07-14 20:08:29 +00:00
}
CDataFileReader Reader ;
2017-10-13 00:25:50 +00:00
Reader . Open ( Storage ( ) , pNewMapName , IStorage : : TYPE_ALL ) ;
2015-07-14 20:08:29 +00:00
CDataFileWriter Writer ;
2015-08-27 11:37:34 +00:00
Writer . Init ( ) ;
2015-07-14 20:08:29 +00:00
int SettingsIndex = Reader . NumData ( ) ;
2015-08-27 13:46:51 +00:00
bool FoundInfo = false ;
2015-07-14 20:08:29 +00:00
for ( int i = 0 ; i < Reader . NumItems ( ) ; i + + )
{
int TypeID ;
int ItemID ;
int * pData = ( int * ) Reader . GetItem ( i , & TypeID , & ItemID ) ;
2017-08-28 16:06:19 +00:00
int Size = Reader . GetItemSize ( i ) ;
2015-07-14 20:08:29 +00:00
CMapItemInfoSettings MapInfo ;
if ( TypeID = = MAPITEMTYPE_INFO & & ItemID = = 0 )
{
2015-08-27 13:46:51 +00:00
FoundInfo = true ;
2015-07-14 20:08:29 +00:00
CMapItemInfoSettings * pInfo = ( CMapItemInfoSettings * ) pData ;
if ( Size > = ( int ) sizeof ( CMapItemInfoSettings ) )
{
2015-08-21 21:02:50 +00:00
if ( pInfo - > m_Settings > - 1 )
2015-07-14 20:08:29 +00:00
{
2015-08-21 21:02:50 +00:00
SettingsIndex = pInfo - > m_Settings ;
char * pMapSettings = ( char * ) Reader . GetData ( SettingsIndex ) ;
2017-08-30 06:36:17 +00:00
int DataSize = Reader . GetDataSize ( SettingsIndex ) ;
2015-08-27 14:20:56 +00:00
if ( DataSize = = TotalLength & & mem_comp ( pSettings , pMapSettings , DataSize ) = = 0 )
2015-08-21 21:02:50 +00:00
{
// Configs coincide, no need to update map.
2020-10-12 14:07:29 +00:00
free ( pSettings ) ;
2015-08-21 21:02:50 +00:00
return ;
}
Reader . UnloadData ( pInfo - > m_Settings ) ;
}
else
{
MapInfo = * pInfo ;
MapInfo . m_Settings = SettingsIndex ;
pData = ( int * ) & MapInfo ;
Size = sizeof ( MapInfo ) ;
2015-07-14 20:08:29 +00:00
}
}
else
{
* ( CMapItemInfo * ) & MapInfo = * ( CMapItemInfo * ) pInfo ;
MapInfo . m_Settings = SettingsIndex ;
pData = ( int * ) & MapInfo ;
Size = sizeof ( MapInfo ) ;
}
}
Writer . AddItem ( TypeID , ItemID , Size , pData ) ;
}
2015-08-27 13:46:51 +00:00
if ( ! FoundInfo )
{
CMapItemInfoSettings Info ;
Info . m_Version = 1 ;
Info . m_Author = - 1 ;
Info . m_MapVersion = - 1 ;
Info . m_Credits = - 1 ;
Info . m_License = - 1 ;
Info . m_Settings = SettingsIndex ;
Writer . AddItem ( MAPITEMTYPE_INFO , 0 , sizeof ( Info ) , & Info ) ;
}
2015-07-14 20:08:29 +00:00
for ( int i = 0 ; i < Reader . NumData ( ) | | i = = SettingsIndex ; i + + )
{
if ( i = = SettingsIndex )
{
Writer . AddData ( TotalLength , pSettings ) ;
continue ;
}
unsigned char * pData = ( unsigned char * ) Reader . GetData ( i ) ;
2017-08-30 06:36:17 +00:00
int Size = Reader . GetDataSize ( i ) ;
2015-07-14 20:08:29 +00:00
Writer . AddData ( Size , pData ) ;
Reader . UnloadData ( i ) ;
}
dbg_msg ( " mapchange " , " imported settings " ) ;
2020-10-12 14:07:29 +00:00
free ( pSettings ) ;
2015-07-14 20:08:29 +00:00
Reader . Close ( ) ;
2021-12-20 14:00:21 +00:00
char aTemp [ IO_MAX_PATH_LENGTH ] ;
Writer . OpenFile ( Storage ( ) , IStorage : : FormatTmpPath ( aTemp , sizeof ( aTemp ) , pNewMapName ) ) ;
2015-07-14 20:08:29 +00:00
Writer . Finish ( ) ;
str_copy ( pNewMapName , aTemp , MapNameSize ) ;
str_copy ( m_aDeleteTempfile , aTemp , sizeof ( m_aDeleteTempfile ) ) ;
}
2020-07-04 17:53:27 +00:00
void CGameContext : : OnShutdown ( )
2010-05-29 07:25:38 +00:00
{
2020-05-13 20:27:49 +00:00
Antibot ( ) - > RoundEnd ( ) ;
2017-09-12 12:58:44 +00:00
if ( m_TeeHistorianActive )
{
m_TeeHistorian . Finish ( ) ;
2017-10-13 00:48:42 +00:00
aio_close ( m_pTeeHistorianFile ) ;
aio_wait ( m_pTeeHistorianFile ) ;
int Error = aio_error ( m_pTeeHistorianFile ) ;
2017-10-10 02:07:38 +00:00
if ( Error )
{
dbg_msg ( " teehistorian " , " error closing file, err=%d " , Error ) ;
2017-10-13 00:25:50 +00:00
Server ( ) - > SetErrorShutdown ( " teehistorian close error " ) ;
2017-10-10 02:07:38 +00:00
}
2017-10-13 00:48:42 +00:00
aio_free ( m_pTeeHistorianFile ) ;
2017-09-12 12:58:44 +00:00
}
2015-07-14 20:08:29 +00:00
DeleteTempfile ( ) ;
2015-07-15 12:02:21 +00:00
Console ( ) - > ResetServerGameSettings ( ) ;
2010-10-27 10:14:26 +00:00
Collision ( ) - > Dest ( ) ;
2010-05-29 07:25:38 +00:00
delete m_pController ;
m_pController = 0 ;
Clear ( ) ;
2008-08-14 18:42:47 +00:00
}
2011-07-13 20:38:32 +00:00
void CGameContext : : LoadMapSettings ( )
{
IMap * pMap = Kernel ( ) - > RequestInterface < IMap > ( ) ;
int Start , Num ;
pMap - > GetType ( MAPITEMTYPE_INFO , & Start , & Num ) ;
for ( int i = Start ; i < Start + Num ; i + + )
{
int ItemID ;
CMapItemInfoSettings * pItem = ( CMapItemInfoSettings * ) pMap - > GetItem ( i , 0 , & ItemID ) ;
2017-08-28 16:06:19 +00:00
int ItemSize = pMap - > GetItemSize ( i ) ;
2011-07-13 20:38:32 +00:00
if ( ! pItem | | ItemID ! = 0 )
continue ;
if ( ItemSize < ( int ) sizeof ( CMapItemInfoSettings ) )
break ;
if ( ! ( pItem - > m_Settings > - 1 ) )
break ;
2017-08-30 06:36:17 +00:00
int Size = pMap - > GetDataSize ( pItem - > m_Settings ) ;
2011-07-13 20:38:32 +00:00
char * pSettings = ( char * ) pMap - > GetData ( pItem - > m_Settings ) ;
char * pNext = pSettings ;
while ( pNext < pSettings + Size )
{
int StrSize = str_length ( pNext ) + 1 ;
2015-07-15 12:02:21 +00:00
Console ( ) - > ExecuteLine ( pNext , IConsole : : CLIENT_ID_GAME ) ;
2011-07-13 20:38:32 +00:00
pNext + = StrSize ;
}
pMap - > UnloadData ( pItem - > m_Settings ) ;
2015-08-21 21:02:50 +00:00
break ;
2011-07-13 20:38:32 +00:00
}
2015-07-15 12:02:21 +00:00
2021-12-20 14:00:21 +00:00
char aBuf [ IO_MAX_PATH_LENGTH ] ;
2015-07-15 12:02:21 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " maps/%s.map.cfg " , g_Config . m_SvMap ) ;
Console ( ) - > ExecuteFile ( aBuf , IConsole : : CLIENT_ID_NO_GAME ) ;
2011-07-13 20:38:32 +00:00
}
2011-02-12 10:40:36 +00:00
void CGameContext : : OnSnap ( int ClientID )
2008-08-14 18:42:47 +00:00
{
2012-01-08 23:49:20 +00:00
// add tuning to demo
CTuningParams StandardTuning ;
if ( ClientID = = - 1 & & Server ( ) - > DemoRecorder_IsRecording ( ) & & mem_comp ( & StandardTuning , & m_Tuning , sizeof ( CTuningParams ) ) ! = 0 )
{
CMsgPacker Msg ( NETMSGTYPE_SV_TUNEPARAMS ) ;
int * pParams = ( int * ) & m_Tuning ;
2020-09-26 19:41:58 +00:00
for ( unsigned i = 0 ; i < sizeof ( m_Tuning ) / sizeof ( int ) ; i + + )
2012-01-08 23:49:20 +00:00
Msg . AddInt ( pParams [ i ] ) ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendMsg ( & Msg , MSGFLAG_RECORD | MSGFLAG_NOSEND , ClientID ) ;
2012-01-08 23:49:20 +00:00
}
2021-10-25 00:34:28 +00:00
m_pController - > Snap ( ClientID ) ;
2020-10-26 14:14:07 +00:00
for ( auto & pPlayer : m_apPlayers )
2008-08-14 18:42:47 +00:00
{
2020-10-26 14:14:07 +00:00
if ( pPlayer )
pPlayer - > Snap ( ClientID ) ;
2008-08-14 18:42:47 +00:00
}
2014-09-26 01:20:47 +00:00
if ( ClientID > - 1 )
2016-09-20 19:40:40 +00:00
m_apPlayers [ ClientID ] - > FakeSnap ( ) ;
2021-10-21 20:39:54 +00:00
m_World . Snap ( ClientID ) ;
m_Events . Snap ( ClientID ) ;
2008-08-14 18:42:47 +00:00
}
2010-05-29 07:25:38 +00:00
void CGameContext : : OnPreSnap ( ) { }
void CGameContext : : OnPostSnap ( )
{
m_Events . Clear ( ) ;
}
2021-02-08 21:26:26 +00:00
bool CGameContext : : IsClientReady ( int ClientID ) const
2011-03-15 08:58:57 +00:00
{
2022-01-22 16:34:23 +00:00
return m_apPlayers [ ClientID ] & & m_apPlayers [ ClientID ] - > m_IsReady ;
2011-03-15 08:58:57 +00:00
}
2021-02-08 21:26:26 +00:00
bool CGameContext : : IsClientPlayer ( int ClientID ) const
2011-03-20 14:33:49 +00:00
{
2021-02-07 15:03:31 +00:00
return m_apPlayers [ ClientID ] & & m_apPlayers [ ClientID ] - > GetTeam ( ) ! = TEAM_SPECTATORS ;
2011-03-20 14:33:49 +00:00
}
2021-02-08 21:26:26 +00:00
CUuid CGameContext : : GameUuid ( ) const { return m_GameUuid ; }
const char * CGameContext : : GameType ( ) const { return m_pController & & m_pController - > m_pGameType ? m_pController - > m_pGameType : " " ; }
const char * CGameContext : : Version ( ) const { return GAME_VERSION ; }
const char * CGameContext : : NetVersion ( ) const { return GAME_NETVERSION ; }
2010-05-29 07:25:38 +00:00
IGameServer * CreateGameServer ( ) { return new CGameContext ; }
2010-09-17 09:34:13 +00:00
2011-01-29 00:59:50 +00:00
bool CGameContext : : PlayerCollision ( )
{
float Temp ;
m_Tuning . Get ( " player_collision " , & Temp ) ;
2019-07-08 21:08:42 +00:00
return Temp ! = 0.0f ;
2011-01-29 00:59:50 +00:00
}
bool CGameContext : : PlayerHooking ( )
{
float Temp ;
m_Tuning . Get ( " player_hooking " , & Temp ) ;
2019-07-08 21:08:42 +00:00
return Temp ! = 0.0f ;
2011-01-29 00:59:50 +00:00
}
2013-11-13 12:25:26 +00:00
float CGameContext : : PlayerJetpack ( )
{
float Temp ;
m_Tuning . Get ( " player_jetpack " , & Temp ) ;
return Temp ;
}
2011-02-13 05:35:13 +00:00
void CGameContext : : OnSetAuthed ( int ClientID , int Level )
2011-01-29 00:59:50 +00:00
{
2011-02-13 05:35:13 +00:00
if ( m_apPlayers [ ClientID ] )
2011-01-29 00:59:50 +00:00
{
2011-08-13 00:11:06 +00:00
char aBuf [ 512 ] , aIP [ NETADDR_MAXSTRSIZE ] ;
2017-06-06 03:51:12 +00:00
Server ( ) - > GetClientAddr ( ClientID , aIP , sizeof ( aIP ) ) ;
2011-07-20 00:41:11 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " ban %s %d Banned by vote " , aIP , g_Config . m_SvVoteKickBantime ) ;
2019-02-08 18:43:07 +00:00
if ( ! str_comp_nocase ( m_aVoteCommand , aBuf ) & & Level > Server ( ) - > GetAuthedState ( m_VoteCreator ) )
2011-01-29 00:59:50 +00:00
{
2011-12-26 09:15:43 +00:00
m_VoteEnforce = CGameContext : : VOTE_ENFORCE_NO_ADMIN ;
2019-02-27 18:46:01 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " CGameContext " , " Vote aborted by authorized login. " ) ;
2011-01-29 00:59:50 +00:00
}
}
2018-01-28 02:13:05 +00:00
if ( m_TeeHistorianActive )
{
if ( Level )
{
m_TeeHistorian . RecordAuthLogin ( ClientID , Level , Server ( ) - > GetAuthName ( ClientID ) ) ;
}
else
{
m_TeeHistorian . RecordAuthLogout ( ClientID ) ;
}
}
2011-01-29 00:59:50 +00:00
}
2011-02-27 08:07:57 +00:00
void CGameContext : : SendRecord ( int ClientID )
{
2021-02-24 22:40:11 +00:00
CNetMsg_Sv_Record Msg ;
CNetMsg_Sv_RecordLegacy MsgLegacy ;
MsgLegacy . m_PlayerTimeBest = Msg . m_PlayerTimeBest = Score ( ) - > PlayerData ( ClientID ) - > m_BestTime * 100.0f ;
MsgLegacy . m_ServerTimeBest = Msg . m_ServerTimeBest = m_pController - > m_CurrentRecord * 100.0f ; //TODO: finish this
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
if ( ! Server ( ) - > IsSixup ( ClientID ) & & GetClientVersion ( ClientID ) < VERSION_DDNET_MSG_LEGACY )
{
Server ( ) - > SendPackMsg ( & MsgLegacy , MSGFLAG_VITAL , ClientID ) ;
}
2011-02-23 07:43:05 +00:00
}
2011-02-27 08:07:57 +00:00
2021-06-23 06:51:11 +00:00
int CGameContext : : ProcessSpamProtection ( int ClientID , bool RespectChatInitialDelay )
2011-02-27 08:07:57 +00:00
{
2011-09-07 23:02:09 +00:00
if ( ! m_apPlayers [ ClientID ] )
return 0 ;
2020-09-26 19:41:58 +00:00
if ( g_Config . m_SvSpamprotection & & m_apPlayers [ ClientID ] - > m_LastChat & & m_apPlayers [ ClientID ] - > m_LastChat + Server ( ) - > TickSpeed ( ) * g_Config . m_SvChatDelay > Server ( ) - > Tick ( ) )
2011-02-27 08:07:57 +00:00
return 1 ;
2021-03-01 18:54:18 +00:00
else if ( g_Config . m_SvDnsblChat & & Server ( ) - > DnsblBlack ( ClientID ) )
{
SendChatTarget ( ClientID , " Players are not allowed to chat from VPNs at this time " ) ;
return 1 ;
}
2011-02-27 08:07:57 +00:00
else
2011-04-09 06:41:31 +00:00
m_apPlayers [ ClientID ] - > m_LastChat = Server ( ) - > Tick ( ) ;
2021-03-01 18:54:18 +00:00
2011-02-27 08:07:57 +00:00
NETADDR Addr ;
Server ( ) - > GetClientAddr ( ClientID , & Addr ) ;
2021-03-01 18:44:59 +00:00
int Muted = 0 ;
2021-12-18 10:19:35 +00:00
for ( int i = 0 ; i < m_NumMutes & & Muted < = 0 ; i + + )
2011-02-27 08:07:57 +00:00
{
2021-12-18 10:19:35 +00:00
if ( ! net_addr_comp_noport ( & Addr , & m_aMutes [ i ] . m_Addr ) )
2021-03-01 18:44:59 +00:00
{
2021-12-18 10:19:35 +00:00
if ( RespectChatInitialDelay | | m_aMutes [ i ] . m_InitialChatDelay )
2021-03-01 18:44:59 +00:00
Muted = ( m_aMutes [ i ] . m_Expire - Server ( ) - > Tick ( ) ) / Server ( ) - > TickSpeed ( ) ;
}
2011-02-27 08:07:57 +00:00
}
2020-09-26 19:41:58 +00:00
if ( Muted > 0 )
2011-02-27 08:07:57 +00:00
{
char aBuf [ 128 ] ;
str_format ( aBuf , sizeof aBuf , " You are not permitted to talk for the next %d seconds. " , Muted ) ;
SendChatTarget ( ClientID , aBuf ) ;
return 1 ;
}
2022-03-20 13:12:19 +00:00
if ( g_Config . m_SvSpamMuteDuration & & ( m_apPlayers [ ClientID ] - > m_ChatScore + = g_Config . m_SvChatPenalty ) > g_Config . m_SvChatThreshold )
2011-02-27 08:07:57 +00:00
{
2018-10-08 18:29:33 +00:00
Mute ( & Addr , g_Config . m_SvSpamMuteDuration , Server ( ) - > ClientName ( ClientID ) ) ;
2011-02-27 08:07:57 +00:00
m_apPlayers [ ClientID ] - > m_ChatScore = 0 ;
return 1 ;
}
return 0 ;
}
2011-04-19 19:44:02 +00:00
int CGameContext : : GetDDRaceTeam ( int ClientID )
{
2020-09-26 19:41:58 +00:00
CGameControllerDDRace * pController = ( CGameControllerDDRace * ) m_pController ;
2011-04-19 19:44:02 +00:00
return pController - > m_Teams . m_Core . Team ( ClientID ) ;
}
2011-05-30 20:05:28 +00:00
void CGameContext : : ResetTuning ( )
{
CTuningParams TuningParams ;
m_Tuning = TuningParams ;
Tuning ( ) - > Set ( " gun_speed " , 1400 ) ;
Tuning ( ) - > Set ( " gun_curvature " , 0 ) ;
Tuning ( ) - > Set ( " shotgun_speed " , 500 ) ;
Tuning ( ) - > Set ( " shotgun_speeddiff " , 0 ) ;
Tuning ( ) - > Set ( " shotgun_curvature " , 0 ) ;
SendTuningParams ( - 1 ) ;
}
2013-08-09 13:04:20 +00:00
bool CheckClientID2 ( int ClientID )
{
2022-01-22 16:34:23 +00:00
return ClientID > = 0 & & ClientID < MAX_CLIENTS ;
2013-08-09 13:04:20 +00:00
}
void CGameContext : : Whisper ( int ClientID , char * pStr )
{
char * pName ;
char * pMessage ;
int Error = 0 ;
2013-08-10 01:40:59 +00:00
if ( ProcessSpamProtection ( ClientID ) )
return ;
2013-08-09 13:04:20 +00:00
pStr = str_skip_whitespaces ( pStr ) ;
2013-08-12 21:02:39 +00:00
int Victim ;
2013-08-09 13:04:20 +00:00
// add token
if ( * pStr = = ' " ' )
{
pStr + + ;
2020-04-28 06:54:24 +00:00
pName = pStr ;
char * pDst = pStr ; // we might have to process escape data
2022-02-14 23:12:52 +00:00
while ( true )
2013-08-09 13:04:20 +00:00
{
if ( pStr [ 0 ] = = ' " ' )
2021-11-27 19:55:55 +00:00
{
2013-08-09 13:04:20 +00:00
break ;
2021-11-27 19:55:55 +00:00
}
2013-08-09 13:04:20 +00:00
else if ( pStr [ 0 ] = = ' \\ ' )
{
if ( pStr [ 1 ] = = ' \\ ' )
pStr + + ; // skip due to escape
else if ( pStr [ 1 ] = = ' " ' )
pStr + + ; // skip due to escape
}
else if ( pStr [ 0 ] = = 0 )
2021-11-27 19:55:55 +00:00
{
2013-08-09 13:04:20 +00:00
Error = 1 ;
2021-11-27 19:55:55 +00:00
break ;
}
2013-08-09 13:04:20 +00:00
2020-04-28 06:54:24 +00:00
* pDst = * pStr ;
pDst + + ;
2013-08-09 13:04:20 +00:00
pStr + + ;
}
2021-11-27 19:55:55 +00:00
if ( ! Error )
{
// write null termination
* pDst = 0 ;
2020-04-28 06:54:24 +00:00
2021-11-27 19:55:55 +00:00
pStr + + ;
2013-08-12 21:02:39 +00:00
2021-11-27 19:55:55 +00:00
for ( Victim = 0 ; Victim < MAX_CLIENTS ; Victim + + )
if ( str_comp ( pName , Server ( ) - > ClientName ( Victim ) ) = = 0 )
break ;
}
2013-08-09 13:04:20 +00:00
}
else
{
pName = pStr ;
2022-02-14 23:12:52 +00:00
while ( true )
2013-08-09 13:04:20 +00:00
{
2013-08-10 02:30:59 +00:00
if ( pStr [ 0 ] = = 0 )
{
Error = 1 ;
break ;
}
2013-08-09 13:04:20 +00:00
if ( pStr [ 0 ] = = ' ' )
{
2013-08-12 21:02:39 +00:00
pStr [ 0 ] = 0 ;
for ( Victim = 0 ; Victim < MAX_CLIENTS ; Victim + + )
2020-09-26 19:41:58 +00:00
if ( str_comp ( pName , Server ( ) - > ClientName ( Victim ) ) = = 0 )
2013-08-12 21:02:39 +00:00
break ;
pStr [ 0 ] = ' ' ;
2020-09-26 19:41:58 +00:00
if ( Victim < MAX_CLIENTS )
2013-08-12 21:02:39 +00:00
break ;
2013-08-09 13:04:20 +00:00
}
pStr + + ;
}
}
if ( pStr [ 0 ] ! = ' ' )
{
Error = 1 ;
}
* pStr = 0 ;
pStr + + ;
pMessage = pStr ;
char aBuf [ 256 ] ;
2020-09-26 19:41:58 +00:00
if ( Error )
2013-08-09 13:04:20 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " Invalid whisper " ) ;
SendChatTarget ( ClientID , aBuf ) ;
return ;
}
2020-09-26 19:41:58 +00:00
if ( Victim > = MAX_CLIENTS | | ! CheckClientID2 ( Victim ) )
2013-08-09 13:04:20 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " No player with name \" %s \" found " , pName ) ;
SendChatTarget ( ClientID , aBuf ) ;
return ;
}
2013-10-18 09:42:35 +00:00
WhisperID ( ClientID , Victim , pMessage ) ;
}
2020-06-12 13:14:56 +00:00
void CGameContext : : WhisperID ( int ClientID , int VictimID , const char * pMessage )
2013-10-18 09:42:35 +00:00
{
2020-05-22 15:58:41 +00:00
if ( ! CheckClientID2 ( ClientID ) )
2013-10-18 09:42:35 +00:00
return ;
2020-05-22 15:58:41 +00:00
if ( ! CheckClientID2 ( VictimID ) )
2013-10-18 09:42:35 +00:00
return ;
2020-05-22 15:58:41 +00:00
if ( m_apPlayers [ ClientID ] )
2014-05-18 23:57:52 +00:00
m_apPlayers [ ClientID ] - > m_LastWhisperTo = VictimID ;
2013-10-18 09:42:35 +00:00
2020-09-18 15:37:27 +00:00
char aCensoredMessage [ 256 ] ;
CensorMessage ( aCensoredMessage , pMessage , sizeof ( aCensoredMessage ) ) ;
2013-10-18 09:42:35 +00:00
char aBuf [ 256 ] ;
2020-06-12 13:14:56 +00:00
if ( Server ( ) - > IsSixup ( ClientID ) )
{
protocol7 : : CNetMsg_Sv_Chat Msg ;
Msg . m_ClientID = ClientID ;
Msg . m_Mode = protocol7 : : CHAT_WHISPER ;
2020-09-18 15:37:27 +00:00
Msg . m_pMessage = aCensoredMessage ;
2020-06-12 13:14:56 +00:00
Msg . m_TargetID = VictimID ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2020-06-12 13:14:56 +00:00
}
else if ( GetClientVersion ( ClientID ) > = VERSION_DDNET_WHISPER )
2014-01-30 15:49:15 +00:00
{
CNetMsg_Sv_Chat Msg ;
Msg . m_Team = CHAT_WHISPER_SEND ;
Msg . m_ClientID = VictimID ;
2020-09-18 15:37:27 +00:00
Msg . m_pMessage = aCensoredMessage ;
2014-09-26 00:40:58 +00:00
if ( g_Config . m_SvDemoChat )
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
else
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , ClientID ) ;
2014-09-26 00:40:58 +00:00
}
else
2014-01-30 15:49:15 +00:00
{
2020-09-18 15:37:27 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " [→ %s] %s " , Server ( ) - > ClientName ( VictimID ) , aCensoredMessage ) ;
2014-01-30 15:49:15 +00:00
SendChatTarget ( ClientID , aBuf ) ;
}
2013-08-09 13:04:20 +00:00
2020-06-12 13:14:56 +00:00
if ( Server ( ) - > IsSixup ( VictimID ) )
{
protocol7 : : CNetMsg_Sv_Chat Msg ;
Msg . m_ClientID = ClientID ;
Msg . m_Mode = protocol7 : : CHAT_WHISPER ;
2020-09-18 15:37:27 +00:00
Msg . m_pMessage = aCensoredMessage ;
2020-06-12 13:14:56 +00:00
Msg . m_TargetID = VictimID ;
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL | MSGFLAG_NORECORD , VictimID ) ;
2020-06-12 13:14:56 +00:00
}
else if ( GetClientVersion ( VictimID ) > = VERSION_DDNET_WHISPER )
2014-01-30 15:49:15 +00:00
{
CNetMsg_Sv_Chat Msg2 ;
Msg2 . m_Team = CHAT_WHISPER_RECV ;
Msg2 . m_ClientID = ClientID ;
2020-09-18 15:37:27 +00:00
Msg2 . m_pMessage = aCensoredMessage ;
2014-09-26 00:40:58 +00:00
if ( g_Config . m_SvDemoChat )
Server ( ) - > SendPackMsg ( & Msg2 , MSGFLAG_VITAL , VictimID ) ;
else
2020-09-26 19:41:58 +00:00
Server ( ) - > SendPackMsg ( & Msg2 , MSGFLAG_VITAL | MSGFLAG_NORECORD , VictimID ) ;
2014-09-26 00:40:58 +00:00
}
else
2014-01-30 15:49:15 +00:00
{
2020-09-18 15:37:27 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " [← %s] %s " , Server ( ) - > ClientName ( ClientID ) , aCensoredMessage ) ;
2014-01-30 15:49:15 +00:00
SendChatTarget ( VictimID , aBuf ) ;
}
2013-08-09 13:04:20 +00:00
}
2013-10-18 09:42:35 +00:00
void CGameContext : : Converse ( int ClientID , char * pStr )
{
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
2020-09-26 19:41:58 +00:00
if ( ! pPlayer )
2013-10-18 09:42:35 +00:00
return ;
2014-04-23 22:43:49 +00:00
if ( ProcessSpamProtection ( ClientID ) )
return ;
2020-09-26 19:41:58 +00:00
if ( pPlayer - > m_LastWhisperTo < 0 )
2013-10-18 09:42:35 +00:00
SendChatTarget ( ClientID , " You do not have an ongoing conversation. Whisper to someone to start one " ) ;
else
{
WhisperID ( ClientID , pPlayer - > m_LastWhisperTo , pStr ) ;
}
}
2019-02-04 19:46:42 +00:00
2019-02-11 17:52:40 +00:00
bool CGameContext : : IsVersionBanned ( int Version )
2019-02-04 19:46:42 +00:00
{
char aVersion [ 16 ] ;
str_format ( aVersion , sizeof ( aVersion ) , " %d " , Version ) ;
2019-02-11 17:52:40 +00:00
return str_in_list ( g_Config . m_SvBannedVersions , " , " , aVersion ) ;
2019-02-04 19:46:42 +00:00
}
2013-12-31 05:13:57 +00:00
2017-03-21 10:24:44 +00:00
void CGameContext : : List ( int ClientID , const char * pFilter )
2013-12-31 05:13:57 +00:00
{
2017-03-21 10:24:44 +00:00
int Total = 0 ;
char aBuf [ 256 ] ;
int Bufcnt = 0 ;
2020-09-26 19:41:58 +00:00
if ( pFilter [ 0 ] )
2017-03-21 10:24:44 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Listing players with \" %s \" in name: " , pFilter ) ;
2013-12-31 05:13:57 +00:00
else
2017-07-26 01:58:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Listing all players: " ) ;
2017-03-21 10:24:44 +00:00
SendChatTarget ( ClientID , aBuf ) ;
2013-12-31 05:13:57 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_apPlayers [ i ] )
{
2017-03-21 10:24:44 +00:00
Total + + ;
const char * pName = Server ( ) - > ClientName ( i ) ;
2021-06-28 20:51:14 +00:00
if ( str_utf8_find_nocase ( pName , pFilter ) = = NULL )
2013-12-31 05:13:57 +00:00
continue ;
2020-09-26 19:41:58 +00:00
if ( Bufcnt + str_length ( pName ) + 4 > 256 )
2013-12-31 05:13:57 +00:00
{
2017-03-21 10:24:44 +00:00
SendChatTarget ( ClientID , aBuf ) ;
Bufcnt = 0 ;
2013-12-31 05:13:57 +00:00
}
2020-09-26 19:41:58 +00:00
if ( Bufcnt ! = 0 )
2013-12-31 05:13:57 +00:00
{
2017-03-21 10:24:44 +00:00
str_format ( & aBuf [ Bufcnt ] , sizeof ( aBuf ) - Bufcnt , " , %s " , pName ) ;
Bufcnt + = 2 + str_length ( pName ) ;
2013-12-31 05:13:57 +00:00
}
else
{
2017-03-21 10:24:44 +00:00
str_format ( & aBuf [ Bufcnt ] , sizeof ( aBuf ) - Bufcnt , " %s " , pName ) ;
Bufcnt + = str_length ( pName ) ;
2013-12-31 05:13:57 +00:00
}
}
}
2020-09-26 19:41:58 +00:00
if ( Bufcnt ! = 0 )
2017-03-21 10:24:44 +00:00
SendChatTarget ( ClientID , aBuf ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %d players online " , Total ) ;
SendChatTarget ( ClientID , aBuf ) ;
2013-12-31 05:13:57 +00:00
}
2017-06-06 05:31:56 +00:00
2021-02-08 21:26:26 +00:00
int CGameContext : : GetClientVersion ( int ClientID ) const
2019-12-21 13:35:09 +00:00
{
2020-05-22 15:58:41 +00:00
IServer : : CClientInfo Info = { 0 } ;
Server ( ) - > GetClientInfo ( ClientID , & Info ) ;
return Info . m_DDNetVersion ;
2017-06-06 05:31:56 +00:00
}
2018-01-05 11:04:06 +00:00
2021-02-08 21:26:26 +00:00
bool CGameContext : : PlayerModerating ( ) const
2018-01-05 11:04:06 +00:00
{
2022-01-23 17:56:37 +00:00
return std : : any_of ( std : : begin ( m_apPlayers ) , std : : end ( m_apPlayers ) , [ ] ( const CPlayer * pPlayer ) { return pPlayer & & pPlayer - > m_Moderating ; } ) ;
2018-01-05 11:04:06 +00:00
}
2018-01-18 15:17:23 +00:00
void CGameContext : : ForceVote ( int EnforcerID , bool Success )
{
// check if there is a vote running
2018-01-25 18:33:40 +00:00
if ( ! m_VoteCloseTime )
2018-01-18 15:17:23 +00:00
return ;
2018-10-07 22:59:07 +00:00
2018-01-18 15:17:23 +00:00
m_VoteEnforce = Success ? CGameContext : : VOTE_ENFORCE_YES_ADMIN : CGameContext : : VOTE_ENFORCE_NO_ADMIN ;
m_VoteEnforcer = EnforcerID ;
2018-10-07 22:59:07 +00:00
2018-01-18 15:17:23 +00:00
char aBuf [ 256 ] ;
2018-01-18 17:41:37 +00:00
const char * pOption = Success ? " yes " : " no " ;
2018-04-07 14:51:17 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " authorized player forced vote %s " , pOption ) ;
2018-01-18 15:17:23 +00:00
SendChatTarget ( - 1 , aBuf ) ;
2018-01-18 17:30:38 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " forcing vote %s " , pOption ) ;
2018-01-18 15:17:23 +00:00
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " server " , aBuf ) ;
}
2020-06-14 08:44:14 +00:00
bool CGameContext : : RateLimitPlayerVote ( int ClientID )
{
2021-06-23 05:05:49 +00:00
int64_t Now = Server ( ) - > Tick ( ) ;
int64_t TickSpeed = Server ( ) - > TickSpeed ( ) ;
2020-06-14 08:44:14 +00:00
CPlayer * pPlayer = m_apPlayers [ ClientID ] ;
if ( g_Config . m_SvRconVote & & ! Server ( ) - > GetAuthedState ( ClientID ) )
{
SendChatTarget ( ClientID , " You can only vote after logging in. " ) ;
return true ;
}
2020-07-07 21:08:46 +00:00
if ( g_Config . m_SvDnsblVote & & Server ( ) - > DistinctClientCount ( ) > 1 )
2020-06-14 08:44:14 +00:00
{
2020-07-07 21:08:46 +00:00
if ( m_pServer - > DnsblPending ( ClientID ) )
{
2020-07-08 20:02:36 +00:00
SendChatTarget ( ClientID , " You are not allowed to vote because we're currently checking for VPNs. Try again in ~30 seconds. " ) ;
2020-07-07 21:08:46 +00:00
return true ;
}
else if ( m_pServer - > DnsblBlack ( ClientID ) )
{
2020-07-08 20:02:31 +00:00
SendChatTarget ( ClientID , " You are not allowed to vote because you appear to be using a VPN. Try connecting without a VPN or contacting an admin if you think this is a mistake. " ) ;
2020-07-07 21:08:46 +00:00
return true ;
}
2020-06-14 08:44:14 +00:00
}
if ( g_Config . m_SvSpamprotection & & pPlayer - > m_LastVoteTry & & pPlayer - > m_LastVoteTry + TickSpeed * 3 > Now )
return true ;
pPlayer - > m_LastVoteTry = Now ;
if ( m_VoteCloseTime )
{
SendChatTarget ( ClientID , " Wait for current vote to end before calling a new one. " ) ;
return true ;
}
if ( Now < pPlayer - > m_FirstVoteTick )
{
char aBuf [ 64 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " You must wait %d seconds before making your first vote. " , ( int ) ( ( pPlayer - > m_FirstVoteTick - Now ) / TickSpeed ) + 1 ) ;
SendChatTarget ( ClientID , aBuf ) ;
return true ;
}
int TimeLeft = pPlayer - > m_LastVoteCall + TickSpeed * g_Config . m_SvVoteDelay - Now ;
if ( pPlayer - > m_LastVoteCall & & TimeLeft > 0 )
{
char aChatmsg [ 64 ] ;
str_format ( aChatmsg , sizeof ( aChatmsg ) , " You must wait %d seconds before making another vote. " , ( int ) ( TimeLeft / TickSpeed ) + 1 ) ;
SendChatTarget ( ClientID , aChatmsg ) ;
return true ;
}
NETADDR Addr ;
Server ( ) - > GetClientAddr ( ClientID , & Addr ) ;
int VoteMuted = 0 ;
for ( int i = 0 ; i < m_NumVoteMutes & & ! VoteMuted ; i + + )
if ( ! net_addr_comp_noport ( & Addr , & m_aVoteMutes [ i ] . m_Addr ) )
VoteMuted = ( m_aVoteMutes [ i ] . m_Expire - Server ( ) - > Tick ( ) ) / Server ( ) - > TickSpeed ( ) ;
2021-06-22 20:45:30 +00:00
for ( int i = 0 ; i < m_NumMutes & & VoteMuted = = 0 ; i + + )
{
if ( ! net_addr_comp_noport ( & Addr , & m_aMutes [ i ] . m_Addr ) )
VoteMuted = ( m_aMutes [ i ] . m_Expire - Server ( ) - > Tick ( ) ) / Server ( ) - > TickSpeed ( ) ;
}
2020-06-14 08:44:14 +00:00
if ( VoteMuted > 0 )
{
char aChatmsg [ 64 ] ;
str_format ( aChatmsg , sizeof ( aChatmsg ) , " You are not permitted to vote for the next %d seconds. " , VoteMuted ) ;
SendChatTarget ( ClientID , aChatmsg ) ;
return true ;
}
return false ;
}
bool CGameContext : : RateLimitPlayerMapVote ( int ClientID )
{
if ( ! Server ( ) - > GetAuthedState ( ClientID ) & & time_get ( ) < m_LastMapVote + ( time_freq ( ) * g_Config . m_SvVoteMapTimeDelay ) )
{
char aChatmsg [ 512 ] = { 0 } ;
str_format ( aChatmsg , sizeof ( aChatmsg ) , " There's a %d second delay between map-votes, please wait %d seconds. " ,
2020-09-26 19:41:58 +00:00
g_Config . m_SvVoteMapTimeDelay , ( int ) ( ( m_LastMapVote + g_Config . m_SvVoteMapTimeDelay * time_freq ( ) - time_get ( ) ) / time_freq ( ) ) ) ;
2020-06-14 08:44:14 +00:00
SendChatTarget ( ClientID , aChatmsg ) ;
return true ;
}
return false ;
}