1/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
2#include "gamecontext.h"
3
4#include <engine/antibot.h>
5#include <engine/shared/config.h>
6
7#include <game/server/entities/character.h>
8#include <game/server/gamemodes/DDRace.h>
9#include <game/server/player.h>
10#include <game/server/save.h>
11#include <game/server/teams.h>
12
13void CGameContext::ConGoLeft(IConsole::IResult *pResult, void *pUserData)
14{
15 CGameContext *pSelf = (CGameContext *)pUserData;
16 int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(Index: 0) : 1;
17
18 if(!CheckClientId(ClientId: pResult->m_ClientId))
19 return;
20 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: -1 * Tiles, Y: 0);
21}
22
23void CGameContext::ConGoRight(IConsole::IResult *pResult, void *pUserData)
24{
25 CGameContext *pSelf = (CGameContext *)pUserData;
26 int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(Index: 0) : 1;
27
28 if(!CheckClientId(ClientId: pResult->m_ClientId))
29 return;
30 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: Tiles, Y: 0);
31}
32
33void CGameContext::ConGoDown(IConsole::IResult *pResult, void *pUserData)
34{
35 CGameContext *pSelf = (CGameContext *)pUserData;
36 int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(Index: 0) : 1;
37
38 if(!CheckClientId(ClientId: pResult->m_ClientId))
39 return;
40 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: 0, Y: Tiles);
41}
42
43void CGameContext::ConGoUp(IConsole::IResult *pResult, void *pUserData)
44{
45 CGameContext *pSelf = (CGameContext *)pUserData;
46 int Tiles = pResult->NumArguments() == 1 ? pResult->GetInteger(Index: 0) : 1;
47
48 if(!CheckClientId(ClientId: pResult->m_ClientId))
49 return;
50 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: 0, Y: -1 * Tiles);
51}
52
53void CGameContext::ConMove(IConsole::IResult *pResult, void *pUserData)
54{
55 CGameContext *pSelf = (CGameContext *)pUserData;
56 if(!CheckClientId(ClientId: pResult->m_ClientId))
57 return;
58 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: pResult->GetInteger(Index: 0),
59 Y: pResult->GetInteger(Index: 1));
60}
61
62void CGameContext::ConMoveRaw(IConsole::IResult *pResult, void *pUserData)
63{
64 CGameContext *pSelf = (CGameContext *)pUserData;
65 if(!CheckClientId(ClientId: pResult->m_ClientId))
66 return;
67 pSelf->MoveCharacter(ClientId: pResult->m_ClientId, X: pResult->GetInteger(Index: 0),
68 Y: pResult->GetInteger(Index: 1), Raw: true);
69}
70
71void CGameContext::MoveCharacter(int ClientId, int X, int Y, bool Raw)
72{
73 CCharacter *pChr = GetPlayerChar(ClientId);
74
75 if(!pChr)
76 return;
77
78 pChr->Move(RelPos: vec2((Raw ? 1 : 32) * X, (Raw ? 1 : 32) * Y));
79 pChr->ResetVelocity();
80 pChr->m_DDRaceState = ERaceState::CHEATED;
81}
82
83void CGameContext::ConKillPlayer(IConsole::IResult *pResult, void *pUserData)
84{
85 CGameContext *pSelf = (CGameContext *)pUserData;
86 if(!CheckClientId(ClientId: pResult->m_ClientId))
87 return;
88 int Victim = pResult->GetVictim();
89
90 if(pSelf->m_apPlayers[Victim])
91 {
92 pSelf->m_apPlayers[Victim]->KillCharacter(Weapon: WEAPON_GAME);
93 char aBuf[512];
94 if(pResult->NumArguments() == 2)
95 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s was killed by authorized player (%s)",
96 pSelf->Server()->ClientName(ClientId: Victim),
97 pResult->GetString(Index: 1));
98 else
99 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s was killed by authorized player",
100 pSelf->Server()->ClientName(ClientId: Victim));
101 pSelf->SendChat(ClientId: -1, Team: TEAM_ALL, pText: aBuf);
102 }
103}
104
105void CGameContext::ConNinja(IConsole::IResult *pResult, void *pUserData)
106{
107 CGameContext *pSelf = (CGameContext *)pUserData;
108 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_NINJA, Remove: false);
109}
110
111void CGameContext::ConUnNinja(IConsole::IResult *pResult, void *pUserData)
112{
113 CGameContext *pSelf = (CGameContext *)pUserData;
114 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_NINJA, Remove: true);
115}
116
117void CGameContext::ConEndlessHook(IConsole::IResult *pResult, void *pUserData)
118{
119 CGameContext *pSelf = (CGameContext *)pUserData;
120 if(!CheckClientId(ClientId: pResult->m_ClientId))
121 return;
122 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
123 if(pChr)
124 {
125 pChr->SetEndlessHook(true);
126 }
127}
128
129void CGameContext::ConUnEndlessHook(IConsole::IResult *pResult, void *pUserData)
130{
131 CGameContext *pSelf = (CGameContext *)pUserData;
132 if(!CheckClientId(ClientId: pResult->m_ClientId))
133 return;
134 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
135 if(pChr)
136 {
137 pChr->SetEndlessHook(false);
138 }
139}
140
141void CGameContext::ConSuper(IConsole::IResult *pResult, void *pUserData)
142{
143 CGameContext *pSelf = (CGameContext *)pUserData;
144 if(!CheckClientId(ClientId: pResult->m_ClientId))
145 return;
146 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
147 if(pChr && !pChr->IsSuper())
148 {
149 pChr->SetSuper(true);
150 pChr->UnFreeze();
151 }
152}
153
154void CGameContext::ConUnSuper(IConsole::IResult *pResult, void *pUserData)
155{
156 CGameContext *pSelf = (CGameContext *)pUserData;
157 if(!CheckClientId(ClientId: pResult->m_ClientId))
158 return;
159 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
160 if(pChr && pChr->IsSuper())
161 {
162 pChr->SetSuper(false);
163 }
164}
165
166void CGameContext::ConToggleInvincible(IConsole::IResult *pResult, void *pUserData)
167{
168 CGameContext *pSelf = (CGameContext *)pUserData;
169 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
170 if(pChr)
171 pChr->SetInvincible(pResult->NumArguments() == 0 ? !pChr->Core()->m_Invincible : pResult->GetInteger(Index: 0));
172}
173
174void CGameContext::ConSolo(IConsole::IResult *pResult, void *pUserData)
175{
176 CGameContext *pSelf = (CGameContext *)pUserData;
177 if(!CheckClientId(ClientId: pResult->m_ClientId))
178 return;
179 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
180 if(pChr)
181 pChr->SetSolo(true);
182}
183
184void CGameContext::ConUnSolo(IConsole::IResult *pResult, void *pUserData)
185{
186 CGameContext *pSelf = (CGameContext *)pUserData;
187 if(!CheckClientId(ClientId: pResult->m_ClientId))
188 return;
189 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
190 if(pChr)
191 pChr->SetSolo(false);
192}
193
194void CGameContext::ConFreeze(IConsole::IResult *pResult, void *pUserData)
195{
196 CGameContext *pSelf = (CGameContext *)pUserData;
197 if(!CheckClientId(ClientId: pResult->m_ClientId))
198 return;
199 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
200 if(pChr)
201 pChr->Freeze();
202}
203
204void CGameContext::ConUnFreeze(IConsole::IResult *pResult, void *pUserData)
205{
206 CGameContext *pSelf = (CGameContext *)pUserData;
207 if(!CheckClientId(ClientId: pResult->m_ClientId))
208 return;
209 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
210 if(pChr)
211 pChr->UnFreeze();
212}
213
214void CGameContext::ConDeep(IConsole::IResult *pResult, void *pUserData)
215{
216 CGameContext *pSelf = (CGameContext *)pUserData;
217 if(!CheckClientId(ClientId: pResult->m_ClientId))
218 return;
219 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
220 if(pChr)
221 pChr->SetDeepFrozen(true);
222}
223
224void CGameContext::ConUnDeep(IConsole::IResult *pResult, void *pUserData)
225{
226 CGameContext *pSelf = (CGameContext *)pUserData;
227 if(!CheckClientId(ClientId: pResult->m_ClientId))
228 return;
229 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
230 if(pChr)
231 {
232 pChr->SetDeepFrozen(false);
233 pChr->UnFreeze();
234 }
235}
236
237void CGameContext::ConLiveFreeze(IConsole::IResult *pResult, void *pUserData)
238{
239 CGameContext *pSelf = (CGameContext *)pUserData;
240 if(!CheckClientId(ClientId: pResult->m_ClientId))
241 return;
242 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
243 if(pChr)
244 pChr->SetLiveFrozen(true);
245}
246
247void CGameContext::ConUnLiveFreeze(IConsole::IResult *pResult, void *pUserData)
248{
249 CGameContext *pSelf = (CGameContext *)pUserData;
250 if(!CheckClientId(ClientId: pResult->m_ClientId))
251 return;
252 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
253 if(pChr)
254 pChr->SetLiveFrozen(false);
255}
256
257void CGameContext::ConShotgun(IConsole::IResult *pResult, void *pUserData)
258{
259 CGameContext *pSelf = (CGameContext *)pUserData;
260 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_SHOTGUN, Remove: false);
261}
262
263void CGameContext::ConGrenade(IConsole::IResult *pResult, void *pUserData)
264{
265 CGameContext *pSelf = (CGameContext *)pUserData;
266 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_GRENADE, Remove: false);
267}
268
269void CGameContext::ConLaser(IConsole::IResult *pResult, void *pUserData)
270{
271 CGameContext *pSelf = (CGameContext *)pUserData;
272 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_LASER, Remove: false);
273}
274
275void CGameContext::ConJetpack(IConsole::IResult *pResult, void *pUserData)
276{
277 CGameContext *pSelf = (CGameContext *)pUserData;
278 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
279 if(pChr)
280 pChr->SetJetpack(true);
281}
282
283void CGameContext::ConEndlessJump(IConsole::IResult *pResult, void *pUserData)
284{
285 CGameContext *pSelf = (CGameContext *)pUserData;
286 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
287 if(pChr)
288 pChr->SetEndlessJump(true);
289}
290
291void CGameContext::ConSetJumps(IConsole::IResult *pResult, void *pUserData)
292{
293 CGameContext *pSelf = (CGameContext *)pUserData;
294 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
295 if(pChr)
296 pChr->SetJumps(pResult->GetInteger(Index: 0));
297}
298
299void CGameContext::ConWeapons(IConsole::IResult *pResult, void *pUserData)
300{
301 CGameContext *pSelf = (CGameContext *)pUserData;
302 pSelf->ModifyWeapons(pResult, pUserData, Weapon: -1, Remove: false);
303}
304
305void CGameContext::ConUnShotgun(IConsole::IResult *pResult, void *pUserData)
306{
307 CGameContext *pSelf = (CGameContext *)pUserData;
308 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_SHOTGUN, Remove: true);
309}
310
311void CGameContext::ConUnGrenade(IConsole::IResult *pResult, void *pUserData)
312{
313 CGameContext *pSelf = (CGameContext *)pUserData;
314 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_GRENADE, Remove: true);
315}
316
317void CGameContext::ConUnLaser(IConsole::IResult *pResult, void *pUserData)
318{
319 CGameContext *pSelf = (CGameContext *)pUserData;
320 pSelf->ModifyWeapons(pResult, pUserData, Weapon: WEAPON_LASER, Remove: true);
321}
322
323void CGameContext::ConUnJetpack(IConsole::IResult *pResult, void *pUserData)
324{
325 CGameContext *pSelf = (CGameContext *)pUserData;
326 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
327 if(pChr)
328 pChr->SetJetpack(false);
329}
330
331void CGameContext::ConUnEndlessJump(IConsole::IResult *pResult, void *pUserData)
332{
333 CGameContext *pSelf = (CGameContext *)pUserData;
334 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
335 if(pChr)
336 pChr->SetEndlessJump(false);
337}
338
339void CGameContext::ConUnWeapons(IConsole::IResult *pResult, void *pUserData)
340{
341 CGameContext *pSelf = (CGameContext *)pUserData;
342 pSelf->ModifyWeapons(pResult, pUserData, Weapon: -1, Remove: true);
343}
344
345void CGameContext::ConAddWeapon(IConsole::IResult *pResult, void *pUserData)
346{
347 CGameContext *pSelf = (CGameContext *)pUserData;
348 pSelf->ModifyWeapons(pResult, pUserData, Weapon: pResult->GetInteger(Index: 0), Remove: false);
349}
350
351void CGameContext::ConRemoveWeapon(IConsole::IResult *pResult, void *pUserData)
352{
353 CGameContext *pSelf = (CGameContext *)pUserData;
354 pSelf->ModifyWeapons(pResult, pUserData, Weapon: pResult->GetInteger(Index: 0), Remove: true);
355}
356
357void CGameContext::ModifyWeapons(IConsole::IResult *pResult, void *pUserData,
358 int Weapon, bool Remove)
359{
360 CGameContext *pSelf = (CGameContext *)pUserData;
361 CCharacter *pChr = GetPlayerChar(ClientId: pResult->m_ClientId);
362 if(!pChr)
363 return;
364
365 if(std::clamp(val: Weapon, lo: -1, hi: NUM_WEAPONS - 1) != Weapon)
366 {
367 pSelf->Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "info",
368 pStr: "invalid weapon id");
369 return;
370 }
371
372 if(Weapon == -1)
373 {
374 pChr->GiveWeapon(Weapon: WEAPON_SHOTGUN, Remove);
375 pChr->GiveWeapon(Weapon: WEAPON_GRENADE, Remove);
376 pChr->GiveWeapon(Weapon: WEAPON_LASER, Remove);
377 }
378 else
379 {
380 pChr->GiveWeapon(Weapon, Remove);
381 }
382
383 pChr->m_DDRaceState = ERaceState::CHEATED;
384}
385
386void CGameContext::Teleport(CCharacter *pChr, vec2 Pos)
387{
388 pChr->SetPosition(Pos);
389 pChr->m_Pos = Pos;
390 pChr->m_PrevPos = Pos;
391 pChr->m_DDRaceState = ERaceState::CHEATED;
392}
393
394void CGameContext::ConToTeleporter(IConsole::IResult *pResult, void *pUserData)
395{
396 CGameContext *pSelf = (CGameContext *)pUserData;
397 unsigned int TeleTo = pResult->GetInteger(Index: 0);
398
399 if(!pSelf->Collision()->TeleOuts(Number: TeleTo - 1).empty())
400 {
401 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
402 if(pChr)
403 {
404 int TeleOut = pSelf->m_World.m_Core.RandomOr0(BelowThis: pSelf->Collision()->TeleOuts(Number: TeleTo - 1).size());
405 pSelf->Teleport(pChr, Pos: pSelf->Collision()->TeleOuts(Number: TeleTo - 1)[TeleOut]);
406 }
407 }
408}
409
410void CGameContext::ConToCheckTeleporter(IConsole::IResult *pResult, void *pUserData)
411{
412 CGameContext *pSelf = (CGameContext *)pUserData;
413 unsigned int TeleTo = pResult->GetInteger(Index: 0);
414
415 if(!pSelf->Collision()->TeleCheckOuts(Number: TeleTo - 1).empty())
416 {
417 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: pResult->m_ClientId);
418 if(pChr)
419 {
420 int TeleOut = pSelf->m_World.m_Core.RandomOr0(BelowThis: pSelf->Collision()->TeleCheckOuts(Number: TeleTo - 1).size());
421 pSelf->Teleport(pChr, Pos: pSelf->Collision()->TeleCheckOuts(Number: TeleTo - 1)[TeleOut]);
422 pChr->m_TeleCheckpoint = TeleTo;
423 }
424 }
425}
426
427void CGameContext::ConTeleport(IConsole::IResult *pResult, void *pUserData)
428{
429 CGameContext *pSelf = (CGameContext *)pUserData;
430 int Tele = pResult->NumArguments() == 2 ? pResult->GetInteger(Index: 0) : pResult->m_ClientId;
431 int TeleTo = pResult->NumArguments() ? pResult->GetInteger(Index: pResult->NumArguments() - 1) : pResult->m_ClientId;
432 int AuthLevel = pSelf->Server()->GetAuthedState(ClientId: pResult->m_ClientId);
433
434 if(Tele != pResult->m_ClientId && AuthLevel < g_Config.m_SvTeleOthersAuthLevel)
435 {
436 pSelf->Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "tele", pStr: "you aren't allowed to tele others");
437 return;
438 }
439
440 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: Tele);
441 CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId];
442
443 if(pChr && pPlayer && pSelf->GetPlayerChar(ClientId: TeleTo))
444 {
445 // default to view pos when character is not available
446 vec2 Pos = pPlayer->m_ViewPos;
447 if(pResult->NumArguments() == 0 && !pPlayer->IsPaused() && pChr->IsAlive())
448 {
449 vec2 Target = vec2(pChr->Core()->m_Input.m_TargetX, pChr->Core()->m_Input.m_TargetY);
450 Pos = pPlayer->m_CameraInfo.ConvertTargetToWorld(Position: pChr->GetPos(), Target);
451 }
452 pSelf->Teleport(pChr, Pos);
453 pChr->ResetJumps();
454 pChr->UnFreeze();
455 pChr->SetVelocity(vec2(0, 0));
456 }
457}
458
459void CGameContext::ConKill(IConsole::IResult *pResult, void *pUserData)
460{
461 CGameContext *pSelf = (CGameContext *)pUserData;
462 if(!CheckClientId(ClientId: pResult->m_ClientId))
463 return;
464 CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId];
465
466 if(!pPlayer || (pPlayer->m_LastKill && pPlayer->m_LastKill + pSelf->Server()->TickSpeed() * g_Config.m_SvKillDelay > pSelf->Server()->Tick()))
467 return;
468
469 pPlayer->m_LastKill = pSelf->Server()->Tick();
470 pPlayer->KillCharacter(Weapon: WEAPON_SELF);
471}
472
473void CGameContext::ConForcePause(IConsole::IResult *pResult, void *pUserData)
474{
475 CGameContext *pSelf = (CGameContext *)pUserData;
476 int Victim = pResult->GetVictim();
477 int Seconds = 0;
478 if(pResult->NumArguments() > 1)
479 Seconds = std::clamp(val: pResult->GetInteger(Index: 1), lo: 0, hi: 360);
480
481 CPlayer *pPlayer = pSelf->m_apPlayers[Victim];
482 if(!pPlayer)
483 return;
484
485 pPlayer->ForcePause(Time: Seconds);
486}
487
488void CGameContext::ConModerate(IConsole::IResult *pResult, void *pUserData)
489{
490 CGameContext *pSelf = (CGameContext *)pUserData;
491 if(!CheckClientId(ClientId: pResult->m_ClientId))
492 return;
493
494 bool HadModerator = pSelf->PlayerModerating();
495
496 CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId];
497 pPlayer->m_Moderating = !pPlayer->m_Moderating;
498
499 if(!HadModerator && pPlayer->m_Moderating)
500 pSelf->SendChat(ClientId: -1, Team: TEAM_ALL, pText: "Server kick/spec votes will now be actively moderated.", SpamProtectionClientId: 0);
501
502 if(!pSelf->PlayerModerating())
503 pSelf->SendChat(ClientId: -1, Team: TEAM_ALL, pText: "Server kick/spec votes are no longer actively moderated.", SpamProtectionClientId: 0);
504
505 if(pPlayer->m_Moderating)
506 pSelf->SendChatTarget(To: pResult->m_ClientId, pText: "Active moderator mode enabled for you.");
507 else
508 pSelf->SendChatTarget(To: pResult->m_ClientId, pText: "Active moderator mode disabled for you.");
509}
510
511void CGameContext::ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData)
512{
513 CGameContext *pSelf = (CGameContext *)pUserData;
514 auto *pController = pSelf->m_pController;
515
516 if(g_Config.m_SvTeam == SV_TEAM_FORBIDDEN || g_Config.m_SvTeam == SV_TEAM_FORCED_SOLO)
517 {
518 pSelf->Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "join",
519 pStr: "Teams are disabled");
520 return;
521 }
522
523 int Target = pResult->GetVictim();
524 int Team = pResult->GetInteger(Index: 1);
525
526 if(!pController->Teams().IsValidTeamNumber(Team))
527 return;
528
529 CCharacter *pChr = pSelf->GetPlayerChar(ClientId: Target);
530
531 if((pSelf->GetDDRaceTeam(ClientId: Target) && pController->Teams().GetDDRaceState(Player: pSelf->m_apPlayers[Target]) == ERaceState::STARTED) || (pChr && pController->Teams().IsPractice(Team: pChr->Team())))
532 pSelf->m_apPlayers[Target]->KillCharacter(Weapon: WEAPON_GAME);
533
534 pController->Teams().SetForceCharacterTeam(ClientId: Target, Team);
535 pController->Teams().SetTeamLock(Team, Lock: true);
536}
537
538void CGameContext::ConUninvite(IConsole::IResult *pResult, void *pUserData)
539{
540 CGameContext *pSelf = (CGameContext *)pUserData;
541 auto *pController = pSelf->m_pController;
542
543 pController->Teams().SetClientInvited(Team: pResult->GetInteger(Index: 1), ClientId: pResult->GetVictim(), Invited: false);
544}
545
546void CGameContext::ConVoteNo(IConsole::IResult *pResult, void *pUserData)
547{
548 CGameContext *pSelf = (CGameContext *)pUserData;
549
550 pSelf->ForceVote(EnforcerId: pResult->m_ClientId, Success: false);
551}
552
553void CGameContext::ConDrySave(IConsole::IResult *pResult, void *pUserData)
554{
555 CGameContext *pSelf = (CGameContext *)pUserData;
556
557 CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId];
558
559 if(!pPlayer || !pSelf->Server()->IsRconAuthedAdmin(ClientId: pResult->m_ClientId))
560 return;
561
562 CSaveTeam SavedTeam;
563 int Team = pSelf->GetDDRaceTeam(ClientId: pResult->m_ClientId);
564 ESaveResult Result = SavedTeam.Save(pGameServer: pSelf, Team, Dry: true);
565 if(CSaveTeam::HandleSaveError(Result, ClientId: pResult->m_ClientId, pGameContext: pSelf))
566 return;
567
568 char aTimestamp[32];
569 str_timestamp(buffer: aTimestamp, buffer_size: sizeof(aTimestamp));
570 char aBuf[64];
571 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s_%s_%s.save", pSelf->Server()->GetMapName(), aTimestamp, pSelf->Server()->GetAuthName(ClientId: pResult->m_ClientId));
572 IOHANDLE File = pSelf->Storage()->OpenFile(pFilename: aBuf, Flags: IOFLAG_WRITE, Type: IStorage::TYPE_SAVE);
573 if(!File)
574 return;
575
576 int Len = str_length(str: SavedTeam.GetString());
577 io_write(io: File, buffer: SavedTeam.GetString(), size: Len);
578 io_close(io: File);
579}
580
581void CGameContext::ConReloadCensorlist(IConsole::IResult *pResult, void *pUserData)
582{
583 CGameContext *pSelf = (CGameContext *)pUserData;
584 pSelf->ReadCensorList();
585}
586
587void CGameContext::ConDumpAntibot(IConsole::IResult *pResult, void *pUserData)
588{
589 CGameContext *pSelf = (CGameContext *)pUserData;
590 pSelf->Antibot()->ConsoleCommand(pCommand: "dump");
591}
592
593void CGameContext::ConAntibot(IConsole::IResult *pResult, void *pUserData)
594{
595 CGameContext *pSelf = (CGameContext *)pUserData;
596 pSelf->Antibot()->ConsoleCommand(pCommand: pResult->GetString(Index: 0));
597}
598
599void CGameContext::ConDumpLog(IConsole::IResult *pResult, void *pUserData)
600{
601 CGameContext *pSelf = (CGameContext *)pUserData;
602 int LimitSecs = MAX_LOG_SECONDS;
603 if(pResult->NumArguments() > 0)
604 LimitSecs = pResult->GetInteger(Index: 0);
605
606 if(LimitSecs < 0)
607 return;
608
609 int Iterator = pSelf->m_LatestLog;
610 for(int i = 0; i < MAX_LOGS; i++)
611 {
612 CLog *pEntry = &pSelf->m_aLogs[Iterator];
613 Iterator = (Iterator + 1) % MAX_LOGS;
614
615 if(!pEntry->m_Timestamp)
616 continue;
617
618 int Seconds = (time_get() - pEntry->m_Timestamp) / time_freq();
619 if(Seconds > LimitSecs)
620 continue;
621
622 char aBuf[sizeof(pEntry->m_aDescription) + 128];
623 if(pEntry->m_FromServer)
624 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s, %d seconds ago", pEntry->m_aDescription, Seconds);
625 else
626 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s, %d seconds ago < addr=<{%s}> name='%s' client=%d",
627 pEntry->m_aDescription, Seconds, pEntry->m_aClientAddrStr, pEntry->m_aClientName, pEntry->m_ClientVersion);
628 pSelf->Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "log", pStr: aBuf);
629 }
630}
631
632void CGameContext::LogEvent(const char *Description, int ClientId)
633{
634 CLog *pNewEntry = &m_aLogs[m_LatestLog];
635 m_LatestLog = (m_LatestLog + 1) % MAX_LOGS;
636
637 pNewEntry->m_Timestamp = time_get();
638 str_copy(dst&: pNewEntry->m_aDescription, src: Description);
639 pNewEntry->m_FromServer = ClientId < 0;
640 if(!pNewEntry->m_FromServer)
641 {
642 pNewEntry->m_ClientVersion = Server()->GetClientVersion(ClientId);
643 str_copy(dst&: pNewEntry->m_aClientAddrStr, src: Server()->ClientAddrString(ClientId, IncludePort: false));
644 str_copy(dst&: pNewEntry->m_aClientName, src: Server()->ClientName(ClientId));
645 }
646}
647