diff options
Diffstat (limited to 'src/game/server/gamecontext.cpp')
| -rw-r--r-- | src/game/server/gamecontext.cpp | 215 |
1 files changed, 177 insertions, 38 deletions
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 82adcbef..5d2f22b8 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -33,6 +33,7 @@ void CGameContext::Construct(int Resetting) m_pVoteOptionFirst = 0; m_pVoteOptionLast = 0; m_NumVoteOptions = 0; + m_LockTeams = 0; if(Resetting==NO_RESET) m_pVoteOptionHeap = new CHeap(); @@ -93,7 +94,7 @@ void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount) for(int i = 0; i < Amount; i++) { float f = mix(s, e, float(i+1)/float(Amount+2)); - NETEVENT_DAMAGEIND *pEvent = (NETEVENT_DAMAGEIND *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(NETEVENT_DAMAGEIND)); + CNetEvent_DamageInd *pEvent = (CNetEvent_DamageInd *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(CNetEvent_DamageInd)); if(pEvent) { pEvent->m_X = (int)Pos.x; @@ -106,7 +107,7 @@ void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount) void CGameContext::CreateHammerHit(vec2 Pos) { // create the event - NETEVENT_HAMMERHIT *pEvent = (NETEVENT_HAMMERHIT *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(NETEVENT_HAMMERHIT)); + CNetEvent_HammerHit *pEvent = (CNetEvent_HammerHit *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(CNetEvent_HammerHit)); if(pEvent) { pEvent->m_X = (int)Pos.x; @@ -118,7 +119,7 @@ void CGameContext::CreateHammerHit(vec2 Pos) void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage) { // create the event - NETEVENT_EXPLOSION *pEvent = (NETEVENT_EXPLOSION *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(NETEVENT_EXPLOSION)); + CNetEvent_Explosion *pEvent = (CNetEvent_Explosion *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(CNetEvent_Explosion)); if(pEvent) { pEvent->m_X = (int)Pos.x; @@ -162,7 +163,7 @@ void create_smoke(vec2 Pos) void CGameContext::CreatePlayerSpawn(vec2 Pos) { // create the event - NETEVENT_SPAWN *ev = (NETEVENT_SPAWN *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(NETEVENT_SPAWN)); + CNetEvent_Spawn *ev = (CNetEvent_Spawn *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(CNetEvent_Spawn)); if(ev) { ev->m_X = (int)Pos.x; @@ -173,7 +174,7 @@ void CGameContext::CreatePlayerSpawn(vec2 Pos) void CGameContext::CreateDeath(vec2 Pos, int ClientID) { // create the event - NETEVENT_DEATH *pEvent = (NETEVENT_DEATH *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(NETEVENT_DEATH)); + CNetEvent_Death *pEvent = (CNetEvent_Death *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(CNetEvent_Death)); if(pEvent) { pEvent->m_X = (int)Pos.x; @@ -188,7 +189,7 @@ void CGameContext::CreateSound(vec2 Pos, int Sound, int Mask) return; // create a sound - NETEVENT_SOUNDWORLD *pEvent = (NETEVENT_SOUNDWORLD *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(NETEVENT_SOUNDWORLD), Mask); + CNetEvent_SoundWorld *pEvent = (CNetEvent_SoundWorld *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(CNetEvent_SoundWorld), Mask); if(pEvent) { pEvent->m_X = (int)Pos.x; @@ -204,7 +205,15 @@ void CGameContext::CreateSoundGlobal(int Sound, int Target) CNetMsg_Sv_SoundGlobal Msg; Msg.m_SoundID = Sound; - Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, Target); + 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); + } } @@ -225,7 +234,7 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText) str_format(aBuf, sizeof(aBuf), "%d:%d:%s: %s", ChatterClientID, Team, Server()->ClientName(ChatterClientID), pText); else str_format(aBuf, sizeof(aBuf), "*** %s", pText); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "chat", aBuf); + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, Team!=CHAT_ALL?"teamchat":"chat", aBuf); if(Team == CHAT_ALL) { @@ -343,7 +352,8 @@ void CGameContext::SendVoteStatus(int ClientID, int Total, int Yes, int No) void CGameContext::AbortVoteKickOnDisconnect(int ClientID) { - if(m_VoteCloseTime && !str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientID) + 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))) m_VoteCloseTime = -1; } @@ -378,6 +388,22 @@ void CGameContext::SendTuningParams(int ClientID) 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(); +} + void CGameContext::OnTick() { // check tuning @@ -456,7 +482,9 @@ void CGameContext::OnTick() if(m_VoteEnforce == VOTE_ENFORCE_YES) { + Server()->SetRconCID(IServer::RCON_CID_VOTE); Console()->ExecuteLine(m_aVoteCommand); + Server()->SetRconCID(IServer::RCON_CID_SERV); EndVote(); SendChat(-1, CGameContext::CHAT_ALL, "Vote passed"); @@ -691,12 +719,12 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } if(KickID == ClientID) { - SendChatTarget(ClientID, "You cant kick yourself"); + SendChatTarget(ClientID, "You can't kick yourself"); return; } if(Server()->IsAuthed(KickID)) { - SendChatTarget(ClientID, "You cant kick admins"); + SendChatTarget(ClientID, "You can't kick admins"); char aBufKick[128]; str_format(aBufKick, sizeof(aBufKick), "'%s' called for vote to kick you", Server()->ClientName(ClientID)); SendChatTarget(KickID, aBufKick); @@ -712,7 +740,6 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) 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); - Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aCmd); } } else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0) @@ -731,13 +758,13 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } if(SpectateID == ClientID) { - SendChatTarget(ClientID, "You cant move yourself"); + SendChatTarget(ClientID, "You can't move yourself"); return; } 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", SpectateID); + str_format(aCmd, sizeof(aCmd), "set_team %d -1 %d", SpectateID, g_Config.m_SvVoteSpectateRejoindelay); } if(aCmd[0]) @@ -773,6 +800,23 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) if(pPlayer->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick())) 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()) + { + 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; + } + // Switch team on given client and kill/respawn him if(m_pController->CanJoinTeam(pMsg->m_Team, ClientID)) { @@ -783,6 +827,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) m_VoteUpdate = true; pPlayer->SetTeam(pMsg->m_Team); (void)m_pController->CheckTeamBalance(); + pPlayer->m_TeamChangeTick = Server()->Tick(); } else SendBroadcast("Teams must be balanced, please join other team", ClientID); @@ -790,7 +835,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) else { char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots); + str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", Server()->MaxClients()-g_Config.m_SvSpectatorSlots); SendBroadcast(aBuf, ClientID); } } @@ -992,6 +1037,16 @@ void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData) } } +void CGameContext::ConPause(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + + if(pSelf->m_pController->IsGameOver()) + return; + + pSelf->m_World.m_Paused ^= 1; +} + void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -1024,14 +1079,15 @@ void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData) CGameContext *pSelf = (CGameContext *)pUserData; int ClientID = clamp(pResult->GetInteger(0), 0, (int)MAX_CLIENTS-1); 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); - if(!pSelf->m_apPlayers[ClientID]) - return; - + 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(); } @@ -1042,16 +1098,75 @@ void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData) int Team = clamp(pResult->GetInteger(0), -1, 1); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "moved all clients to team %d", Team); - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); + 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); + pSelf->m_apPlayers[i]->SetTeam(Team, false); + + (void)pSelf->m_pController->CheckTeamBalance(); +} + +void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + pSelf->SwapTeams(); +} + +void CGameContext::ConShuffleTeams(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + if(!pSelf->m_pController->IsTeamplay()) + return; + + 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"); + + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS) + { + if(CounterRed == PlayerTeam) + pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false); + else if(CounterBlue == PlayerTeam) + pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false); + else + { + if(rand() % 2) + { + pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false); + ++CounterBlue; + } + else + { + pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false); + ++CounterRed; + } + } + } + } (void)pSelf->m_pController->CheckTeamBalance(); } +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) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -1248,7 +1363,9 @@ void CGameContext::ConForceVote(IConsole::IResult *pResult, void *pUserData) return; } - str_format(aBuf, sizeof(aBuf), "set_team %d -1", SpectateID); + 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); } } @@ -1269,11 +1386,18 @@ void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConVote(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; + + // check if there is a vote running + if(!pSelf->m_VoteCloseTime) + return; + if(str_comp_nocase(pResult->GetString(0), "yes") == 0) pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_YES; else if(str_comp_nocase(pResult->GetString(0), "no") == 0) pSelf->m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO; 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); } @@ -1297,22 +1421,26 @@ void CGameContext::OnConsoleInit() m_pServer = Kernel()->RequestInterface<IServer>(); m_pConsole = Kernel()->RequestInterface<IConsole>(); - Console()->Register("tune", "si", CFGFLAG_SERVER, ConTuneParam, this, ""); - Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, ""); - Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, ""); - - Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, ""); - Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, ""); - Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, ""); - Console()->Register("say", "r", CFGFLAG_SERVER, ConSay, this, ""); - Console()->Register("set_team", "ii", CFGFLAG_SERVER, ConSetTeam, this, ""); - Console()->Register("set_team_all", "i", CFGFLAG_SERVER, ConSetTeamAll, this, ""); - - Console()->Register("add_vote", "sr", CFGFLAG_SERVER, ConAddVote, this, ""); - Console()->Register("remove_vote", "s", CFGFLAG_SERVER, ConRemoveVote, this, ""); - Console()->Register("force_vote", "ss?r", CFGFLAG_SERVER, ConForceVote, this, ""); - Console()->Register("clear_votes", "", CFGFLAG_SERVER, ConClearVotes, this, ""); - Console()->Register("vote", "r", CFGFLAG_SERVER, ConVote, this, ""); + 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", "", 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"); Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this); } @@ -1400,6 +1528,17 @@ void CGameContext::OnShutdown() void CGameContext::OnSnap(int ClientID) { + // 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); |