From 67c101b43d9cb38627feded29551161ee247efd4 Mon Sep 17 00:00:00 2001 From: furo Date: Sat, 16 Dec 2023 01:41:03 +0100 Subject: [PATCH] Add `/join [player]`. --- src/game/ddracechat.h | 9 +- src/game/server/ddracechat.cpp | 189 +++++++++++++++++++-------------- src/game/server/gamecontext.h | 11 +- 3 files changed, 123 insertions(+), 86 deletions(-) diff --git a/src/game/ddracechat.h b/src/game/ddracechat.h index 16f86fc10..b26dceac2 100644 --- a/src/game/ddracechat.h +++ b/src/game/ddracechat.h @@ -45,10 +45,11 @@ CHAT_COMMAND("points", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConPoin CHAT_COMMAND("top5points", "?i[number]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTopPoints, this, "Shows five points of the global point ladder beginning with rank i (1 by default)") CHAT_COMMAND("timecp", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTimeCP, this, "Set your checkpoints based on another player") -CHAT_COMMAND("team", "?i[id]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConJoinTeam, this, "Lets you join team i (shows your team if left blank)") -CHAT_COMMAND("lock", "?i['0'|'1']", CFGFLAG_CHAT | CFGFLAG_SERVER, ConLockTeam, this, "Toggle team lock so no one else can join and so the team restarts when a player dies. /lock 0 to unlock, /lock 1 to lock.") -CHAT_COMMAND("unlock", "", CFGFLAG_CHAT | CFGFLAG_SERVER, ConUnlockTeam, this, "Unlock a team") -CHAT_COMMAND("invite", "r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConInviteTeam, this, "Invite a person to a locked team") +CHAT_COMMAND("team", "?i[id]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeam, this, "Lets you join team i (shows your team if left blank)") +CHAT_COMMAND("lock", "?i['0'|'1']", CFGFLAG_CHAT | CFGFLAG_SERVER, ConLock, this, "Toggle team lock so no one else can join and so the team restarts when a player dies. /lock 0 to unlock, /lock 1 to lock.") +CHAT_COMMAND("unlock", "", CFGFLAG_CHAT | CFGFLAG_SERVER, ConUnlock, this, "Unlock a team") +CHAT_COMMAND("invite", "r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConInvite, this, "Invite a person to a locked team") +CHAT_COMMAND("join", "r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConJoin, this, "Join the team of the specified player") CHAT_COMMAND("showothers", "?i['0'|'1'|'2']", CFGFLAG_CHAT | CFGFLAG_SERVER, ConShowOthers, this, "Whether to show players from other teams or not (off by default), optional i = 0 for off, i = 1 for on, i = 2 for own team only") CHAT_COMMAND("showall", "?i['0'|'1']", CFGFLAG_CHAT | CFGFLAG_SERVER, ConShowAll, this, "Whether to show players at any distance (off by default), optional i = 0 for off else for on") diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp index e63dcbe58..f422657dd 100644 --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -871,7 +871,7 @@ void CGameContext::ConRank(IConsole::IResult *pResult, void *pUserData) pSelf->Server()->ClientName(pResult->m_ClientID)); } -void CGameContext::ConLockTeam(IConsole::IResult *pResult, void *pUserData) +void CGameContext::ConLock(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientID(pResult->m_ClientID)) @@ -917,7 +917,7 @@ void CGameContext::ConLockTeam(IConsole::IResult *pResult, void *pUserData) } } -void CGameContext::ConUnlockTeam(IConsole::IResult *pResult, void *pUserData) +void CGameContext::ConUnlock(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientID(pResult->m_ClientID)) @@ -950,7 +950,81 @@ void CGameContext::UnlockTeam(int ClientID, int Team) const SendChatTeam(Team, aBuf); } -void CGameContext::ConInviteTeam(IConsole::IResult *pResult, void *pUserData) +void CGameContext::AttemptJoinTeam(int ClientID, int Team) +{ + CPlayer *pPlayer = m_apPlayers[ClientID]; + if(!pPlayer) + return; + + if(m_VoteCloseTime && m_VoteCreator == ClientID && (IsKickVote() || IsSpecVote())) + { + Console()->Print( + IConsole::OUTPUT_LEVEL_STANDARD, + "chatresp", + "You are running a vote please try again after the vote is done!"); + } + else if(g_Config.m_SvTeam == SV_TEAM_FORBIDDEN || g_Config.m_SvTeam == SV_TEAM_FORCED_SOLO) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", + "Teams are disabled"); + } + else if(g_Config.m_SvTeam == SV_TEAM_MANDATORY && Team == 0 && pPlayer->GetCharacter() && pPlayer->GetCharacter()->m_LastStartWarning < Server()->Tick() - 3 * Server()->TickSpeed()) + { + Console()->Print( + IConsole::OUTPUT_LEVEL_STANDARD, + "chatresp", + "You must join a team and play with somebody or else you can\'t play"); + pPlayer->GetCharacter()->m_LastStartWarning = Server()->Tick(); + } + + if(pPlayer->GetCharacter() == 0) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", + "You can't change teams while you are dead/a spectator."); + } + else + { + if(Team < 0 || Team >= MAX_CLIENTS) + Team = m_pController->Teams().GetFirstEmptyTeam(); + + if(pPlayer->m_Last_Team + (int64_t)Server()->TickSpeed() * g_Config.m_SvTeamChangeDelay > Server()->Tick()) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", + "You can\'t change teams that fast!"); + } + else if(Team > 0 && Team < MAX_CLIENTS && m_pController->Teams().TeamLocked(Team) && !m_pController->Teams().IsInvited(Team, ClientID)) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", + g_Config.m_SvInvite ? + "This team is locked using /lock. Only members of the team can unlock it using /lock." : + "This team is locked using /lock. Only members of the team can invite you or unlock it using /lock."); + } + else if(Team > 0 && Team < MAX_CLIENTS && m_pController->Teams().Count(Team) >= g_Config.m_SvMaxTeamSize) + { + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "This team already has the maximum allowed size of %d players", g_Config.m_SvMaxTeamSize); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", aBuf); + } + else if(const char *pError = m_pController->Teams().SetCharacterTeam(pPlayer->GetCID(), Team)) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", pError); + } + else + { + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "'%s' joined team %d", + Server()->ClientName(pPlayer->GetCID()), + Team); + SendChat(-1, CGameContext::CHAT_ALL, aBuf); + pPlayer->m_Last_Team = Server()->Tick(); + + if(m_pController->Teams().IsPractice(Team)) + SendChatTarget(pPlayer->GetCID(), "Practice mode enabled for your team, happy practicing!"); + } + } +} + +void CGameContext::ConInvite(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; auto *pController = pSelf->m_pController; @@ -1004,7 +1078,7 @@ void CGameContext::ConInviteTeam(IConsole::IResult *pResult, void *pUserData) pSelf->m_apPlayers[pResult->m_ClientID]->m_LastInvited = pSelf->Server()->Tick(); char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "'%s' invited you to team %d.", pSelf->Server()->ClientName(pResult->m_ClientID), Team); + str_format(aBuf, sizeof(aBuf), "'%s' invited you to team %d. Use /team %d to join.", pSelf->Server()->ClientName(pResult->m_ClientID), Team, Team); pSelf->SendChatTarget(Target, aBuf); str_format(aBuf, sizeof(aBuf), "'%s' invited '%s' to your team.", pSelf->Server()->ClientName(pResult->m_ClientID), pSelf->Server()->ClientName(Target)); @@ -1014,10 +1088,9 @@ void CGameContext::ConInviteTeam(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", "Can't invite players to this team"); } -void CGameContext::ConJoinTeam(IConsole::IResult *pResult, void *pUserData) +void CGameContext::ConTeam(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; - auto *pController = pSelf->m_pController; if(!CheckClientID(pResult->m_ClientID)) return; @@ -1025,78 +1098,9 @@ void CGameContext::ConJoinTeam(IConsole::IResult *pResult, void *pUserData) if(!pPlayer) return; - if(pSelf->m_VoteCloseTime && pSelf->m_VoteCreator == pResult->m_ClientID && (pSelf->IsKickVote() || pSelf->IsSpecVote())) - { - pSelf->Console()->Print( - IConsole::OUTPUT_LEVEL_STANDARD, - "chatresp", - "You are running a vote please try again after the vote is done!"); - return; - } - else if(g_Config.m_SvTeam == SV_TEAM_FORBIDDEN || g_Config.m_SvTeam == SV_TEAM_FORCED_SOLO) - { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", - "Teams are disabled"); - return; - } - else if(g_Config.m_SvTeam == SV_TEAM_MANDATORY && pResult->GetInteger(0) == 0 && pPlayer->GetCharacter() && pPlayer->GetCharacter()->m_LastStartWarning < pSelf->Server()->Tick() - 3 * pSelf->Server()->TickSpeed()) - { - pSelf->Console()->Print( - IConsole::OUTPUT_LEVEL_STANDARD, - "chatresp", - "You must join a team and play with somebody or else you can\'t play"); - pPlayer->GetCharacter()->m_LastStartWarning = pSelf->Server()->Tick(); - } - if(pResult->NumArguments() > 0) { - if(pPlayer->GetCharacter() == 0) - { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", - "You can't change teams while you are dead/a spectator."); - } - else - { - int Team = pResult->GetInteger(0); - - if(Team < 0 || Team >= MAX_CLIENTS) - Team = pController->Teams().GetFirstEmptyTeam(); - - if(pPlayer->m_Last_Team + (int64_t)pSelf->Server()->TickSpeed() * g_Config.m_SvTeamChangeDelay > pSelf->Server()->Tick()) - { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", - "You can\'t change teams that fast!"); - } - else if(Team > 0 && Team < MAX_CLIENTS && pController->Teams().TeamLocked(Team) && !pController->Teams().IsInvited(Team, pResult->m_ClientID)) - { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", - g_Config.m_SvInvite ? - "This team is locked using /lock. Only members of the team can unlock it using /lock." : - "This team is locked using /lock. Only members of the team can invite you or unlock it using /lock."); - } - else if(Team > 0 && Team < MAX_CLIENTS && pController->Teams().Count(Team) >= g_Config.m_SvMaxTeamSize) - { - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "This team already has the maximum allowed size of %d players", g_Config.m_SvMaxTeamSize); - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", aBuf); - } - else if(const char *pError = pController->Teams().SetCharacterTeam(pPlayer->GetCID(), Team)) - { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", pError); - } - else - { - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "'%s' joined team %d", - pSelf->Server()->ClientName(pPlayer->GetCID()), - Team); - pSelf->SendChat(-1, CGameContext::CHAT_ALL, aBuf); - pPlayer->m_Last_Team = pSelf->Server()->Tick(); - - if(pController->Teams().IsPractice(Team)) - pSelf->SendChatTarget(pPlayer->GetCID(), "Practice mode enabled for your team, happy practicing!"); - } - } + pSelf->AttemptJoinTeam(pResult->m_ClientID, pResult->GetInteger(0)); } else { @@ -1115,12 +1119,41 @@ void CGameContext::ConJoinTeam(IConsole::IResult *pResult, void *pUserData) sizeof(aBuf), "You are in team %d", pSelf->GetDDRaceTeam(pResult->m_ClientID)); - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", - aBuf); + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", aBuf); } } } +void CGameContext::ConJoin(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + if(!CheckClientID(pResult->m_ClientID)) + return; + + int Target = -1; + const char *pName = pResult->GetString(0); + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!str_comp(pName, pSelf->Server()->ClientName(i))) + { + Target = i; + break; + } + } + + if(Target == -1) + { + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", "Player not found"); + return; + } + + int Team = pSelf->GetDDRaceTeam(Target); + if(pSelf->ProcessSpamProtection(pResult->m_ClientID, false)) + return; + + pSelf->AttemptJoinTeam(pResult->m_ClientID, Team); +} + void CGameContext::ConMe(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 34e1cf769..67a2a3759 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -437,10 +437,12 @@ private: static void ConMap(IConsole::IResult *pResult, void *pUserData); static void ConTeamRank(IConsole::IResult *pResult, void *pUserData); static void ConRank(IConsole::IResult *pResult, void *pUserData); - static void ConJoinTeam(IConsole::IResult *pResult, void *pUserData); - static void ConLockTeam(IConsole::IResult *pResult, void *pUserData); - static void ConUnlockTeam(IConsole::IResult *pResult, void *pUserData); - static void ConInviteTeam(IConsole::IResult *pResult, void *pUserData); + static void ConTeam(IConsole::IResult *pResult, void *pUserData); + static void ConLock(IConsole::IResult *pResult, void *pUserData); + static void ConUnlock(IConsole::IResult *pResult, void *pUserData); + static void ConInvite(IConsole::IResult *pResult, void *pUserData); + static void ConJoin(IConsole::IResult *pResult, void *pUserData); + static void ConAccept(IConsole::IResult *pResult, void *pUserData); static void ConMe(IConsole::IResult *pResult, void *pUserData); static void ConWhisper(IConsole::IResult *pResult, void *pUserData); static void ConConverse(IConsole::IResult *pResult, void *pUserData); @@ -506,6 +508,7 @@ private: void Converse(int ClientID, char *pStr); bool IsVersionBanned(int Version); void UnlockTeam(int ClientID, int Team) const; + void AttemptJoinTeam(int ClientID, int Team); enum {