ddnet/src/game/server/gamecontext.cpp

2192 lines
67 KiB
C++
Raw Normal View History

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. */
2011-08-31 11:56:04 +00:00
#include <base/tl/sorted_array.h>
2008-09-23 07:43:41 +00:00
#include <new>
2010-05-29 07:25:38 +00:00
#include <base/math.h>
#include <engine/shared/config.h>
#include <engine/map.h>
#include <engine/console.h>
#include "gamecontext.h"
#include <game/version.h>
#include <game/collision.h>
/*#include <game/gamecore.h>
2011-01-29 00:59:50 +00:00
#include "gamemodes/dm.h"
#include "gamemodes/tdm.h"
#include "gamemodes/ctf.h"
#include "gamemodes/mod.h"*/
#include <stdio.h>
#include <string.h>
#include <engine/server/server.h>
#include "gamemodes/DDRace.h"
#include "score.h"
#include "score/file_score.h"
#include <time.h>
#if defined(CONF_SQL)
2010-08-26 13:27:36 +00:00
#include "score/sql_score.h"
#endif
2010-05-29 07:25:38 +00:00
enum
{
RESET,
NO_RESET
};
2010-05-29 07:25:38 +00:00
void CGameContext::Construct(int Resetting)
{
2010-05-29 07:25:38 +00:00
m_Resetting = 0;
m_pServer = 0;
2008-09-23 07:43:41 +00:00
for(int i = 0; i < MAX_CLIENTS; i++)
2010-05-29 07:25:38 +00:00
m_apPlayers[i] = 0;
2010-05-29 07:25:38 +00:00
m_pController = 0;
m_VoteCloseTime = 0;
m_pVoteOptionFirst = 0;
m_pVoteOptionLast = 0;
m_NumVoteOptions = 0;
//m_LockTeams = 0;
2010-05-29 07:25:38 +00:00
if(Resetting==NO_RESET)
2011-02-03 12:02:32 +00:00
{
2010-05-29 07:25:38 +00:00
m_pVoteOptionHeap = new CHeap();
2011-02-23 21:39:53 +00:00
m_pScore = 0;
m_NumMutes = 0;
2011-02-03 12:02:32 +00:00
}
2011-08-31 13:41:32 +00:00
m_ChatResponseTargetID = -1;
2010-05-29 07:25:38 +00:00
}
CGameContext::CGameContext(int Resetting)
{
Construct(Resetting);
}
CGameContext::CGameContext()
{
Construct(NO_RESET);
2008-09-23 07:43:41 +00:00
}
2010-05-29 07:25:38 +00:00
CGameContext::~CGameContext()
2008-09-23 07:43:41 +00:00
{
for(int i = 0; i < MAX_CLIENTS; i++)
2010-05-29 07:25:38 +00:00
delete m_apPlayers[i];
if(!m_Resetting)
delete m_pVoteOptionHeap;
}
2010-05-29 07:25:38 +00:00
void CGameContext::Clear()
{
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;
int NumVoteOptions = m_NumVoteOptions;
2010-05-29 07:25:38 +00:00
CTuningParams Tuning = m_Tuning;
m_Resetting = true;
this->~CGameContext();
2008-09-23 07:43:41 +00:00
mem_zero(this, sizeof(*this));
2010-05-29 07:25:38 +00:00
new (this) CGameContext(RESET);
m_pVoteOptionHeap = pVoteOptionHeap;
m_pVoteOptionFirst = pVoteOptionFirst;
m_pVoteOptionLast = pVoteOptionLast;
m_NumVoteOptions = NumVoteOptions;
2010-05-29 07:25:38 +00:00
m_Tuning = Tuning;
}
class CCharacter *CGameContext::GetPlayerChar(int ClientID)
{
if(ClientID < 0 || ClientID >= MAX_CLIENTS || !m_apPlayers[ClientID])
return 0;
return m_apPlayers[ClientID]->GetCharacter();
}
void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, int Mask)
{
float a = 3 * 3.14159f / 2 + Angle;
//float a = get_angle(dir);
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++)
{
float f = mix(s, e, float(i+1)/float(Amount+2));
CNetEvent_DamageInd *pEvent = (CNetEvent_DamageInd *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(CNetEvent_DamageInd), Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
pEvent->m_Y = (int)Pos.y;
pEvent->m_Angle = (int)(f*256.0f);
}
}
}
void CGameContext::CreateHammerHit(vec2 Pos, int Mask)
{
// create the event
CNetEvent_HammerHit *pEvent = (CNetEvent_HammerHit *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(CNetEvent_HammerHit), Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
pEvent->m_Y = (int)Pos.y;
}
}
void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, int Mask)
{
// create the event
CNetEvent_Explosion *pEvent = (CNetEvent_Explosion *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(CNetEvent_Explosion), Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
pEvent->m_Y = (int)Pos.y;
}
2011-02-23 07:43:05 +00:00
/*
2010-05-29 07:25:38 +00:00
if (!NoDamage)
{
2011-02-23 07:43:05 +00:00
*/
// deal damage
CCharacter *apEnts[MAX_CLIENTS];
2010-05-29 07:25:38 +00:00
float Radius = 135.0f;
float InnerRadius = 48.0f;
int Num = m_World.FindEntities(Pos, Radius, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
2010-05-29 07:25:38 +00:00
for(int i = 0; i < Num; i++)
{
vec2 Diff = apEnts[i]->m_Pos - Pos;
2011-01-29 00:59:50 +00:00
vec2 ForceDir(0,1);
2010-05-29 07:25:38 +00:00
float l = length(Diff);
if(l)
2010-05-29 07:25:38 +00:00
ForceDir = normalize(Diff);
l = 1-clamp((l-InnerRadius)/(Radius-InnerRadius), 0.0f, 1.0f);
float Dmg = 6 * l;
if((int)Dmg)
if((GetPlayerChar(Owner) ? !(GetPlayerChar(Owner)->m_Hit&CCharacter::DISABLE_HIT_GRENADE) : g_Config.m_SvHit || NoDamage) || Owner == apEnts[i]->GetPlayer()->GetCID())
{
2011-01-29 00:59:50 +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;
apEnts[i]->TakeDamage(ForceDir*Dmg*2, (int)Dmg, Owner, Weapon);
if(GetPlayerChar(Owner) ? GetPlayerChar(Owner)->m_Hit&CCharacter::DISABLE_HIT_GRENADE : !g_Config.m_SvHit || NoDamage) break;
}
}
2011-02-23 07:43:05 +00:00
//}
}
/*
void create_smoke(vec2 Pos)
{
// create the event
EV_EXPLOSION *pEvent = (EV_EXPLOSION *)events.create(EVENT_SMOKE, sizeof(EV_EXPLOSION));
if(pEvent)
{
pEvent->x = (int)Pos.x;
pEvent->y = (int)Pos.y;
}
}*/
void CGameContext::CreatePlayerSpawn(vec2 Pos, int Mask)
{
// create the event
CNetEvent_Spawn *ev = (CNetEvent_Spawn *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(CNetEvent_Spawn), Mask);
if(ev)
{
ev->m_X = (int)Pos.x;
ev->m_Y = (int)Pos.y;
}
}
void CGameContext::CreateDeath(vec2 Pos, int ClientID, int Mask)
{
// create the event
CNetEvent_Death *pEvent = (CNetEvent_Death *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(CNetEvent_Death), Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
pEvent->m_Y = (int)Pos.y;
pEvent->m_ClientID = ClientID;
}
}
2010-05-29 07:25:38 +00:00
void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask)
{
2011-01-29 00:59:50 +00:00
if (Sound < 0)
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);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
pEvent->m_Y = (int)Pos.y;
pEvent->m_SoundID = Sound;
}
}
2010-05-29 07:25:38 +00:00
void CGameContext::CreateSoundGlobal(int Sound, int Target)
{
2011-01-29 00:59:50 +00:00
if (Sound < 0)
return;
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_SoundGlobal Msg;
Msg.m_SoundID = Sound;
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);
}
}
2010-05-29 07:25:38 +00:00
void CGameContext::SendChatTarget(int To, const char *pText)
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Chat Msg;
Msg.m_Team = 0;
Msg.m_ClientID = -1;
2010-05-29 07:25:38 +00:00
Msg.m_pMessage = pText;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, To);
}
void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, int SpamProtectionClientID)
{
if(SpamProtectionClientID >= 0 && SpamProtectionClientID < MAX_CLIENTS)
{
2011-02-23 21:39:53 +00:00
if(ProcessSpamProtection(SpamProtectionClientID))
{
SendChatTarget(SpamProtectionClientID, "Muted text:");
SendChatTarget(SpamProtectionClientID, pText);
return;
}
}
char aBuf[256], aText[256];
str_copy(aText, pText, sizeof(aText));
if(ChatterClientID >= 0 && ChatterClientID < MAX_CLIENTS)
str_format(aBuf, sizeof(aBuf), "%d:%d:%s: %s", ChatterClientID, Team, Server()->ClientName(ChatterClientID), aText);
else if(ChatterClientID == -2)
{
str_format(aBuf, sizeof(aBuf), "### %s", aText);
str_copy(aText, aBuf, sizeof(aText));
ChatterClientID = -1;
}
else
str_format(aBuf, sizeof(aBuf), "*** %s", aText);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, Team!=CHAT_ALL?"teamchat":"chat", aBuf);
2010-05-29 07:25:38 +00:00
if(Team == CHAT_ALL)
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Chat Msg;
Msg.m_Team = 0;
Msg.m_ClientID = ChatterClientID;
Msg.m_pMessage = aText;
2010-05-29 07:25:38 +00:00
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
}
else
{
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;
Msg.m_ClientID = ChatterClientID;
Msg.m_pMessage = aText;
// pack one for the recording only
2010-05-29 07:25:38 +00:00
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NOSEND, -1);
2011-01-29 00:59:50 +00:00
// send to the clients
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_apPlayers[i] != 0) {
if(Team == CHAT_SPEC) {
if(m_apPlayers[i]->GetTeam() == CHAT_SPEC) {
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i);
}
} else {
2011-01-17 00:01:11 +00:00
if(Teams->Team(i) == Team && m_apPlayers[i]->GetTeam() != CHAT_SPEC) {
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, i);
}
}
}
}
}
}
void CGameContext::SendEmoticon(int ClientID, int Emoticon)
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Emoticon Msg;
Msg.m_ClientID = ClientID;
2010-05-29 07:25:38 +00:00
Msg.m_Emoticon = Emoticon;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
}
void CGameContext::SendWeaponPickup(int ClientID, int Weapon)
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_WeaponPickup Msg;
Msg.m_Weapon = Weapon;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
}
void CGameContext::SendBroadcast(const char *pText, int ClientID)
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_Broadcast Msg;
Msg.m_pMessage = pText;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
}
//
void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason)
2008-09-24 14:47:03 +00:00
{
// check if a vote is already running
2010-05-29 07:25:38 +00:00
if(m_VoteCloseTime)
2008-09-24 14:47:03 +00:00
return;
// 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;
2008-09-24 14:47:03 +00:00
for(int i = 0; i < MAX_CLIENTS; i++)
{
2010-05-29 07:25:38 +00:00
if(m_apPlayers[i])
{
m_apPlayers[i]->m_Vote = 0;
m_apPlayers[i]->m_VotePos = 0;
}
2008-09-24 14:47:03 +00:00
}
2008-09-24 14:47:03 +00:00
// start vote
2010-05-29 07:25:38 +00:00
m_VoteCloseTime = time_get() + time_freq()*25;
str_copy(m_aVoteDescription, pDesc, sizeof(m_aVoteDescription));
str_copy(m_aVoteCommand, pCommand, sizeof(m_aVoteCommand));
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
}
2008-09-25 12:41:37 +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
}
void CGameContext::SendVoteSet(int ClientID)
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
CNetMsg_Sv_VoteSet Msg;
if(m_VoteCloseTime)
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
Msg.m_Timeout = (m_VoteCloseTime-time_get())/time_freq();
Msg.m_pDescription = m_aVoteDescription;
Msg.m_pReason = m_aVoteReason;
2008-09-24 14:47:03 +00:00
}
else
{
2010-05-29 07:25:38 +00:00
Msg.m_Timeout = 0;
Msg.m_pDescription = "";
Msg.m_pReason = "";
2008-09-24 14:47:03 +00:00
}
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
2008-09-24 14:47:03 +00:00
}
void CGameContext::SendVoteStatus(int ClientID, int Total, int Yes, int No)
2008-09-24 14:47:03 +00:00
{
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;
Msg.m_Pass = Total - (Yes+No);
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
2010-05-29 07:25:38 +00:00
}
void CGameContext::AbortVoteKickOnDisconnect(int ClientID)
2010-05-29 07:25:38 +00:00
{
if(m_VoteCloseTime && ((!str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientID) ||
(!str_comp_num(m_aVoteCommand, "set_team ", 9) && str_toint(&m_aVoteCommand[9]) == ClientID)))
2010-05-29 07:25:38 +00:00
m_VoteCloseTime = -1;
}
void CGameContext::CheckPureTuning()
{
// might not be created yet during start up
if(!m_pController)
return;
2010-05-29 07:25:38 +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
{
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
}
}
2008-09-24 14:47:03 +00:00
}
void CGameContext::SendTuningParams(int ClientID)
{
2010-05-29 07:25:38 +00:00
CheckPureTuning();
2010-05-29 07:25:38 +00:00
CMsgPacker Msg(NETMSGTYPE_SV_TUNEPARAMS);
int *pParams = (int *)&m_Tuning;
for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++)
Msg.AddInt(pParams[i]);
Server()->SendMsg(&Msg, MSGFLAG_VITAL, ClientID);
}
/*
void CGameContext::SwapTeams()
{
if(!m_pController->IsTeamplay())
return;
SendChat(-1, CGameContext::CHAT_ALL, "Teams were swapped");
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
m_apPlayers[i]->SetTeam(m_apPlayers[i]->GetTeam()^1, false);
}
(void)m_pController->CheckTeamBalance();
}
*/
2010-05-29 07:25:38 +00:00
void CGameContext::OnTick()
{
2010-05-29 07:25:38 +00:00
// check tuning
CheckPureTuning();
// copy tuning
m_World.m_Core.m_Tuning = m_Tuning;
m_World.Tick();
//if(world.paused) // make sure that the game object always updates
2010-05-29 07:25:38 +00:00
m_pController->Tick();
for(int i = 0; i < MAX_CLIENTS; i++)
{
2010-05-29 07:25:38 +00:00
if(m_apPlayers[i])
{
2010-05-29 07:25:38 +00:00
m_apPlayers[i]->Tick();
m_apPlayers[i]->PostTick();
}
}
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
{
// abort the kick-vote on player-leave
2010-05-29 07:25:38 +00:00
if(m_VoteCloseTime == -1)
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
SendChat(-1, CGameContext::CHAT_ALL, "Vote aborted");
EndVote();
}
else
{
2010-05-29 07:25:38 +00:00
int Total = 0, Yes = 0, No = 0;
if(m_VoteUpdate)
2008-09-24 14:47:03 +00:00
{
2010-05-29 07:25:38 +00:00
// count votes
char aaBuf[MAX_CLIENTS][NETADDR_MAXSTRSIZE] = {{0}};
2010-05-29 07:25:38 +00:00
for(int i = 0; i < MAX_CLIENTS; i++)
if(m_apPlayers[i])
Server()->GetClientAddr(i, aaBuf[i], NETADDR_MAXSTRSIZE);
2010-05-29 07:25:38 +00:00
bool aVoteChecked[MAX_CLIENTS] = {0};
for(int i = 0; i < MAX_CLIENTS; i++)
{
//if(!m_apPlayers[i] || m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS || aVoteChecked[i]) // don't count in votes by spectators
if(!m_apPlayers[i] ||
(g_Config.m_SvSpectatorVotes == 0 &&
m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS) ||
aVoteChecked[i]) // don't count in votes by spectators if the admin doesn't want it
2010-05-29 07:25:38 +00:00
continue;
if(m_VoteKick &&
2010-09-14 16:58:18 +00:00
GetPlayerChar(m_VoteCreator) && GetPlayerChar(i) &&
GetPlayerChar(m_VoteCreator)->Team() != GetPlayerChar(i)->Team())
2010-05-29 07:25:38 +00:00
continue;
2010-05-29 07:25:38 +00:00
int ActVote = m_apPlayers[i]->m_Vote;
int ActVotePos = m_apPlayers[i]->m_VotePos;
2010-05-29 07:25: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)
{
if(!m_apPlayers[j] || aVoteChecked[j] || str_comp(aaBuf[j], aaBuf[i]))
continue;
aVoteChecked[j] = true;
if(m_apPlayers[j]->m_Vote && (!ActVote || ActVotePos > m_apPlayers[j]->m_VotePos))
{
ActVote = m_apPlayers[j]->m_Vote;
ActVotePos = m_apPlayers[j]->m_VotePos;
}
}
Total++;
if(ActVote > 0)
Yes++;
else if(ActVote < 0)
No++;
}
2010-05-29 07:25:38 +00:00
//if(Yes >= Total/2+1)
if(Yes > Total / (100.0 / g_Config.m_SvVoteYesPercentage))
2010-05-29 07:25:38 +00:00
m_VoteEnforce = VOTE_ENFORCE_YES;
//else if(No >= (Total+1)/2)
else if(No >= Total - Total / (100.0 / g_Config.m_SvVoteYesPercentage))
2010-05-29 07:25:38 +00:00
m_VoteEnforce = VOTE_ENFORCE_NO;
m_VoteWillPass = Yes > (Yes + No) / (100.0 / g_Config.m_SvVoteYesPercentage);
2008-09-24 14:47:03 +00:00
}
if(time_get() > m_VoteCloseTime && !g_Config.m_SvVoteMajority)
m_VoteEnforce = (m_VoteWillPass) ? VOTE_ENFORCE_YES : VOTE_ENFORCE_NO;
2010-05-29 07:25:38 +00:00
if(m_VoteEnforce == VOTE_ENFORCE_YES)
{
Server()->SetRconCID(IServer::RCON_CID_VOTE);
Console()->ExecuteLine(m_aVoteCommand);
Server()->SetRconCID(IServer::RCON_CID_SERV);
2010-10-11 11:10:39 +00:00
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
2010-05-29 07:25:38 +00:00
if(m_apPlayers[m_VoteCreator])
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];
str_format(aBuf, sizeof(aBuf),"Vote passed enforced by server administrator");
Console()->ExecuteLine(m_aVoteCommand, m_VoteEnforcer);
2010-10-11 11:10:39 +00:00
SendChat(-1, CGameContext::CHAT_ALL, aBuf);
EndVote();
}
else if(m_VoteEnforce == VOTE_ENFORCE_NO_ADMIN)
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf),"Vote failed enforced by server administrator");
2010-10-11 11:10:39 +00:00
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, aBuf);
}
//else if(m_VoteEnforce == VOTE_ENFORCE_NO || time_get() > m_VoteCloseTime)
else if(m_VoteEnforce == VOTE_ENFORCE_NO || (time_get() > m_VoteCloseTime && g_Config.m_SvVoteMajority))
2010-05-29 07:25:38 +00:00
{
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote failed");
}
else if(m_VoteUpdate)
{
m_VoteUpdate = false;
SendVoteStatus(-1, Total, Yes, No);
}
}
}
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];
}
}
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
{
2011-02-23 21:39:53 +00:00
char *Line = ((CServer *) Server())->GetAnnouncementLine(g_Config.m_SvAnnouncementFileName);
if(Line)
SendChat(-1, CGameContext::CHAT_ALL, Line);
}
if(Collision()->m_NumSwitchers > 0)
for (int i = 0; i < Collision()->m_NumSwitchers+1; ++i)
2010-11-22 20:43:22 +00:00
{
2011-02-23 21:39:53 +00:00
for (int j = 0; j < 16; ++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
}
}
2010-05-29 07:25:38 +00:00
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
for(int i = 0; i < g_Config.m_DbgDummies ; i++)
{
CNetObj_PlayerInput Input = {0};
Input.m_Direction = (i&1)?-1:1;
m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input);
}
}
#endif
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);
}
void CGameContext::OnClientPredictedInput(int ClientID, void *pInput)
{
if(!m_World.m_Paused)
m_apPlayers[ClientID]->OnPredictedInput((CNetObj_PlayerInput *)pInput);
}
void CGameContext::OnClientEnter(int ClientID)
2010-05-29 07:25:38 +00:00
{
//world.insert_entity(&players[client_id]);
m_apPlayers[ClientID]->Respawn();
// init the player
Score()->PlayerData(ClientID)->Reset();
Score()->LoadScore(ClientID);
Score()->PlayerData(ClientID)->m_CurrentTime = Score()->PlayerData(ClientID)->m_BestTime;
m_apPlayers[ClientID]->m_Score = (Score()->PlayerData(ClientID)->m_BestTime)?Score()->PlayerData(ClientID)->m_BestTime:-9999;
if(((CServer *) Server())->m_aPrevStates[ClientID] < CServer::CClient::STATE_INGAME)
{
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientID), m_pController->GetTeamName(m_apPlayers[ClientID]->GetTeam()));
SendChat(-1, CGameContext::CHAT_ALL, aBuf);
SendChatTarget(ClientID, "DDRace Mod. Version: " GAME_VERSION);
SendChatTarget(ClientID, "please visit http://DDRace.info or say /info for more info");
2011-08-26 06:09:51 +00:00
if(g_Config.m_SvWelcome[0]!=0)
SendChatTarget(ClientID,g_Config.m_SvWelcome);
str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientID, Server()->ClientName(ClientID), m_apPlayers[ClientID]->GetTeam());
2010-05-29 07:25:38 +00:00
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
time_t rawtime;
struct tm* timeinfo;
char d[16], m [16], y[16];
int dd, mm, yy;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
strftime (d,sizeof(y),"%d",timeinfo);
strftime (m,sizeof(m),"%m",timeinfo);
strftime (y,sizeof(y),"%Y",timeinfo);
dd = atoi(d);
mm = atoi(m);
yy = atoi(y);
if((mm == 12 && dd >= 20))
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "Happy %d from GreYFoX", yy+1);
SendBroadcast(aBuf, ClientID);
}
else if(mm == 1 && dd <= 20)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "Happy %d from GreYFoX", yy);
SendBroadcast(aBuf, ClientID);
}
}
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true;
2011-08-26 18:03:30 +00:00
2011-08-26 18:23:47 +00:00
m_apPlayers[ClientID]->m_Authed = ((CServer*)Server())->m_aClients[ClientID].m_Authed;
2010-05-29 07:25:38 +00:00
}
void CGameContext::OnClientConnected(int ClientID)
2010-05-29 07:25:38 +00:00
{
// Check which team the player should be on
const int StartTeam = g_Config.m_SvTournamentMode ? TEAM_SPECTATORS : m_pController->GetAutoTeam(ClientID);
2010-05-29 07:25:38 +00:00
m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, StartTeam);
2010-05-29 07:25:38 +00:00
//players[client_id].init(client_id);
//players[client_id].client_id = client_id;
//(void)m_pController->CheckTeamBalance();
2010-05-29 07:25:38 +00:00
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
if(ClientID >= MAX_CLIENTS-g_Config.m_DbgDummies)
2010-05-29 07:25:38 +00:00
return;
}
#endif
// send active vote
if(m_VoteCloseTime)
SendVoteSet(ClientID);
2010-05-29 07:25:38 +00:00
// send motd
CNetMsg_Sv_Motd Msg;
Msg.m_pMessage = g_Config.m_SvMotd;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
2010-05-29 07:25:38 +00:00
}
void CGameContext::OnClientDrop(int ClientID, const char *pReason)
2010-05-29 07:25:38 +00:00
{
AbortVoteKickOnDisconnect(ClientID);
m_apPlayers[ClientID]->OnDisconnect(pReason);
delete m_apPlayers[ClientID];
m_apPlayers[ClientID] = 0;
//(void)m_pController->CheckTeamBalance();
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true;
// update spectator modes
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(m_apPlayers[i] && m_apPlayers[i]->m_SpectatorID == ClientID)
m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
}
2010-05-29 07:25:38 +00:00
}
void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
2010-05-29 07:25:38 +00:00
{
void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgID, pUnpacker);
CPlayer *pPlayer = m_apPlayers[ClientID];
2010-05-29 07:25:38 +00:00
if(!pRawMsg)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgID), MsgID, m_NetObjHandler.FailedMsgOn());
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
2010-05-29 07:25:38 +00:00
return;
}
if(MsgID == NETMSGTYPE_CL_SAY)
2010-05-29 07:25:38 +00:00
{
CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg;
2010-10-07 12:10:49 +00:00
int Team = pMsg->m_Team;
/*if(Team)
Team = pPlayer->GetTeam();
2011-01-29 00:59:50 +00:00
else
Team = CGameContext::CHAT_ALL;
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick())
2011-01-29 00:59:50 +00:00
return;
pPlayer->m_LastChat = Server()->Tick();*/
int GameTeam = ((CGameControllerDDRace*)m_pController)->m_Teams.m_Core.Team(pPlayer->GetCID());
if(Team)
Team = ((pPlayer->GetTeam() == -1) ? CHAT_SPEC : GameTeam);
else
2010-10-07 12:10:49 +00:00
Team = CHAT_ALL;
2011-12-26 09:15:43 +00:00
/*
if(str_length(pMsg->m_pMessage)>370)
{
SendChatTarget(ClientID, "Your Message is too long");
return;
2011-12-26 09:15:43 +00:00
} if it's needed someone will report it! :D, i can't check from here so...*/
2010-05-29 07:25:38 +00:00
// check for invalid chars
unsigned char *pMessage = (unsigned char *)pMsg->m_pMessage;
while (*pMessage)
{
if(*pMessage < 32)
*pMessage = ' ';
pMessage++;
}
2010-09-09 13:32:14 +00:00
if(pMsg->m_pMessage[0]=='/')
{
2011-08-31 13:41:32 +00:00
m_ChatResponseTargetID = ClientID;
Console()->SetFlagMask(CFGFLAG_CHAT);
if (pPlayer->m_Authed)
Console()->SetAccessLevel(pPlayer->m_Authed == CServer::AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD);
else
Console()->SetAccessLevel(IConsole::ACCESS_LEVEL_USER);
Console()->SetPrintOutputLevel(m_ChatPrintCBIndex, 0);
2011-08-31 13:41:32 +00:00
Console()->ExecuteLine(pMsg->m_pMessage + 1, ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "chat-command", pMsg->m_pMessage);
Console()->SetAccessLevel(IConsole::ACCESS_LEVEL_ADMIN);
2011-08-31 13:41:32 +00:00
Console()->SetFlagMask(CFGFLAG_SERVER);
m_ChatResponseTargetID = -1;
2010-09-09 13:32:14 +00:00
}
else
SendChat(ClientID, Team, pMsg->m_pMessage, ClientID);
}
else if(MsgID == NETMSGTYPE_CL_CALLVOTE)
2010-05-29 07:25:38 +00:00
{
if(g_Config.m_SvSpamprotection && pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry+Server()->TickSpeed()*3 > Server()->Tick())
2010-05-29 07:25:38 +00:00
return;
int64 Now = Server()->Tick();
pPlayer->m_LastVoteTry = Now;
//if(pPlayer->GetTeam() == TEAM_SPECTATORS)
if(g_Config.m_SvSpectatorVotes == 0 && pPlayer->GetTeam() == TEAM_SPECTATORS)
2010-08-06 19:03:38 +00:00
{
SendChatTarget(ClientID, "Spectators aren't allowed to start a vote.");
2010-08-06 19:03:38 +00:00
return;
}
2010-05-29 07:25:38 +00:00
if(m_VoteCloseTime)
{
SendChatTarget(ClientID, "Wait for current vote to end before calling a new one.");
2010-05-29 07:25:38 +00:00
return;
}
int Timeleft = pPlayer->m_LastVoteCall + Server()->TickSpeed()*60 - Now;
if(pPlayer->m_LastVoteCall && Timeleft > 0)
2010-05-29 07:25:38 +00:00
{
char aChatmsg[512] = {0};
str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d seconds before making another vote", (Timeleft/Server()->TickSpeed())+1);
SendChatTarget(ClientID, aChatmsg);
2010-05-29 07:25:38 +00:00
return;
}
2010-05-29 07:25:38 +00:00
char aChatmsg[512] = {0};
2011-03-26 16:44:34 +00:00
char aDesc[VOTE_DESC_LENGTH] = {0};
char aCmd[VOTE_CMD_LENGTH] = {0};
2010-05-29 07:25:38 +00:00
CNetMsg_Cl_CallVote *pMsg = (CNetMsg_Cl_CallVote *)pRawMsg;
const char *pReason = pMsg->m_Reason[0] ? pMsg->m_Reason : "No reason given";
2010-05-29 07:25:38 +00:00
if(str_comp_nocase(pMsg->m_Type, "option") == 0)
{
2011-03-26 16:44:34 +00:00
CVoteOptionServer *pOption = m_pVoteOptionFirst;
static int64 LastMapVote = 0;
2010-05-29 07:25:38 +00:00
while(pOption)
{
2011-03-25 08:49:21 +00:00
if(str_comp_nocase(pMsg->m_Value, pOption->m_aDescription) == 0)
2010-05-29 07:25:38 +00:00
{
if(!Console()->LineIsValid(pOption->m_aCommand))
{
SendChatTarget(ClientID, "Invalid option");
return;
}
if(!m_apPlayers[ClientID]->m_Authed && (strncmp(pOption->m_aCommand, "sv_map ", 7) == 0 || strncmp(pOption->m_aCommand, "change_map ", 11) == 0) && time_get() < LastMapVote + (time_freq() * g_Config.m_SvVoteMapTimeDelay))
{
char chatmsg[512] = {0};
str_format(chatmsg, sizeof(chatmsg), "There's a %d second delay between map-votes,Please wait %d Second(s)", g_Config.m_SvVoteMapTimeDelay,((LastMapVote+(g_Config.m_SvVoteMapTimeDelay * time_freq()))/time_freq())-(time_get()/time_freq()));
SendChatTarget(ClientID, chatmsg);
return;
}
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", Server()->ClientName(ClientID),
pOption->m_aDescription, pReason);
str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aDescription);
2010-05-29 07:25:38 +00:00
str_format(aCmd, sizeof(aCmd), "%s", pOption->m_aCommand);
LastMapVote = time_get();
2010-05-29 07:25:38 +00:00
break;
}
pOption = pOption->m_pNext;
}
2010-05-29 07:25:38 +00:00
if(!pOption)
{
if (!pPlayer->m_Authed) // allow admins to call any vote they want
2010-10-11 09:18:44 +00:00
{
str_format(aChatmsg, sizeof(aChatmsg), "'%s' isn't an option on this server", pMsg->m_Value);
SendChatTarget(ClientID, aChatmsg);
2010-10-11 09:18:44 +00:00
return;
}
else
{
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s'", Server()->ClientName(ClientID), pMsg->m_Value);
2010-10-11 09:18:44 +00:00
str_format(aDesc, sizeof(aDesc), "%s", pMsg->m_Value);
str_format(aCmd, sizeof(aCmd), "%s", pMsg->m_Value);
}
}
2011-01-29 00:59:50 +00:00
LastMapVote = time_get();
m_VoteKick = false;
2010-05-29 07:25:38 +00:00
}
else if(str_comp_nocase(pMsg->m_Type, "kick") == 0)
{
if(!m_apPlayers[ClientID]->m_Authed && time_get() < m_apPlayers[ClientID]->m_Last_KickVote + (time_freq() * 5))
2011-01-29 00:59:50 +00:00
return;
else if(!m_apPlayers[ClientID]->m_Authed && time_get() < m_apPlayers[ClientID]->m_Last_KickVote + (time_freq() * g_Config.m_SvVoteKickTimeDelay))
2010-07-29 19:55:33 +00:00
{
char chatmsg[512] = {0};
str_format(chatmsg, sizeof(chatmsg), "There's a %d second wait time between kick votes for each player please wait %d second(s)",
g_Config.m_SvVoteKickTimeDelay,
((m_apPlayers[ClientID]->m_Last_KickVote + (m_apPlayers[ClientID]->m_Last_KickVote*time_freq()))/time_freq())-(time_get()/time_freq())
2010-07-29 19:55:33 +00:00
);
SendChatTarget(ClientID, chatmsg);
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
2010-07-29 19:55:33 +00:00
return;
}
//else if(!g_Config.m_SvVoteKick)
else if(!g_Config.m_SvVoteKick && !pPlayer->m_Authed) // allow admins to call kick votes even if they are forbidden
{
SendChatTarget(ClientID, "Server does not allow voting to kick players");
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
2010-05-29 07:25:38 +00:00
return;
}
if(g_Config.m_SvVoteKickMin)
{
int PlayerNum = 0;
for(int i = 0; i < MAX_CLIENTS; ++i)
if(m_apPlayers[i] && m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
++PlayerNum;
if(PlayerNum < g_Config.m_SvVoteKickMin)
{
str_format(aChatmsg, sizeof(aChatmsg), "Kick voting requires %d players on the server", g_Config.m_SvVoteKickMin);
SendChatTarget(ClientID, aChatmsg);
return;
}
}
int KickID = str_toint(pMsg->m_Value);
if(KickID < 0 || KickID >= MAX_CLIENTS || !m_apPlayers[KickID])
2010-05-29 07:25:38 +00:00
{
SendChatTarget(ClientID, "Invalid client id to kick");
2010-05-29 07:25:38 +00:00
return;
}
if(KickID == ClientID)
{
2011-06-01 17:31:13 +00:00
SendChatTarget(ClientID, "You can't kick yourself");
return;
}
//if(Server()->IsAuthed(KickID))
if(m_apPlayers[KickID]->m_Authed > 0 && m_apPlayers[KickID]->m_Authed >= pPlayer->m_Authed)
{
2011-06-01 17:31:13 +00:00
SendChatTarget(ClientID, "You can't kick admins");
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
char aBufKick[128];
str_format(aBufKick, sizeof(aBufKick), "'%s' called for vote to kick you", Server()->ClientName(ClientID));
SendChatTarget(KickID, aBufKick);
return;
}
2011-04-19 19:44:02 +00:00
if(GetPlayerChar(ClientID) && GetPlayerChar(KickID) && GetDDRaceTeam(ClientID) != GetDDRaceTeam(KickID))
{
SendChatTarget(ClientID, "You can kick only your team member");
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
return;
}
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to kick '%s' (%s)", Server()->ClientName(ClientID), Server()->ClientName(KickID), pReason);
str_format(aDesc, sizeof(aDesc), "Kick '%s'", Server()->ClientName(KickID));
2011-01-29 00:59:50 +00:00
if (!g_Config.m_SvVoteKickBantime)
str_format(aCmd, sizeof(aCmd), "kick %d Kicked by vote", KickID);
2010-05-29 07:25:38 +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);
2010-05-29 07:25:38 +00:00
}
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
m_VoteKick = true;
2010-05-29 07:25:38 +00:00
}
else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0)
{
if(!g_Config.m_SvVoteSpectate)
{
SendChatTarget(ClientID, "Server does not allow voting to move players to spectators");
return;
}
int SpectateID = str_toint(pMsg->m_Value);
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)
{
2011-06-01 17:31:13 +00:00
SendChatTarget(ClientID, "You can't move yourself");
return;
}
if(g_Config.m_SvPauseable && g_Config.m_SvVotePause)
{
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, pReason);
str_format(aDesc, sizeof(aDesc), "Pause '%s' (%ds)", Server()->ClientName(SpectateID), g_Config.m_SvVotePauseTime);
str_format(aCmd, sizeof(aCmd), "force_pause %d %d", SpectateID, g_Config.m_SvVotePauseTime);
}
else
{
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to move '%s' to spectators (%s)", Server()->ClientName(ClientID), Server()->ClientName(SpectateID), pReason);
str_format(aDesc, sizeof(aDesc), "move '%s' to spectators", Server()->ClientName(SpectateID));
str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, g_Config.m_SvVoteSpectateRejoindelay);
}
}
2010-05-29 07:25:38 +00:00
if(aCmd[0])
{
SendChat(-1, CGameContext::CHAT_ALL, aChatmsg);
StartVote(aDesc, aCmd, pReason);
pPlayer->m_Vote = 1;
pPlayer->m_VotePos = m_VotePos = 1;
m_VoteCreator = ClientID;
pPlayer->m_LastVoteCall = Now;
2010-05-29 07:25:38 +00:00
}
}
else if(MsgID == NETMSGTYPE_CL_VOTE)
2010-05-29 07:25:38 +00:00
{
if(!m_VoteCloseTime)
return;
if(pPlayer->m_Vote == 0)
2010-05-29 07:25:38 +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;
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true;
2008-09-25 12:23:44 +00:00
}
2008-09-24 14:47:03 +00:00
}
else if (MsgID == NETMSGTYPE_CL_SETTEAM && !m_World.m_Paused)
2010-05-29 07:25:38 +00:00
{
CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg;
//if(pPlayer->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick()))
if(pPlayer->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam + Server()->TickSpeed() * g_Config.m_SvTeamChangeDelay > Server()->Tick()))
2010-05-29 07:25:38 +00:00
return;
/*if(pMsg->m_Team != TEAM_SPECTATORS && m_LockTeams)
{
pPlayer->m_LastSetTeam = Server()->Tick();
SendBroadcast("Teams are locked", ClientID);
return;
}*/
if(pPlayer->m_TeamChangeTick > Server()->Tick())
{
2011-06-27 15:20:46 +00:00
pPlayer->m_LastSetTeam = Server()->Tick();
int TimeLeft = (pPlayer->m_TeamChangeTick - Server()->Tick())/Server()->TickSpeed();
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "Time to wait before changing team: %02d:%02d", TimeLeft/60, TimeLeft%60);
SendBroadcast(aBuf, ClientID);
return;
}
2010-05-29 07:25:38 +00:00
// Switch team on given client and kill/respawn him
if(m_pController->CanJoinTeam(pMsg->m_Team, ClientID))
2010-05-29 07:25:38 +00:00
{
//if(m_pController->CanChangeTeam(pPlayer, pMsg->m_Team))
if(pPlayer->m_Paused)
SendChatTarget(ClientID,"Use /pause first then you can kill");
2011-05-09 16:45:35 +00:00
else
2011-01-29 00:59:50 +00:00
{
//pPlayer->m_LastSetTeam = Server()->Tick();
if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS)
2010-05-29 07:25:38 +00:00
m_VoteUpdate = true;
pPlayer->SetTeam(pMsg->m_Team);
//(void)m_pController->CheckTeamBalance();
pPlayer->m_TeamChangeTick = Server()->Tick();
2011-01-29 00:59:50 +00:00
}
//else
//SendBroadcast("Teams must be balanced, please join other team", ClientID);
2010-05-29 07:25:38 +00:00
}
else
{
char aBuf[128];
2011-12-04 15:51:33 +00:00
str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", Server()->MaxClients()-g_Config.m_SvSpectatorSlots);
SendBroadcast(aBuf, ClientID);
2010-05-29 07:25:38 +00:00
}
}
else if (MsgID == NETMSGTYPE_CL_ISDDRACE)
{
pPlayer->m_IsUsingDDRaceClient = true;
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "%d use DDRace Client", ClientID);
dbg_msg("DDRace", aBuf);
//first update his teams state
((CGameControllerDDRace*)m_pController)->m_Teams.SendTeamsState(ClientID);
//second give him records
SendRecord(ClientID);
//third give him others current time for table score
if(g_Config.m_SvHideScore) return;
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_apPlayers[i] && Score()->PlayerData(i)->m_CurrentTime > 0)
{
CNetMsg_Sv_PlayerTime Msg;
2010-11-07 11:03:26 +00:00
Msg.m_Time = Score()->PlayerData(i)->m_CurrentTime * 100;
Msg.m_ClientID = i;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID);
2010-11-04 18:33:51 +00:00
//also send its time to others
}
}
2010-11-04 18:33:51 +00:00
//also send its time to others
if(Score()->PlayerData(ClientID)->m_CurrentTime > 0) {
2010-11-04 18:33:51 +00:00
//TODO: make function for this fucking steps
CNetMsg_Sv_PlayerTime Msg;
Msg.m_Time = Score()->PlayerData(ClientID)->m_CurrentTime * 100;
Msg.m_ClientID = ClientID;
2010-11-04 18:33:51 +00:00
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
}
}
else if (MsgID == NETMSGTYPE_CL_SETSPECTATORMODE && !m_World.m_Paused)
2010-05-29 07:25:38 +00:00
{
CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg;
if((pPlayer->GetTeam() != TEAM_SPECTATORS && !pPlayer->m_Paused) || pPlayer->m_SpectatorID == pMsg->m_SpectatorID || ClientID == pMsg->m_SpectatorID ||
(g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick()))
2010-05-29 07:25:38 +00:00
return;
pPlayer->m_LastSetSpectatorMode = Server()->Tick();
if(pMsg->m_SpectatorID != SPEC_FREEVIEW && (!m_apPlayers[pMsg->m_SpectatorID] || m_apPlayers[pMsg->m_SpectatorID]->GetTeam() == TEAM_SPECTATORS))
SendChatTarget(ClientID, "Invalid spectator id used");
else
pPlayer->m_SpectatorID = pMsg->m_SpectatorID;
}
else if (MsgID == NETMSGTYPE_CL_STARTINFO)
{
if(pPlayer->m_IsReady)
2010-05-29 07:25:38 +00:00
return;
CNetMsg_Cl_StartInfo *pMsg = (CNetMsg_Cl_StartInfo *)pRawMsg;
pPlayer->m_LastChangeInfo = Server()->Tick();
// set start infos
Server()->SetClientName(ClientID, pMsg->m_pName);
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;
//m_pController->OnPlayerInfoChange(pPlayer);
2010-05-29 07:25:38 +00:00
// send vote options
CNetMsg_Sv_VoteClearOptions ClearMsg;
Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientID);
CNetMsg_Sv_VoteOptionListAdd OptionMsg;
int NumOptions = 0;
2011-04-01 15:46:20 +00:00
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 = "";
2011-03-26 16:44:34 +00:00
CVoteOptionServer *pCurrent = m_pVoteOptionFirst;
while(pCurrent)
2010-05-29 07:25:38 +00:00
{
switch(NumOptions++)
2010-05-29 07:25:38 +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;
OptionMsg.m_NumOptions = NumOptions;
Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
OptionMsg = CNetMsg_Sv_VoteOptionListAdd();
NumOptions = 0;
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 = "";
}
2010-05-29 07:25:38 +00:00
}
pCurrent = pCurrent->m_pNext;
}
if(NumOptions > 0)
{
OptionMsg.m_NumOptions = NumOptions;
Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
NumOptions = 0;
}
// send tuning parameters to client
SendTuningParams(ClientID);
2010-05-29 07:25:38 +00:00
// client is ready to enter
pPlayer->m_IsReady = true;
CNetMsg_Sv_ReadyToEnter m;
Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID);
}
else if (MsgID == NETMSGTYPE_CL_CHANGEINFO)
{
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChangeInfo && pPlayer->m_LastChangeInfo+Server()->TickSpeed()*g_Config.m_SvInfoChangeDelay > Server()->Tick())
return;
CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg;
pPlayer->m_LastChangeInfo = Server()->Tick();
// set infos
char aOldName[MAX_NAME_LENGTH];
str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName));
Server()->SetClientName(ClientID, pMsg->m_pName);
if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0)
2010-05-29 07:25:38 +00:00
{
char aChatText[256];
str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID));
2010-05-29 07:25:38 +00:00
SendChat(-1, CGameContext::CHAT_ALL, aChatText);
// reload scores
Score()->PlayerData(ClientID)->Reset();
Score()->LoadScore(ClientID);
Score()->PlayerData(ClientID)->m_CurrentTime = Score()->PlayerData(ClientID)->m_BestTime;
m_apPlayers[ClientID]->m_Score = (Score()->PlayerData(ClientID)->m_BestTime)?Score()->PlayerData(ClientID)->m_BestTime:-9999;
2010-05-29 07:25:38 +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;
//m_pController->OnPlayerInfoChange(pPlayer);
2010-05-29 07:25:38 +00:00
}
else if (MsgID == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused)
2010-05-29 07:25:38 +00:00
{
CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg;
if(g_Config.m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*g_Config.m_SvEmoticonDelay > Server()->Tick())
2010-05-29 07:25:38 +00:00
return;
pPlayer->m_LastEmote = Server()->Tick();
SendEmoticon(ClientID, pMsg->m_Emoticon);
2011-04-13 23:36:51 +00:00
CCharacter* pChr = pPlayer->GetCharacter();
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
if(pChr && g_Config.m_SvEmotionalTees && pPlayer->m_EyeEmote)
{
switch(pMsg->m_Emoticon)
{
2011-04-13 23:36:51 +00:00
case EMOTICON_EXCLAMATION:
case EMOTICON_GHOST:
case EMOTICON_QUESTION:
case EMOTICON_WTF:
2011-01-29 00:59:50 +00:00
pChr->SetEmoteType(EMOTE_SURPRISE);
break;
2011-04-13 23:36:51 +00:00
case EMOTICON_DOTDOT:
case EMOTICON_DROP:
case EMOTICON_ZZZ:
2011-01-29 00:59:50 +00:00
pChr->SetEmoteType(EMOTE_BLINK);
break;
2011-04-13 23:36:51 +00:00
case EMOTICON_EYES:
case EMOTICON_HEARTS:
case EMOTICON_MUSIC:
2011-01-29 00:59:50 +00:00
pChr->SetEmoteType(EMOTE_HAPPY);
break;
2011-04-13 23:36:51 +00:00
case EMOTICON_OOP:
case EMOTICON_SORRY:
case EMOTICON_SUSHI:
2011-01-29 00:59:50 +00:00
pChr->SetEmoteType(EMOTE_PAIN);
break;
2011-04-13 23:36:51 +00:00
case EMOTICON_DEVILTEE:
case EMOTICON_SPLATTEE:
2011-04-13 23:36:51 +00:00
case EMOTICON_ZOMG:
2011-01-29 00:59:50 +00:00
pChr->SetEmoteType(EMOTE_ANGRY);
break;
default:
2011-04-13 23:36:51 +00:00
pChr->SetEmoteType(EMOTE_NORMAL);
break;
}
2011-01-29 00:59:50 +00:00
pChr->SetEmoteStop(Server()->Tick() + 2 * Server()->TickSpeed());
2011-04-13 23:36:51 +00:00
}
2010-05-29 07:25:38 +00:00
}
else if (MsgID == NETMSGTYPE_CL_KILL && !m_World.m_Paused)
2010-05-29 07:25:38 +00:00
{
2011-04-19 19:44:02 +00:00
if(m_VoteCloseTime && m_VoteCreator == ClientID && GetDDRaceTeam(ClientID))
{
SendChatTarget(ClientID, "You are running a vote please try again after the vote is done!");
return;
}
if(pPlayer->m_LastKill && pPlayer->m_LastKill+Server()->TickSpeed()*g_Config.m_SvKillDelay > Server()->Tick())
2010-05-29 07:25:38 +00:00
return;
2011-12-31 10:30:24 +00:00
if(pPlayer->m_Paused)
return;
pPlayer->m_LastKill = Server()->Tick();
pPlayer->KillCharacter(WEAPON_SELF);
2010-05-29 07:25:38 +00:00
}
}
2011-01-29 00:59:50 +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))
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "%s changed to %.2f", pParamName, NewValue);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", aBuf);
2010-05-29 07:25:38 +00:00
pSelf->SendTuningParams(-1);
}
else
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", "No such tuning parameter");
2010-05-29 07:25:38 +00:00
}
void CGameContext::ConTuneReset(IConsole::IResult *pResult, void *pUserData)
2010-05-29 07:25:38 +00:00
{
CGameContext *pSelf = (CGameContext *)pUserData;
/*CTuningParams TuningParams;
*pSelf->Tuning() = TuningParams;
pSelf->SendTuningParams(-1);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", "Tuning reset");*/
pSelf->ResetTuning();
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", "Tuning reset");
2010-05-29 07:25:38 +00:00
}
void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData)
2010-05-29 07:25:38 +00:00
{
CGameContext *pSelf = (CGameContext *)pUserData;
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);
str_format(aBuf, sizeof(aBuf), "%s %.2f", pSelf->Tuning()->m_apNames[i], v);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tuning", aBuf);
2010-05-29 07:25:38 +00:00
}
}
2012-01-09 23:49:31 +00:00
void CGameContext::ConPause(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
/*if(pSelf->m_pController->IsGameOver())
return;*/
2012-01-09 23:49:31 +00:00
pSelf->m_World.m_Paused ^= 1;
}
void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData)
2010-05-29 07:25:38 +00:00
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->m_pController->ChangeMap(pResult->NumArguments() ? pResult->GetString(0) : "");
2010-05-29 07:25:38 +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();
}
void CGameContext::ConBroadcast(IConsole::IResult *pResult, void *pUserData)
2010-05-29 07:25:38 +00:00
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->SendBroadcast(pResult->GetString(0), -1);
}
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));
}
void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData)
2010-05-29 07:25:38 +00:00
{
CGameContext *pSelf = (CGameContext *)pUserData;
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);
int Delay = pResult->NumArguments()>2 ? pResult->GetInteger(2) : 0;
if(!pSelf->m_apPlayers[ClientID])
return;
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "moved client %d to team %d", ClientID, Team);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
pSelf->m_apPlayers[ClientID]->m_TeamChangeTick = pSelf->Server()->Tick()+pSelf->Server()->TickSpeed()*Delay*60;
pSelf->m_apPlayers[ClientID]->SetTeam(Team);
// (void)pSelf->m_pController->CheckTeamBalance();
2010-05-29 07:25:38 +00:00
}
void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
int Team = clamp(pResult->GetInteger(0), -1, 1);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "All players were moved to the %s", pSelf->m_pController->GetTeamName(Team));
pSelf->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
for(int i = 0; i < MAX_CLIENTS; ++i)
if(pSelf->m_apPlayers[i])
pSelf->m_apPlayers[i]->SetTeam(Team, false);
// (void)pSelf->m_pController->CheckTeamBalance();
}
/*
2011-09-04 09:13:30 +00:00
void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->SwapTeams();
2011-09-04 09:13:30 +00:00
}
2011-09-04 09:13:30 +00:00
void CGameContext::ConShuffleTeams(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
2011-12-30 21:17:51 +00:00
if(!pSelf->m_pController->IsTeamplay())
return;
2011-09-04 09:13:30 +00:00
2011-12-30 21:17:51 +00:00
int CounterRed = 0;
int CounterBlue = 0;
int PlayerTeam = 0;
for(int i = 0; i < MAX_CLIENTS; ++i)
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
++PlayerTeam;
PlayerTeam = (PlayerTeam+1)/2;
pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were shuffled");
2011-09-04 09:13:30 +00:00
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
{
2011-12-30 21:17:51 +00:00
if(CounterRed == PlayerTeam)
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
2011-12-30 21:17:51 +00:00
else if(CounterBlue == PlayerTeam)
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
2011-09-04 09:13:30 +00:00
else
{
if(rand() % 2)
{
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false);
2011-12-30 21:17:51 +00:00
++CounterBlue;
2011-09-04 09:13:30 +00:00
}
else
{
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false);
2011-12-30 21:17:51 +00:00
++CounterRed;
2011-09-04 09:13:30 +00:00
}
}
}
}
2011-12-30 21:17:51 +00:00
// (void)pSelf->m_pController->CheckTeamBalance();
2011-09-04 09:13:30 +00:00
}
void CGameContext::ConLockTeams(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->m_LockTeams ^= 1;
if(pSelf->m_LockTeams)
pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were locked");
else
pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were unlocked");
}
*/
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);
if(pSelf->m_NumVoteOptions == MAX_VOTE_OPTIONS)
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "maximum number of vote options reached");
return;
}
// check for valid option
if(!pSelf->Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH)
{
char aBuf[256];
2011-03-26 16:44:34 +00:00
str_format(aBuf, sizeof(aBuf), "skipped invalid command '%s'", pCommand);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
2011-03-26 16:44:34 +00:00
return;
}
while(*pDescription && *pDescription == ' ')
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);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return;
}
2011-03-25 08:49:21 +00:00
// check for duplicate entry
2011-03-26 16:44:34 +00:00
CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst;
while(pOption)
{
2011-03-25 10:49:35 +00:00
if(str_comp_nocase(pDescription, pOption->m_aDescription) == 0)
{
char aBuf[256];
2011-03-25 08:49:21 +00:00
str_format(aBuf, sizeof(aBuf), "option '%s' already exists", pDescription);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return;
}
pOption = pOption->m_pNext;
}
2011-03-25 08:49:21 +00:00
// add the option
++pSelf->m_NumVoteOptions;
2011-03-25 08:49:21 +00:00
int Len = str_length(pCommand);
2011-03-26 16:44:34 +00:00
pOption = (CVoteOptionServer *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len);
2010-05-29 07:25:38 +00:00
pOption->m_pNext = 0;
pOption->m_pPrev = pSelf->m_pVoteOptionLast;
if(pOption->m_pPrev)
pOption->m_pPrev->m_pNext = pOption;
pSelf->m_pVoteOptionLast = pOption;
if(!pSelf->m_pVoteOptionFirst)
pSelf->m_pVoteOptionFirst = pOption;
2011-03-25 08:49:21 +00:00
str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription));
mem_copy(pOption->m_aCommand, pCommand, Len+1);
char aBuf[256];
2011-03-25 08:49:21 +00:00
str_format(aBuf, sizeof(aBuf), "added option '%s' '%s'", pOption->m_aDescription, pOption->m_aCommand);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
2010-05-29 07:25:38 +00:00
2011-03-25 10:49:35 +00:00
// inform clients about added option
CNetMsg_Sv_VoteOptionAdd OptionMsg;
OptionMsg.m_pDescription = pOption->m_aDescription;
2010-05-29 07:25:38 +00:00
pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1);
}
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-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);
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
// inform clients about removed option
CNetMsg_Sv_VoteOptionRemove OptionMsg;
OptionMsg.m_pDescription = pOption->m_aDescription;
pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1);
2011-03-25 10:49:35 +00:00
// TODO: improve this
// remove the option
--pSelf->m_NumVoteOptions;
2011-03-25 10:49:35 +00:00
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "removed option '%s' '%s'", pOption->m_aDescription, pOption->m_aCommand);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
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;
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-03-25 10:49:35 +00:00
str_copy(pDst->m_aDescription, pSrc->m_aDescription, sizeof(pDst->m_aDescription));
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;
pSelf->m_NumVoteOptions = NumVoteOptions;
2010-05-29 07:25:38 +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)
{
str_format(aBuf, sizeof(aBuf), "admin forced server option '%s' (%s)", pValue, pReason);
pSelf->SendChatTarget(-1, aBuf);
pSelf->Console()->ExecuteLine(pOption->m_aCommand);
2011-03-25 11:06:45 +00:00
break;
}
pOption = pOption->m_pNext;
}
2011-03-25 11:06:45 +00:00
if(!pOption)
{
str_format(aBuf, sizeof(aBuf), "'%s' isn't an option on this server", pValue);
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])
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to kick");
2011-03-25 11:06:45 +00:00
return;
}
if (!g_Config.m_SvVoteKickBantime)
{
str_format(aBuf, sizeof(aBuf), "kick %d %s", KickID, pReason);
pSelf->Console()->ExecuteLine(aBuf);
2011-03-25 11:06:45 +00:00
}
else
{
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);
pSelf->Console()->ExecuteLine(aBuf);
2011-03-25 11:06:45 +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)
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to move");
return;
}
str_format(aBuf, sizeof(aBuf), "admin moved '%s' to spectator (%s)", pSelf->Server()->ClientName(SpectateID), pReason);
pSelf->SendChatTarget(-1, aBuf);
str_format(aBuf, sizeof(aBuf), "set_team %d -1 %d", SpectateID, g_Config.m_SvVoteSpectateRejoindelay);
pSelf->Console()->ExecuteLine(aBuf);
}
2011-03-25 11:06:45 +00:00
}
void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "cleared votes");
CNetMsg_Sv_VoteClearOptions VoteClearOptionsMsg;
pSelf->Server()->SendPackMsg(&VoteClearOptionsMsg, MSGFLAG_VITAL, -1);
pSelf->m_pVoteOptionHeap->Reset();
pSelf->m_pVoteOptionFirst = 0;
pSelf->m_pVoteOptionLast = 0;
pSelf->m_NumVoteOptions = 0;
}
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
// check if there is a vote running
if(!pSelf->m_VoteCloseTime)
return;
2010-05-29 07:25:38 +00:00
if(str_comp_nocase(pResult->GetString(0), "yes") == 0)
pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_YES_ADMIN;
2010-05-29 07:25:38 +00:00
else if(str_comp_nocase(pResult->GetString(0), "no") == 0)
pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO_ADMIN;
pSelf->m_VoteEnforcer = pResult->m_ClientID;
2011-01-29 00:59:50 +00:00
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "admin forced vote %s", pResult->GetString(0));
pSelf->SendChatTarget(-1, aBuf);
str_format(aBuf, sizeof(aBuf), "forcing vote %s", pResult->GetString(0));
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
2010-05-29 07:25:38 +00:00
}
void CGameContext::ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
2010-05-29 07:25:38 +00:00
if(pResult->NumArguments())
{
CNetMsg_Sv_Motd Msg;
Msg.m_pMessage = g_Config.m_SvMotd;
CGameContext *pSelf = (CGameContext *)pUserData;
for(int i = 0; i < MAX_CLIENTS; ++i)
if(pSelf->m_apPlayers[i])
pSelf->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, i);
}
}
void CGameContext::OnConsoleInit()
{
m_pServer = Kernel()->RequestInterface<IServer>();
m_pConsole = Kernel()->RequestInterface<IConsole>();
2010-09-16 22:40:44 +00:00
m_ChatPrintCBIndex = Console()->RegisterPrintCallback(0, SendChatResponse, this);
2011-08-31 13:41:32 +00:00
Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, "Tune variable to value");
Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning");
Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning");
Console()->Register("pause_game", "", CFGFLAG_SERVER, ConPause, this, "Pause/unpause game");
Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map");
Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)");
Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message");
Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, "Say in chat");
Console()->Register("set_team", "ii?i", CFGFLAG_SERVER, ConSetTeam, this, "Set team of player to team");
Console()->Register("set_team_all", "i", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team");
//Console()->Register("swap_teams", "", CFGFLAG_SERVER, ConSwapTeams, this, "Swap the current teams");
//Console()->Register("shuffle_teams", "", CFGFLAG_SERVER, ConShuffleTeams, this, "Shuffle the current teams");
//Console()->Register("lock_teams", "", CFGFLAG_SERVER, ConLockTeams, this, "Lock/unlock teams");
Console()->Register("add_vote", "sr", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option");
Console()->Register("remove_vote", "s", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option");
Console()->Register("force_vote", "ss?r", CFGFLAG_SERVER, ConForceVote, this, "Force a voting option");
Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, "Clears the voting options");
Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, "Force a vote to yes/no");
2010-05-29 07:25:38 +00:00
Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
#define CONSOLE_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
2011-01-29 00:59:50 +00:00
#include "game/ddracecommands.h"
2011-08-31 13:41:32 +00:00
#define CHAT_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, callback, userdata, help);
#include "ddracechat.h"
2010-05-29 07:25:38 +00:00
}
void CGameContext::OnInit(/*class IKernel *pKernel*/)
{
m_pServer = Kernel()->RequestInterface<IServer>();
m_pConsole = Kernel()->RequestInterface<IConsole>();
m_World.SetGameServer(this);
m_Events.SetGameServer(this);
2010-05-29 07:25:38 +00:00
//if(!data) // only load once
//data = load_data_from_memory(internal_data);
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);
// reset everything here
//world = new GAMEWORLD;
//players = new CPlayer[MAX_CLIENTS];
// Reset Tuning
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);
}
if(g_Config.m_SvDDRaceTuneReset)
{
g_Config.m_SvHit = 1;
g_Config.m_SvEndlessDrag = 0;
g_Config.m_SvOldLaser = 0;
}
char buf[512];
str_format(buf, sizeof(buf), "data/maps/%s.cfg", g_Config.m_SvMap);
Console()->ExecuteFile(buf);
str_format(buf, sizeof(buf), "data/maps/%s.map.cfg", g_Config.m_SvMap);
Console()->ExecuteFile(buf);
2011-01-29 00:59:50 +00:00
/* // select gametype
if(str_comp(g_Config.m_SvGametype, "mod") == 0)
m_pController = new CGameControllerMOD(this);
else if(str_comp(g_Config.m_SvGametype, "ctf") == 0)
m_pController = new CGameControllerCTF(this);
else if(str_comp(g_Config.m_SvGametype, "tdm") == 0)
m_pController = new CGameControllerTDM(this);
else
m_pController = new CGameControllerDM(this);*/
m_pController = new CGameControllerDDRace(this);
((CGameControllerDDRace*)m_pController)->m_Teams.Reset();
// delete old score object
if(m_pScore)
delete m_pScore;
// create score object (add sql later)
#if defined(CONF_SQL)
2010-08-26 13:27:36 +00:00
if(g_Config.m_SvUseSQL)
m_pScore = new CSqlScore(this);
else
#endif
m_pScore = new CFileScore(this);
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-01-29 00:59:50 +00:00
/*
num_spawn_points[0] = 0;
num_spawn_points[1] = 0;
num_spawn_points[2] = 0;
2011-01-29 00:59:50 +00:00
*/
CTile *pFront = 0;
CSwitchTile *pSwitch = 0;
if(m_Layers.FrontLayer())
2011-08-26 11:46:22 +00:00
pFront = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(m_Layers.FrontLayer()->m_Front);
if(m_Layers.SwitchLayer())
2011-08-26 11:46:22 +00:00
pSwitch = (CSwitchTile *)Kernel()->RequestInterface<IMap>()->GetData(m_Layers.SwitchLayer()->m_Switch);
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++)
{
int Index = pTiles[y*pTileMap->m_Width+x].m_Index;
2010-12-01 22:45:04 +00:00
if(Index == TILE_OLDLASER)
{
2010-12-01 22:45:04 +00:00
g_Config.m_SvOldLaser = 1;
2011-01-29 00:59:50 +00:00
dbg_msg("Game Layer", "Found Old Laser Tile");
}
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);
dbg_msg("Game Layer", "Found No Collision Tile");
}
else if(Index == TILE_EHOOK)
{
g_Config.m_SvEndlessDrag = 1;
2011-01-29 00:59:50 +00:00
dbg_msg("Game Layer", "Found No Unlimited hook time Tile");
}
else if(Index == TILE_NOHIT)
{
g_Config.m_SvHit = 0;
2011-01-29 00:59:50 +00:00
dbg_msg("Game Layer", "Found No Weapons Hitting others Tile");
}
else if(Index == TILE_NPH)
{
2011-01-29 00:59:50 +00:00
m_Tuning.Set("player_hooking", 0);
dbg_msg("Game Layer", "Found No Player Hooking Tile");
}
2010-05-29 07:25:38 +00:00
if(Index >= ENTITY_OFFSET)
{
vec2 Pos(x*32.0f+16.0f, y*32.0f+16.0f);
//m_pController->OnEntity(Index-ENTITY_OFFSET, Pos);
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);
}
if(pFront)
{
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;
2011-01-29 00:59:50 +00:00
dbg_msg("Front Layer", "Found Old Laser Tile");
}
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);
dbg_msg("Front Layer", "Found No Collision Tile");
}
else if(Index == TILE_EHOOK)
2011-01-29 00:59:50 +00:00
{
g_Config.m_SvEndlessDrag = 1;
2011-01-29 00:59:50 +00:00
dbg_msg("Front Layer", "Found No Unlimited hook time Tile");
}
else if(Index == TILE_NOHIT)
2011-01-29 00:59:50 +00:00
{
g_Config.m_SvHit = 0;
2011-01-29 00:59:50 +00:00
dbg_msg("Front Layer", "Found No Weapons Hitting others Tile");
}
else if(Index == TILE_NPH)
2011-01-29 00:59:50 +00:00
{
m_Tuning.Set("player_hooking", 0);
dbg_msg("Front Layer", "Found No Player Hooking Tile");
}
if(Index >= ENTITY_OFFSET)
{
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);
}
}
if(pSwitch)
{
2011-01-29 00:59:50 +00:00
Index = pSwitch[y*pTileMap->m_Width + x].m_Type;
if(Index >= ENTITY_OFFSET)
{
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-05-29 07:25:38 +00:00
}
}
}
2011-01-29 00:59:50 +00:00
//game.world.insert_entity(game.Controller);
2010-05-29 07:25:38 +00:00
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
for(int i = 0; i < g_Config.m_DbgDummies ; i++)
{
OnClientConnected(MAX_CLIENTS-i-1);
}
}
#endif
}
void CGameContext::OnShutdown()
{
2010-10-27 10:14:26 +00:00
Layers()->Dest();
Collision()->Dest();
2010-05-29 07:25:38 +00:00
delete m_pController;
m_pController = 0;
Clear();
}
void CGameContext::OnSnap(int ClientID)
{
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;
for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++)
Msg.AddInt(pParams[i]);
Server()->SendMsg(&Msg, MSGFLAG_RECORD|MSGFLAG_NOSEND, ClientID);
}
m_World.Snap(ClientID);
m_pController->Snap(ClientID);
m_Events.Snap(ClientID);
for(int i = 0; i < MAX_CLIENTS; i++)
{
2010-05-29 07:25:38 +00:00
if(m_apPlayers[i])
m_apPlayers[i]->Snap(ClientID);
}
}
2010-05-29 07:25:38 +00:00
void CGameContext::OnPreSnap() {}
void CGameContext::OnPostSnap()
{
m_Events.Clear();
}
bool CGameContext::IsClientReady(int ClientID)
{
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->m_IsReady ? true : false;
}
bool CGameContext::IsClientPlayer(int ClientID)
{
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true;
}
const char *CGameContext::GameType() { return m_pController && m_pController->m_pGameType ? m_pController->m_pGameType : ""; }
2010-05-29 07:25:38 +00:00
const char *CGameContext::Version() { return GAME_VERSION; }
const char *CGameContext::NetVersion() { return GAME_NETVERSION; }
IGameServer *CreateGameServer() { return new CGameContext; }
2011-01-29 00:59:50 +00:00
void CGameContext::SendChatResponseAll(const char *pLine, void *pUser)
{
CGameContext *pSelf = (CGameContext *)pUser;
static volatile int ReentryGuard = 0;
if(ReentryGuard)
return;
ReentryGuard++;
if(*pLine == '[')
do
pLine++;
while(*(pLine - 2) != ':' && *pLine != 0);//remove the category (e.g. [Console]: No Such Command)
pSelf->SendChat(-1, CHAT_ALL, pLine);
ReentryGuard--;
}
void CGameContext::SendChatResponse(const char *pLine, void *pUser)
{
2011-08-31 13:41:32 +00:00
CGameContext *pSelf = (CGameContext *)pUser;
int ClientID = pSelf->m_ChatResponseTargetID;
if(ClientID < 0 || ClientID >= MAX_CLIENTS)
return;
2011-01-29 00:59:50 +00:00
static volatile int ReentryGuard = 0;
if(ReentryGuard)
return;
ReentryGuard++;
if(*pLine == '[')
do
pLine++;
while(*(pLine - 2) != ':' && *pLine != 0); // remove the category (e.g. [Console]: No Such Command)
2011-08-31 13:41:32 +00:00
pSelf->SendChatTarget(ClientID, pLine);
2011-01-29 00:59:50 +00:00
ReentryGuard--;
}
bool CGameContext::PlayerCollision()
{
float Temp;
m_Tuning.Get("player_collision", &Temp);
return Temp != 0.0;
}
bool CGameContext::PlayerHooking()
{
float Temp;
m_Tuning.Get("player_hooking", &Temp);
return Temp != 0.0;
}
void CGameContext::OnSetAuthed(int ClientID, int Level)
2011-01-29 00:59:50 +00:00
{
CServer* pServ = (CServer*)Server();
if(m_apPlayers[ClientID])
2011-01-29 00:59:50 +00:00
{
m_apPlayers[ClientID]->m_Authed = Level;
char aBuf[512], aIP[NETADDR_MAXSTRSIZE];
pServ->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);
2011-04-14 02:26:13 +00:00
if(!str_comp_nocase(m_aVoteCommand, aBuf) && Level > 0)
2011-01-29 00:59:50 +00:00
{
2011-12-26 09:15:43 +00:00
m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO_ADMIN;
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "CGameContext", "Aborted vote by admin login.");
2011-01-29 00:59:50 +00:00
}
}
}
void CGameContext::SendRecord(int ClientID)
{
2011-01-29 00:59:50 +00:00
CNetMsg_Sv_Record RecordsMsg;
2011-04-14 02:38:03 +00:00
RecordsMsg.m_PlayerTimeBest = Score()->PlayerData(ClientID)->m_BestTime * 100.0f;
RecordsMsg.m_ServerTimeBest = m_pController->m_CurrentRecord * 100.0f; //TODO: finish this
Server()->SendPackMsg(&RecordsMsg, MSGFLAG_VITAL, ClientID);
2011-02-23 07:43:05 +00:00
}
int CGameContext::ProcessSpamProtection(int ClientID)
{
2011-09-07 23:02:09 +00:00
if(!m_apPlayers[ClientID])
return 0;
if(g_Config.m_SvSpamprotection && m_apPlayers[ClientID]->m_LastChat
&& m_apPlayers[ClientID]->m_LastChat + Server()->TickSpeed() * g_Config.m_SvChatDelay > Server()->Tick())
return 1;
else
m_apPlayers[ClientID]->m_LastChat = Server()->Tick();
NETADDR Addr;
Server()->GetClientAddr(ClientID, &Addr);
int Muted = 0;
for(int i = 0; i < m_NumMutes && !Muted; i++)
{
if(!net_addr_comp(&Addr, &m_aMutes[i].m_Addr))
Muted = (m_aMutes[i].m_Expire - Server()->Tick()) / Server()->TickSpeed();
}
if (Muted > 0)
{
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;
}
if ((m_apPlayers[ClientID]->m_ChatScore += g_Config.m_SvChatPenalty) > g_Config.m_SvChatThreshold)
{
Mute(0, &Addr, g_Config.m_SvSpamMuteDuration, Server()->ClientName(ClientID));
m_apPlayers[ClientID]->m_ChatScore = 0;
return 1;
}
return 0;
}
2011-04-19 19:44:02 +00:00
int CGameContext::GetDDRaceTeam(int ClientID)
{
CGameControllerDDRace* pController = (CGameControllerDDRace*)m_pController;
return pController->m_Teams.m_Core.Team(ClientID);
}
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);
}