/
dieoska
/
ddnet
Обзор
Документация
Войти
/
dieoska
/
ddnet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/game/server/ddracecommands.cpp
650 строк
19 KB
ChillerDragon
Fix `invincible` and `tele` causing oob from econ and fifo
14 дек 2025, 14:10
14 дек 2025, 14:10
6970e0b
Код
Авторство
О чём код?
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */ #include "gamecontext.h" #include <engine/antibot.h> #include <engine/shared/config.h> #include <game/server/entities/character.h> #include <game/server/gamemodes/DDRace.h> #include <game/server/player.h> #include <game/server/save.h> #include <game/server/teams.h> void CGameContext::ConGoLeft(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(0) : 1; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, -1 * Tiles, 0); } void CGameContext::ConGoRight(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(0) : 1; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, Tiles, 0); } void CGameContext::ConGoDown(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(0) : 1; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, 0, Tiles); } void CGameContext::ConGoUp(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(0) : 1; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, 0, -1 * Tiles); } void CGameContext::ConMove(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, pResult->GetInteger(0), pResult->GetInteger(1)); } void CGameContext::ConMoveRaw(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; pSelf->MoveCharacter(pResult->m_ClientId, pResult->GetInteger(0), pResult->GetInteger(1), true); } void CGameContext::MoveCharacter(int ClientId, int X, int Y, bool Raw) { CCharacter *pChr = GetPlayerChar(ClientId); if(!pChr) return; pChr->Move(vec2((Raw ? 1 : 32) * X, (Raw ? 1 : 32) * Y)); pChr->ResetVelocity(); pChr->m_DDRaceState = ERaceState::CHEATED; } void CGameContext::ConKillPlayer(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; int Victim = pResult->GetVictim(); if(pSelf->m_apPlayers[Victim]) { pSelf->m_apPlayers[Victim]->KillCharacter(WEAPON_GAME); char aBuf[512]; if(pResult->NumArguments() == 2) str_format(aBuf, sizeof(aBuf), "%s was killed by authorized player (%s)", pSelf->Server()->ClientName(Victim), pResult->GetString(1)); else str_format(aBuf, sizeof(aBuf), "%s was killed by authorized player", pSelf->Server()->ClientName(Victim)); pSelf->SendChat(-1, TEAM_ALL, aBuf); } } void CGameContext::ConNinja(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_NINJA, false); } void CGameContext::ConUnNinja(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_NINJA, true); } void CGameContext::ConEndlessHook(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) { pChr->SetEndlessHook(true); } } void CGameContext::ConUnEndlessHook(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) { pChr->SetEndlessHook(false); } } void CGameContext::ConSuper(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr && !pChr->IsSuper()) { pChr->SetSuper(true); pChr->UnFreeze(); } } void CGameContext::ConUnSuper(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr && pChr->IsSuper()) { pChr->SetSuper(false); } } void CGameContext::ConToggleInvincible(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetInvincible(pResult->NumArguments() == 0 ? !pChr->Core()->m_Invincible : pResult->GetInteger(0)); } void CGameContext::ConSolo(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetSolo(true); } void CGameContext::ConUnSolo(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetSolo(false); } void CGameContext::ConFreeze(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->Freeze(); } void CGameContext::ConUnFreeze(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->UnFreeze(); } void CGameContext::ConDeep(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetDeepFrozen(true); } void CGameContext::ConUnDeep(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) { pChr->SetDeepFrozen(false); pChr->UnFreeze(); } } void CGameContext::ConLiveFreeze(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetLiveFrozen(true); } void CGameContext::ConUnLiveFreeze(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetLiveFrozen(false); } void CGameContext::ConShotgun(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_SHOTGUN, false); } void CGameContext::ConGrenade(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_GRENADE, false); } void CGameContext::ConLaser(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_LASER, false); } void CGameContext::ConJetpack(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetJetpack(true); } void CGameContext::ConEndlessJump(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetEndlessJump(true); } void CGameContext::ConSetJumps(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetJumps(pResult->GetInteger(0)); } void CGameContext::ConWeapons(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, -1, false); } void CGameContext::ConUnShotgun(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_SHOTGUN, true); } void CGameContext::ConUnGrenade(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_GRENADE, true); } void CGameContext::ConUnLaser(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, WEAPON_LASER, true); } void CGameContext::ConUnJetpack(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetJetpack(false); } void CGameContext::ConUnEndlessJump(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) pChr->SetEndlessJump(false); } void CGameContext::ConUnWeapons(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, -1, true); } void CGameContext::ConAddWeapon(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, pResult->GetInteger(0), false); } void CGameContext::ConRemoveWeapon(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ModifyWeapons(pResult, pUserData, pResult->GetInteger(0), true); } void CGameContext::ModifyWeapons(IConsole::IResult *pResult, void *pUserData, int Weapon, bool Remove) { CGameContext *pSelf = (CGameContext *)pUserData; CCharacter *pChr = GetPlayerChar(pResult->m_ClientId); if(!pChr) return; if(std::clamp(Weapon, -1, NUM_WEAPONS - 1) != Weapon) { pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "info", "invalid weapon id"); return; } if(Weapon == -1) { pChr->GiveWeapon(WEAPON_SHOTGUN, Remove); pChr->GiveWeapon(WEAPON_GRENADE, Remove); pChr->GiveWeapon(WEAPON_LASER, Remove); } else { pChr->GiveWeapon(Weapon, Remove); } pChr->m_DDRaceState = ERaceState::CHEATED; } void CGameContext::Teleport(CCharacter *pChr, vec2 Pos) { pChr->SetPosition(Pos); pChr->m_Pos = Pos; pChr->m_PrevPos = Pos; pChr->m_DDRaceState = ERaceState::CHEATED; } void CGameContext::ConToTeleporter(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; unsigned int TeleTo = pResult->GetInteger(0); if(!pSelf->Collision()->TeleOuts(TeleTo - 1).empty()) { CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) { int TeleOut = pSelf->m_World.m_Core.RandomOr0(pSelf->Collision()->TeleOuts(TeleTo - 1).size()); pSelf->Teleport(pChr, pSelf->Collision()->TeleOuts(TeleTo - 1)[TeleOut]); } } } void CGameContext::ConToCheckTeleporter(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; unsigned int TeleTo = pResult->GetInteger(0); if(!pSelf->Collision()->TeleCheckOuts(TeleTo - 1).empty()) { CCharacter *pChr = pSelf->GetPlayerChar(pResult->m_ClientId); if(pChr) { int TeleOut = pSelf->m_World.m_Core.RandomOr0(pSelf->Collision()->TeleCheckOuts(TeleTo - 1).size()); pSelf->Teleport(pChr, pSelf->Collision()->TeleCheckOuts(TeleTo - 1)[TeleOut]); pChr->m_TeleCheckpoint = TeleTo; } } } void CGameContext::ConTeleport(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; int Tele = pResult->NumArguments() == 2 ? pResult->GetInteger(0) : pResult->m_ClientId; int TeleTo = pResult->NumArguments() ? pResult->GetInteger(pResult->NumArguments() - 1) : pResult->m_ClientId; int AuthLevel = pSelf->Server()->GetAuthedState(pResult->m_ClientId); if(Tele != pResult->m_ClientId && AuthLevel < g_Config.m_SvTeleOthersAuthLevel) { pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "tele", "you aren't allowed to tele others"); return; } CCharacter *pChr = pSelf->GetPlayerChar(Tele); CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId]; if(pChr && pPlayer && pSelf->GetPlayerChar(TeleTo)) { // default to view pos when character is not available vec2 Pos = pPlayer->m_ViewPos; if(pResult->NumArguments() == 0 && !pPlayer->IsPaused() && pChr->IsAlive()) { vec2 Target = vec2(pChr->Core()->m_Input.m_TargetX, pChr->Core()->m_Input.m_TargetY); Pos = pPlayer->m_CameraInfo.ConvertTargetToWorld(pChr->GetPos(), Target); } pSelf->Teleport(pChr, Pos); pChr->ResetJumps(); pChr->UnFreeze(); pChr->SetVelocity(vec2(0, 0)); } } void CGameContext::ConKill(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId]; if(!pPlayer || (pPlayer->m_LastKill && pPlayer->m_LastKill + pSelf->Server()->TickSpeed() * g_Config.m_SvKillDelay > pSelf->Server()->Tick())) return; pPlayer->m_LastKill = pSelf->Server()->Tick(); pPlayer->KillCharacter(WEAPON_SELF); } void CGameContext::ConForcePause(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Victim = pResult->GetVictim(); int Seconds = 0; if(pResult->NumArguments() > 1) Seconds = std::clamp(pResult->GetInteger(1), 0, 360); CPlayer *pPlayer = pSelf->m_apPlayers[Victim]; if(!pPlayer) return; pPlayer->ForcePause(Seconds); } void CGameContext::ConModerate(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; bool HadModerator = pSelf->PlayerModerating(); CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId]; pPlayer->m_Moderating = !pPlayer->m_Moderating; if(!HadModerator && pPlayer->m_Moderating) pSelf->SendChat(-1, TEAM_ALL, "Server kick/spec votes will now be actively moderated.", 0); if(!pSelf->PlayerModerating()) pSelf->SendChat(-1, TEAM_ALL, "Server kick/spec votes are no longer actively moderated.", 0); if(pPlayer->m_Moderating) pSelf->SendChatTarget(pResult->m_ClientId, "Active moderator mode enabled for you."); else pSelf->SendChatTarget(pResult->m_ClientId, "Active moderator mode disabled for you."); } void CGameContext::ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; auto *pController = pSelf->m_pController; if(g_Config.m_SvTeam == SV_TEAM_FORBIDDEN || g_Config.m_SvTeam == SV_TEAM_FORCED_SOLO) { pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "join", "Teams are disabled"); return; } int Target = pResult->GetVictim(); int Team = pResult->GetInteger(1); if(!pController->Teams().IsValidTeamNumber(Team)) return; CCharacter *pChr = pSelf->GetPlayerChar(Target); if((pSelf->GetDDRaceTeam(Target) && pController->Teams().GetDDRaceState(pSelf->m_apPlayers[Target]) == ERaceState::STARTED) || (pChr && pController->Teams().IsPractice(pChr->Team()))) pSelf->m_apPlayers[Target]->KillCharacter(WEAPON_GAME); pController->Teams().SetForceCharacterTeam(Target, Team); pController->Teams().SetTeamLock(Team, true); } void CGameContext::ConUninvite(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; auto *pController = pSelf->m_pController; pController->Teams().SetClientInvited(pResult->GetInteger(1), pResult->GetVictim(), false); } void CGameContext::ConVoteNo(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ForceVote(false); } void CGameContext::ConDrySave(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; if(!CheckClientId(pResult->m_ClientId)) return; CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId]; if(!pPlayer || !pSelf->Server()->IsRconAuthedAdmin(pResult->m_ClientId)) return; CSaveTeam SavedTeam; int Team = pSelf->GetDDRaceTeam(pResult->m_ClientId); ESaveResult Result = SavedTeam.Save(pSelf, Team, true); if(CSaveTeam::HandleSaveError(Result, pResult->m_ClientId, pSelf)) return; char aTimestamp[32]; str_timestamp(aTimestamp, sizeof(aTimestamp)); char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s_%s_%s.save", pSelf->Server()->GetMapName(), aTimestamp, pSelf->Server()->GetAuthName(pResult->m_ClientId)); IOHANDLE File = pSelf->Storage()->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(!File) return; int Len = str_length(SavedTeam.GetString()); io_write(File, SavedTeam.GetString(), Len); io_close(File); } void CGameContext::ConReloadCensorlist(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->ReadCensorList(); } void CGameContext::ConDumpAntibot(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->Antibot()->ConsoleCommand("dump"); } void CGameContext::ConAntibot(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; pSelf->Antibot()->ConsoleCommand(pResult->GetString(0)); } void CGameContext::ConDumpLog(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int LimitSecs = MAX_LOG_SECONDS; if(pResult->NumArguments() > 0) LimitSecs = pResult->GetInteger(0); if(LimitSecs < 0) return; int Iterator = pSelf->m_LatestLog; for(int i = 0; i < MAX_LOGS; i++) { CLog *pEntry = &pSelf->m_aLogs[Iterator]; Iterator = (Iterator + 1) % MAX_LOGS; if(!pEntry->m_Timestamp) continue; int Seconds = (time_get() - pEntry->m_Timestamp) / time_freq(); if(Seconds > LimitSecs) continue; char aBuf[sizeof(pEntry->m_aDescription) + 128]; if(pEntry->m_FromServer) str_format(aBuf, sizeof(aBuf), "%s, %d seconds ago", pEntry->m_aDescription, Seconds); else str_format(aBuf, sizeof(aBuf), "%s, %d seconds ago < addr=<{%s}> name='%s' client=%d", pEntry->m_aDescription, Seconds, pEntry->m_aClientAddrStr, pEntry->m_aClientName, pEntry->m_ClientVersion); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "log", aBuf); } } void CGameContext::LogEvent(const char *Description, int ClientId) { CLog *pNewEntry = &m_aLogs[m_LatestLog]; m_LatestLog = (m_LatestLog + 1) % MAX_LOGS; pNewEntry->m_Timestamp = time_get(); str_copy(pNewEntry->m_aDescription, Description); pNewEntry->m_FromServer = ClientId < 0; if(!pNewEntry->m_FromServer) { pNewEntry->m_ClientVersion = Server()->GetClientVersion(ClientId); str_copy(pNewEntry->m_aClientAddrStr, Server()->ClientAddrString(ClientId, false)); str_copy(pNewEntry->m_aClientName, Server()->ClientName(ClientId)); } }