ddnet/src/game/server/player.cpp

273 lines
7.4 KiB
C++
Raw Normal View History

#include <new>
#include <stdio.h>
#include <engine/server.h>
#include <engine/server/server.h>
#include <engine/shared/config.h>
#include "player.h"
#include "gamecontext.h"
#include <game/gamecore.h>
#include "gamemodes/DDRace.h"
2010-05-29 07:25:38 +00:00
MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)
2010-05-29 07:25:38 +00:00
IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team)
{
2010-05-29 07:25:38 +00:00
m_pGameServer = pGameServer;
m_RespawnTick = Server()->Tick();
m_DieTick = Server()->Tick();
m_ScoreStartTick = Server()->Tick();
2010-05-29 07:25:38 +00:00
Character = 0;
m_Muted = 0;
2010-05-29 07:25:38 +00:00
this->m_ClientID = CID;
m_Team = GameServer()->m_pController->ClampTeam(Team);
2010-07-29 19:55:33 +00:00
m_LastPlaytime = time_get();
m_LastTarget_x = 0;
m_LastTarget_y = 0;
m_SentAfkWarning = 0; // afk timer's 1st warning after 50% of sv_max_afk_time
m_SentAfkWarning2 = 0;
}
2010-05-29 07:25:38 +00:00
CPlayer::~CPlayer()
{
2010-05-29 07:25:38 +00:00
delete Character;
Character = 0;
}
2010-05-29 07:25:38 +00:00
void CPlayer::Tick()
{
int pos=0;
CPlayerScore *pscore = ((CGameControllerDDRace*)GameServer()->m_pController)->m_Score.SearchName(Server()->ClientName(m_ClientID), pos);
if(pscore && pos > -1 && pscore->m_Score != -1)
{
float time = pscore->m_Score;
//if (!config.sv_hide_score)
m_Score = time * 100;
//else
// score=authed;
} else
m_Score = 0.0f;
Server()->SetClientAuthed(m_ClientID, m_Authed);
2010-05-29 07:25:38 +00:00
Server()->SetClientScore(m_ClientID, m_Score);
if(m_Muted > 0) m_Muted--;
// do latency stuff
{
2010-05-29 07:25:38 +00:00
IServer::CClientInfo Info;
if(Server()->GetClientInfo(m_ClientID, &Info))
{
2010-05-29 07:25:38 +00:00
m_Latency.m_Accum += Info.m_Latency;
m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency);
m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency);
}
2010-05-29 07:25:38 +00:00
// each second
if(Server()->Tick()%Server()->TickSpeed() == 0)
{
2010-05-29 07:25:38 +00:00
m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed();
m_Latency.m_Max = m_Latency.m_AccumMax;
m_Latency.m_Min = m_Latency.m_AccumMin;
m_Latency.m_Accum = 0;
m_Latency.m_AccumMin = 1000;
m_Latency.m_AccumMax = 0;
}
}
2008-11-16 14:28:44 +00:00
2010-05-29 07:25:38 +00:00
if(!Character && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
m_Spawning = true;
2008-09-24 14:54:51 +00:00
2010-05-29 07:25:38 +00:00
if(Character)
2008-09-24 14:54:51 +00:00
{
2010-05-29 07:25:38 +00:00
if(Character->IsAlive())
2008-09-24 14:54:51 +00:00
{
2010-05-29 07:25:38 +00:00
m_ViewPos = Character->m_Pos;
2008-09-24 14:54:51 +00:00
}
else
{
2010-05-29 07:25:38 +00:00
delete Character;
Character = 0;
2008-09-24 14:54:51 +00:00
}
}
2010-05-29 07:25:38 +00:00
else if(m_Spawning && m_RespawnTick <= Server()->Tick())
TryRespawn();
}
2010-05-29 07:25:38 +00:00
void CPlayer::Snap(int SnappingClient)
{
2010-05-29 07:25:38 +00:00
CNetObj_ClientInfo *ClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
StrToInts(&ClientInfo->m_Name0, 6, Server()->ClientName(m_ClientID));
StrToInts(&ClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
ClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
ClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
ClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
CNetObj_PlayerInfo *Info = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo)));
Info->m_Latency = m_Latency.m_Min;
Info->m_LatencyFlux = m_Latency.m_Max-m_Latency.m_Min;
Info->m_Local = 0;
Info->m_ClientId = m_ClientID;
Info->m_Score = m_Score;
Info->m_Team = m_Team;
if(m_ClientID == SnappingClient)
Info->m_Local = 1;
}
2010-05-29 07:25:38 +00:00
void CPlayer::OnDisconnect()
{
2010-05-29 07:25:38 +00:00
KillCharacter();
if(Server()->ClientIngame(m_ClientID))
{
char Buf[512];
const char * Name = Server()->ClientName(m_ClientID);
str_format(Buf, sizeof(Buf), "%s has left the game", Name);
2010-05-29 07:25:38 +00:00
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf);
char Cmd[64];
2010-08-07 08:02:58 +00:00
dbg_msg("game", "leave player='%d:%s'", m_ClientID, Name);
if(m_Muted > 0) {
2010-08-07 08:02:58 +00:00
str_format(Cmd, sizeof(Cmd), "ban %d %d '%s'", m_ClientID, m_Muted/Server()->TickSpeed(), "ppc");
GameServer()->Console()->ExecuteLine(Cmd, 3, -1);
}
2010-05-29 07:25:38 +00:00
}
}
2010-05-29 07:25:38 +00:00
void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
{
2010-05-29 07:25:38 +00:00
if(Character)
Character->OnPredictedInput(NewInput);
}
2010-05-29 07:25:38 +00:00
void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
{
2010-05-29 07:25:38 +00:00
if(Character)
Character->OnDirectInput(NewInput);
2010-05-29 07:25:38 +00:00
if(!Character && m_Team >= 0 && (NewInput->m_Fire&1))
m_Spawning = true;
2008-09-09 15:50:41 +00:00
2010-05-29 07:25:38 +00:00
if(!Character && m_Team == -1)
m_ViewPos = vec2(NewInput->m_TargetX, NewInput->m_TargetY);
2010-07-29 19:55:33 +00:00
AfkTimer(NewInput->m_TargetX, NewInput->m_TargetY);
}
2010-05-29 07:25:38 +00:00
CCharacter *CPlayer::GetCharacter()
{
2010-05-29 07:25:38 +00:00
if(Character && Character->IsAlive())
return Character;
return 0;
}
2010-05-29 07:25:38 +00:00
void CPlayer::KillCharacter(int Weapon)
{
2010-05-29 07:25:38 +00:00
if(Character)
{
2010-05-29 07:25:38 +00:00
Character->Die(m_ClientID, Weapon);
delete Character;
Character = 0;
}
}
2010-05-29 07:25:38 +00:00
void CPlayer::Respawn()
{
2010-05-29 07:25:38 +00:00
if(m_Team > -1)
m_Spawning = true;
}
2010-05-29 07:25:38 +00:00
void CPlayer::SetTeam(int Team)
{
// clamp the team
2010-05-29 07:25:38 +00:00
Team = GameServer()->m_pController->ClampTeam(Team);
if(m_Team == Team)
return;
2010-05-29 07:25:38 +00:00
char Buf[512];
str_format(Buf, sizeof(Buf), "%s joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf);
2010-05-29 07:25:38 +00:00
KillCharacter();
2010-05-29 07:25:38 +00:00
m_Team = Team;
// we got to wait 0.5 secs before respawning
m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
dbg_msg("game", "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
//GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
}
2010-05-29 07:25:38 +00:00
void CPlayer::TryRespawn()
{
2010-05-29 07:25:38 +00:00
vec2 SpawnPos = vec2(100.0f, -60.0f);
2010-05-29 07:25:38 +00:00
if(!GameServer()->m_pController->CanSpawn(this, &SpawnPos))
return;
// check if the position is occupado
2010-05-29 07:25:38 +00:00
CEntity *apEnts[2] = {0};
int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, NETOBJTYPE_CHARACTER);
2010-05-29 07:25:38 +00:00
if(NumEnts == 0)
{
2010-05-29 07:25:38 +00:00
m_Spawning = false;
Character = new(m_ClientID) CCharacter(&GameServer()->m_World);
Character->Spawn(this, SpawnPos);
GameServer()->CreatePlayerSpawn(SpawnPos);
}
}
2010-07-29 19:55:33 +00:00
void CPlayer::AfkTimer(int new_target_x, int new_target_y)
{
/*
afk timer (x, y = mouse coordinates)
Since a player has to move the mouse to play, this is a better method than checking
the player's position in the game world, because it can easily be bypassed by just locking a key.
Frozen players could be kicked as well, because they can't move.
It also works for spectators.
*/
if(m_Authed) return; // don't kick admins
if(g_Config.m_SvMaxAfkTime == 0) return; // 0 = disabled
if(new_target_x != m_LastTarget_x || new_target_y != m_LastTarget_y)
2010-07-29 19:55:33 +00:00
{
m_LastPlaytime = time_get();
m_LastTarget_x = new_target_x;
m_LastTarget_y = new_target_y;
m_SentAfkWarning = 0; // afk timer's 1st warning after 50% of sv_max_afk_time
m_SentAfkWarning2 = 0;
}
else
{
// not playing, check how long
if(m_SentAfkWarning == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.5))
{
sprintf(
m_pAfkMsg,
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
(int)(g_Config.m_SvMaxAfkTime*0.5),
g_Config.m_SvMaxAfkTime
);
m_pGameServer->SendChatTarget(m_ClientID, m_pAfkMsg);
2010-07-29 19:55:33 +00:00
m_SentAfkWarning = 1;
} else if(m_SentAfkWarning2 == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.9))
{
sprintf(
m_pAfkMsg,
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
(int)(g_Config.m_SvMaxAfkTime*0.9),
g_Config.m_SvMaxAfkTime
);
m_pGameServer->SendChatTarget(m_ClientID, m_pAfkMsg);
2010-07-29 19:55:33 +00:00
m_SentAfkWarning = 1;
} else if(m_LastPlaytime < time_get()-time_freq()*g_Config.m_SvMaxAfkTime)
2010-07-29 19:55:33 +00:00
{
CServer* serv = (CServer*)m_pGameServer->Server();
serv->Kick(m_ClientID,"Away from keyboard");
2010-07-29 19:55:33 +00:00
}
}
}