1#include "antibot.h"
2
3#include <antibot/antibot_interface.h>
4
5#include <base/dbg.h>
6#include <base/mem.h>
7#include <base/str.h>
8#include <base/time.h>
9
10#include <engine/console.h>
11#include <engine/kernel.h>
12#include <engine/server.h>
13
14class IEngineAntibot;
15
16#ifdef CONF_ANTIBOT
17CAntibot::CAntibot() :
18 m_pServer(0), m_pConsole(0), m_pGameServer(0), m_Initialized(false)
19{
20}
21CAntibot::~CAntibot()
22{
23 if(m_pGameServer)
24 free(m_RoundData.m_Map.m_pTiles);
25
26 if(m_Initialized)
27 AntibotDestroy();
28}
29void CAntibot::Kick(int ClientId, const char *pMessage, void *pUser)
30{
31 CAntibot *pAntibot = (CAntibot *)pUser;
32 pAntibot->Server()->Kick(ClientId, pMessage);
33}
34void CAntibot::Log(const char *pMessage, void *pUser)
35{
36 CAntibot *pAntibot = (CAntibot *)pUser;
37 pAntibot->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "antibot", pMessage);
38}
39void CAntibot::Report(int ClientId, const char *pMessage, void *pUser)
40{
41 char aBuf[256];
42 str_format(aBuf, sizeof(aBuf), "%d: %s", ClientId, pMessage);
43 Log(aBuf, pUser);
44}
45void CAntibot::Send(int ClientId, const void *pData, int Size, int Flags, void *pUser)
46{
47 CAntibot *pAntibot = (CAntibot *)pUser;
48
49 int RealFlags = MSGFLAG_VITAL;
50 if(Flags & ANTIBOT_MSGFLAG_NONVITAL)
51 {
52 RealFlags &= ~MSGFLAG_VITAL;
53 }
54 if(Flags & ANTIBOT_MSGFLAG_FLUSH)
55 {
56 RealFlags |= MSGFLAG_FLUSH;
57 }
58 pAntibot->Server()->SendMsgRaw(ClientId, pData, Size, RealFlags);
59}
60void CAntibot::Teehistorian(const void *pData, int Size, void *pUser)
61{
62 CAntibot *pAntibot = (CAntibot *)pUser;
63 pAntibot->m_pGameServer->TeehistorianRecordAntibot(pData, Size);
64}
65void CAntibot::Init()
66{
67 m_pServer = Kernel()->RequestInterface<IServer>();
68 m_pConsole = Kernel()->RequestInterface<IConsole>();
69 dbg_assert(m_pServer && m_pConsole, "antibot requires server and console");
70 dbg_assert(AntibotAbiVersion() == ANTIBOT_ABI_VERSION, "antibot abi version mismatch (antibot=%d server=%d)", AntibotAbiVersion(), ANTIBOT_ABI_VERSION);
71
72 mem_zero(&m_Data, sizeof(m_Data));
73 CAntibotVersion Version = ANTIBOT_VERSION;
74 m_Data.m_Version = Version;
75
76 m_Data.m_Now = time_get();
77 m_Data.m_Freq = time_freq();
78 m_Data.m_pfnKick = Kick;
79 m_Data.m_pfnLog = Log;
80 m_Data.m_pfnReport = Report;
81 m_Data.m_pfnSend = Send;
82 m_Data.m_pfnTeehistorian = Teehistorian;
83 m_Data.m_pUser = this;
84 AntibotInit(&m_Data);
85
86 m_Initialized = true;
87}
88void CAntibot::RoundStart(IGameServer *pGameServer)
89{
90 m_pGameServer = pGameServer;
91 mem_zero(&m_RoundData, sizeof(m_RoundData));
92 m_RoundData.m_Map.m_pTiles = 0;
93 AntibotRoundStart(&m_RoundData);
94 Update();
95}
96void CAntibot::RoundEnd()
97{
98 // Let the external module clean up first
99 AntibotRoundEnd();
100
101 m_pGameServer = 0;
102 free(m_RoundData.m_Map.m_pTiles);
103}
104void CAntibot::ConsoleCommand(const char *pCommand)
105{
106 AntibotConsoleCommand(pCommand);
107}
108void CAntibot::Update()
109{
110 m_Data.m_Now = time_get();
111 m_Data.m_Freq = time_freq();
112
113 Server()->FillAntibot(&m_RoundData);
114 if(GameServer())
115 {
116 GameServer()->FillAntibot(&m_RoundData);
117 AntibotUpdateData();
118 }
119}
120
121void CAntibot::OnPlayerInit(int ClientId)
122{
123 Update();
124 AntibotOnPlayerInit(ClientId);
125}
126void CAntibot::OnPlayerDestroy(int ClientId)
127{
128 Update();
129 AntibotOnPlayerDestroy(ClientId);
130}
131void CAntibot::OnSpawn(int ClientId)
132{
133 Update();
134 AntibotOnSpawn(ClientId);
135}
136void CAntibot::OnHammerFireReloading(int ClientId)
137{
138 Update();
139 AntibotOnHammerFireReloading(ClientId);
140}
141void CAntibot::OnHammerFire(int ClientId)
142{
143 Update();
144 AntibotOnHammerFire(ClientId);
145}
146void CAntibot::OnHammerHit(int ClientId, int TargetId)
147{
148 Update();
149 AntibotOnHammerHit(ClientId, TargetId);
150}
151void CAntibot::OnDirectInput(int ClientId)
152{
153 Update();
154 AntibotOnDirectInput(ClientId);
155}
156void CAntibot::OnCharacterTick(int ClientId)
157{
158 Update();
159 AntibotOnCharacterTick(ClientId);
160}
161void CAntibot::OnHookAttach(int ClientId, bool Player)
162{
163 Update();
164 AntibotOnHookAttach(ClientId, Player);
165}
166
167void CAntibot::OnEngineTick()
168{
169 Update();
170 AntibotOnEngineTick();
171}
172void CAntibot::OnEngineClientJoin(int ClientId)
173{
174 Update();
175 AntibotOnEngineClientJoin(ClientId);
176}
177void CAntibot::OnEngineClientDrop(int ClientId, const char *pReason)
178{
179 Update();
180 AntibotOnEngineClientDrop(ClientId, pReason);
181}
182bool CAntibot::OnEngineClientMessage(int ClientId, const void *pData, int Size, int Flags)
183{
184 Update();
185 int AntibotFlags = 0;
186 if((Flags & MSGFLAG_VITAL) == 0)
187 {
188 AntibotFlags |= ANTIBOT_MSGFLAG_NONVITAL;
189 }
190 return AntibotOnEngineClientMessage(ClientId, pData, Size, AntibotFlags);
191}
192bool CAntibot::OnEngineServerMessage(int ClientId, const void *pData, int Size, int Flags)
193{
194 Update();
195 int AntibotFlags = 0;
196 if((Flags & MSGFLAG_VITAL) == 0)
197 {
198 AntibotFlags |= ANTIBOT_MSGFLAG_NONVITAL;
199 }
200 return AntibotOnEngineServerMessage(ClientId, pData, Size, AntibotFlags);
201}
202bool CAntibot::OnEngineSimulateClientMessage(int *pClientId, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags)
203{
204 int AntibotFlags = 0;
205 bool Result = AntibotOnEngineSimulateClientMessage(pClientId, pBuffer, BufferSize, pOutSize, &AntibotFlags);
206 if(Result)
207 {
208 *pFlags = 0;
209 if((AntibotFlags & ANTIBOT_MSGFLAG_NONVITAL) == 0)
210 {
211 *pFlags |= MSGFLAG_VITAL;
212 }
213 }
214 return Result;
215}
216#else
217CAntibot::CAntibot() :
218 m_pServer(nullptr), m_pConsole(nullptr), m_pGameServer(nullptr), m_Initialized(false)
219{
220}
221CAntibot::~CAntibot() = default;
222void CAntibot::Init()
223{
224 m_pServer = Kernel()->RequestInterface<IServer>();
225 m_pConsole = Kernel()->RequestInterface<IConsole>();
226 dbg_assert(m_pServer && m_pConsole, "antibot requires server and console");
227}
228void CAntibot::RoundStart(IGameServer *pGameServer)
229{
230 m_pGameServer = pGameServer;
231}
232void CAntibot::RoundEnd()
233{
234 m_pGameServer = nullptr;
235}
236void CAntibot::ConsoleCommand(const char *pCommand)
237{
238 if(str_comp(a: pCommand, b: "dump") == 0)
239 {
240 Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "antibot", pStr: "antibot support not compiled in");
241 }
242 else
243 {
244 Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "antibot", pStr: "unknown command");
245 }
246}
247void CAntibot::Update()
248{
249}
250
251void CAntibot::OnPlayerInit(int ClientId) {}
252void CAntibot::OnPlayerDestroy(int ClientId) {}
253void CAntibot::OnSpawn(int ClientId) {}
254void CAntibot::OnHammerFireReloading(int ClientId) {}
255void CAntibot::OnHammerFire(int ClientId) {}
256void CAntibot::OnHammerHit(int ClientId, int TargetId) {}
257void CAntibot::OnDirectInput(int ClientId) {}
258void CAntibot::OnCharacterTick(int ClientId) {}
259void CAntibot::OnHookAttach(int ClientId, bool Player) {}
260
261void CAntibot::OnEngineTick() {}
262void CAntibot::OnEngineClientJoin(int ClientId) {}
263void CAntibot::OnEngineClientDrop(int ClientId, const char *pReason) {}
264bool CAntibot::OnEngineClientMessage(int ClientId, const void *pData, int Size, int Flags) { return false; }
265bool CAntibot::OnEngineServerMessage(int ClientId, const void *pData, int Size, int Flags) { return false; }
266bool CAntibot::OnEngineSimulateClientMessage(int *pClientId, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags) { return false; }
267#endif
268
269IEngineAntibot *CreateEngineAntibot()
270{
271 return new CAntibot;
272}
273