1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 #include "C4Include.h"
17 
18 #include "C4Version.h"
19 #include "control/C4RoundResults.h"
20 #include "gui/C4GameLobby.h"
21 #include "network/C4GameControlNetwork.h"
22 #include "network/C4Network2.h"
23 #include "network/C4Network2Res.h"
24 
25 // *** constants
26 
27 // workaround
28 template <class T> struct unpack_class
29 {
unpackunpack_class30 	static C4PacketBase *unpack(StdCompiler *pComp)
31 	{
32 		assert(pComp->isDeserializer());
33 		T *pPkt = new T();
34 		try
35 		{
36 			pComp->Value(*pPkt);
37 		}
38 		catch (...)
39 		{
40 			delete pPkt;
41 			throw;
42 		}
43 		return pPkt;
44 	}
45 };
46 
47 #define PKT_UNPACK(T) unpack_class<T>::unpack
48 
49 
50 const C4PktHandlingData PktHandlingData[] =
51 {
52 
53 	// C4Network2IO (network thread)
54 	{ PID_Conn,         PC_Network, "Connection Request",         true,   true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketConn)        },
55 	{ PID_ConnRe,       PC_Network, "Connection Request Reply",   true,   true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketConnRe)      },
56 
57 	{ PID_Ping,         PC_Network, "Ping",                       true,   true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketPing)        },
58 	{ PID_Pong,         PC_Network, "Pong",                       true,   true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketPing)        },
59 
60 	{ PID_FwdReq,       PC_Network, "Forward Request",            false,  true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketFwd)         },
61 	{ PID_Fwd,          PC_Network, "Forward",                    false,  true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketFwd)         },
62 
63 	{ PID_PostMortem,   PC_Network, "Post Mortem",                false,  true,   PH_C4Network2IO,          PKT_UNPACK(C4PacketPostMortem)  },
64 
65 	// C4Network2 (main thread)
66 	{ PID_Conn,         PC_Network, "Connection Request",         true,   false,  PH_C4Network2,            PKT_UNPACK(C4PacketConn)        },
67 	{ PID_ConnRe,       PC_Network, "Connection Request Reply",   true,   false,  PH_C4Network2,            PKT_UNPACK(C4PacketConnRe)      },
68 
69 	{ PID_Status,       PC_Network, "Game Status",                true,   false,  PH_C4Network2,            PKT_UNPACK(C4Network2Status)    },
70 	{ PID_StatusAck,    PC_Network, "Game Status Acknowledgement",true,   false,  PH_C4Network2,            PKT_UNPACK(C4Network2Status)    },
71 
72 	{ PID_ClientActReq, PC_Network, "Client Activation Request",  false,  false,  PH_C4Network2,            PKT_UNPACK(C4PacketActivateReq) },
73 
74 	{ PID_JoinData,     PC_Network, "Join Data",                  false,  false,  PH_C4Network2,            PKT_UNPACK(C4PacketJoinData)    },
75 
76 	// C4Network2PlayerList (main thread)
77 	{ PID_PlayerInfoUpdReq,PC_Network, "Player info update request",true, false,  PH_C4Network2Players,     PKT_UNPACK(C4PacketPlayerInfoUpdRequest)  },
78 
79 	{ PID_LeagueRoundResults,PC_Network, "League round results",   true,  false,  PH_C4Network2Players,     PKT_UNPACK(C4PacketLeagueRoundResults)  },
80 
81 	// C4GameLobby (main thread)
82 	{ PID_LobbyCountdown,PC_Network,"Lobby countdown",            false,  false,  PH_C4GUIMainDlg,          PKT_UNPACK(C4GameLobby::C4PacketCountdown)  },
83 	{ PID_SetScenarioParameter,PC_Network,"Scenario parameter",   false,  false,  PH_C4GUIMainDlg,          PKT_UNPACK(C4GameLobby::C4PacketSetScenarioParameter)  },
84 
85 	// C4Network2ClientList (main thread)
86 	{ PID_Addr,         PC_Network, "Client Address",             false,  false,  PH_C4Network2ClientList,  PKT_UNPACK(C4PacketAddr)        },
87 
88 
89 	// C4Network2ResList (network thread)
90 	{ PID_NetResDis,    PC_Network, "Resource Discover",          true,   true,   PH_C4Network2ResList,     PKT_UNPACK(C4PacketResDiscover) },
91 	{ PID_NetResStat,   PC_Network, "Resource Status",            false,  true,   PH_C4Network2ResList,     PKT_UNPACK(C4PacketResStatus)   },
92 	{ PID_NetResDerive, PC_Network, "Resource Derive",            false,  true,   PH_C4Network2ResList,     PKT_UNPACK(C4Network2ResCore)   },
93 	{ PID_NetResReq,    PC_Network, "Resource Request",           false,  true,   PH_C4Network2ResList,     PKT_UNPACK(C4PacketResRequest)  },
94 	{ PID_NetResData,   PC_Network, "Resource Data",              false,  true,   PH_C4Network2ResList,     PKT_UNPACK(C4Network2ResChunk)  },
95 
96 	// C4GameControlNetwork (network thread)
97 	{ PID_Control,      PC_Network, "Control",                    false,  true,   PH_C4GameControlNetwork,  PKT_UNPACK(C4GameControlPacket) },
98 	{ PID_ControlReq,   PC_Network, "Control Request",            false,  true,   PH_C4GameControlNetwork,  PKT_UNPACK(C4PacketControlReq)  },
99 	//                       main thread
100 	{ PID_ControlPkt,   PC_Network, "Control Paket",              false,  false,  PH_C4GameControlNetwork,  PKT_UNPACK(C4PacketControlPkt)  },
101 	{ PID_ExecSyncCtrl, PC_Network, "Execute Sync Control",       false,  false,  PH_C4GameControlNetwork,  PKT_UNPACK(C4PacketExecSyncCtrl)},
102 
103 	// Control (Isn't send over network, handled only as part of a control list)
104 	{ CID_ClientJoin,   PC_Control, "Client Join",                false,  true,   0,                        PKT_UNPACK(C4ControlClientJoin) },
105 	{ CID_ClientUpdate, PC_Control, "Client Update",              false,  true,   0,                        PKT_UNPACK(C4ControlClientUpdate)},
106 	{ CID_ClientRemove, PC_Control, "Client Remove",              false,  true,   0,                        PKT_UNPACK(C4ControlClientRemove)},
107 	{ CID_Vote,         PC_Control, "Voting",                     false,  true,   0,                        PKT_UNPACK(C4ControlVote)       },
108 	{ CID_VoteEnd,      PC_Control, "Voting End",                 false,  true,   0,                        PKT_UNPACK(C4ControlVoteEnd)    },
109 	{ CID_SyncCheck,    PC_Control, "Sync Check",                 false,  true,   0,                        PKT_UNPACK(C4ControlSyncCheck)  },
110 	{ CID_Synchronize,  PC_Control, "Synchronize",                false,  true,   0,                        PKT_UNPACK(C4ControlSynchronize)},
111 	{ CID_Set,          PC_Control, "Set",                        false,  true,   0,                        PKT_UNPACK(C4ControlSet)        },
112 	{ CID_Script,       PC_Control, "Script",                     false,  true,   0,                        PKT_UNPACK(C4ControlScript)     },
113 	{ CID_MsgBoardReply,PC_Control, "Message Board Reply",        false,  true,   0,                        PKT_UNPACK(C4ControlMsgBoardReply)},
114 	{ CID_MsgBoardCmd  ,PC_Control, "Message Board Command",      false,  true,   0,                        PKT_UNPACK(C4ControlMsgBoardCmd)},
115 	{ CID_PlrInfo,      PC_Control, "Player Info",                false,  true,   0,                        PKT_UNPACK(C4ControlPlayerInfo) },
116 	{ CID_JoinPlr,      PC_Control, "Join Player",                false,  true,   0,                        PKT_UNPACK(C4ControlJoinPlayer) },
117 	{ CID_RemovePlr,    PC_Control, "Remove Player",              false,  true,   0,                        PKT_UNPACK(C4ControlRemovePlr)  },
118 	{ CID_PlrSelect,    PC_Control, "Player Select",              false,  true,   0,                        PKT_UNPACK(C4ControlPlayerSelect)},
119 	{ CID_PlrControl,   PC_Control, "Player Control",             false,  true,   0,                        PKT_UNPACK(C4ControlPlayerControl)},
120 	{ CID_PlrAction,    PC_Control, "Player Self-Mgmt Action",    false,  true,   0,                        PKT_UNPACK(C4ControlPlayerAction)},
121 	{ CID_PlrMouseMove, PC_Control, "Player Mouse Movement",      false,  true,   0,                        PKT_UNPACK(C4ControlPlayerMouse)},
122 	{ CID_Message,      PC_Control, "Message",                    false,  true,   0,                        PKT_UNPACK(C4ControlMessage)    },
123 	{ CID_MenuCommand,   PC_Control, "Menu Command",              false,  true,   0,                        PKT_UNPACK(C4ControlMenuCommand)},
124 	{ CID_EMMoveObj,    PC_Control, "EM Move Obj",                false,  true,   0,                        PKT_UNPACK(C4ControlEMMoveObject)},
125 	{ CID_EMDrawTool,   PC_Control, "EM Draw Tool",               false,  true,   0,                        PKT_UNPACK(C4ControlEMDrawTool) },
126 	{ CID_ReInitScenario,PC_Control, "Reinit Scenario",           false,  true,   0,                        PKT_UNPACK(C4ControlReInitScenario) },
127 	{ CID_EditGraph,    PC_Control, "Edit Graph",                 false,  true,   0,                        PKT_UNPACK(C4ControlEditGraph)  },
128 
129 	{ CID_DebugRec,     PC_Control, "Debug Rec",                  false,  true,   0,                        PKT_UNPACK(C4ControlDebugRec)   },
130 
131 	// EOL
132 	{ PID_None,         PC_Network, nullptr,                         false,  true,   0,                        nullptr                            }
133 };
134 
PacketNameByID(C4PacketType eID)135 const char *PacketNameByID(C4PacketType eID)
136 {
137 	for (const C4PktHandlingData *pPData = PktHandlingData; pPData->ID != PID_None; pPData++)
138 		if (pPData->ID == eID)
139 			return pPData->Name;
140 	return "?!?";
141 }
142 
143 // *** C4PacketBase
144 
145 C4PacketBase::C4PacketBase() = default;
146 
147 C4PacketBase::~C4PacketBase() = default;
148 
pack(const C4NetIO::addr_t & addr) const149 C4NetIOPacket C4PacketBase::pack(const C4NetIO::addr_t &addr) const
150 {
151 	return C4NetIOPacket(DecompileToBuf<StdCompilerBinWrite>(*this), addr);
152 }
153 
pack(uint8_t cStatus,const C4NetIO::addr_t & addr) const154 C4NetIOPacket C4PacketBase::pack(uint8_t cStatus, const C4NetIO::addr_t &addr) const
155 {
156 	return C4NetIOPacket(DecompileToBuf<StdCompilerBinWrite>(mkInsertAdapt(mkDecompileAdapt(*this), cStatus)), addr);
157 }
158 
unpack(const C4NetIOPacket & Pkt,char * pStatus)159 void C4PacketBase::unpack(const C4NetIOPacket &Pkt, char *pStatus)
160 {
161 	if (pStatus) *pStatus = Pkt.getStatus();
162 	CompileFromBuf<StdCompilerBinRead>(*this, pStatus ? Pkt.getPBuf() : Pkt.getRef());
163 }
164 
165 
166 // *** C4PktBuf
167 
168 C4PktBuf::C4PktBuf() = default;
169 
C4PktBuf(const C4PktBuf & rCopy)170 C4PktBuf::C4PktBuf(const C4PktBuf &rCopy) : C4PacketBase(rCopy)
171 {
172 	Data.Copy(rCopy.Data);
173 }
174 
C4PktBuf(const StdBuf & rCpyData)175 C4PktBuf::C4PktBuf(const StdBuf &rCpyData)
176 {
177 	Data.Copy(rCpyData);
178 }
179 
CompileFunc(StdCompiler * pComp)180 void C4PktBuf::CompileFunc(StdCompiler *pComp)
181 {
182 	pComp->Value(mkNamingAdapt(Data, "Data"));
183 }
184 
185 // *** C4IDPacket
186 
187 C4IDPacket::C4IDPacket() = default;
188 
C4IDPacket(C4PacketType eID,C4PacketBase * pPkt,bool fTakePkt)189 C4IDPacket::C4IDPacket(C4PacketType eID, C4PacketBase *pPkt, bool fTakePkt)
190 		: eID(eID), pPkt(pPkt), fOwnPkt(fTakePkt), pNext(nullptr)
191 {
192 
193 }
194 
C4IDPacket(const C4IDPacket & Packet2)195 C4IDPacket::C4IDPacket(const C4IDPacket &Packet2)
196 		: C4PacketBase(Packet2)
197 {
198 	// kinda hacky (note this might throw an uncaught exception)
199 	C4PacketBase::unpack(Packet2.C4PacketBase::pack());
200 }
201 
~C4IDPacket()202 C4IDPacket::~C4IDPacket()
203 {
204 	Clear();
205 }
206 
getPktName() const207 const char *C4IDPacket::getPktName() const
208 {
209 	// Use map
210 	for (const C4PktHandlingData *pPData = PktHandlingData; pPData->ID != PID_None; pPData++)
211 		if (pPData->ID == eID && pPData->Name)
212 			return pPData->Name;
213 	return "Unknown Packet Type";
214 }
215 
Default()216 void C4IDPacket::Default()
217 {
218 	eID = PID_None; pPkt = nullptr;
219 }
220 
Clear()221 void C4IDPacket::Clear()
222 {
223 	if (fOwnPkt) delete pPkt; pPkt = nullptr;
224 	eID = PID_None;
225 }
226 
CompileFunc(StdCompiler * pComp)227 void C4IDPacket::CompileFunc(StdCompiler *pComp)
228 {
229 	// Packet ID
230 	pComp->Value(mkNamingAdapt(mkIntAdaptT<uint8_t>(eID), "ID", PID_None));
231 	// Compiling or Decompiling?
232 	if (pComp->isDeserializer())
233 	{
234 		if (!pComp->Name(getPktName()))
235 			{ pComp->excCorrupt("C4IDPacket: Data value needed! Packet data missing!"); return; }
236 		// Delete old packet
237 		if (fOwnPkt) delete pPkt; pPkt = nullptr;
238 		if (eID == PID_None) return;
239 		// Search unpacking function
240 		for (const C4PktHandlingData *pPData = PktHandlingData; pPData->ID != PID_None; pPData++)
241 			if (pPData->ID == eID && pPData->FnUnpack)
242 			{
243 				pPkt = pPData->FnUnpack(pComp);
244 				break;
245 			}
246 		if (!pPkt)
247 			pComp->excCorrupt("C4IDPacket: could not unpack packet id %02x!", eID);
248 		pComp->NameEnd();
249 	}
250 	else if (eID != PID_None)
251 		// Just write
252 		pComp->Value(mkNamingAdapt(*pPkt, getPktName()));
253 }
254 
255 // *** C4PacketList
256 
257 C4PacketList::C4PacketList() = default;
258 
C4PacketList(const C4PacketList & List2)259 C4PacketList::C4PacketList(const C4PacketList &List2)
260 		: C4PacketBase(List2),
261 		pFirst(nullptr), pLast(nullptr)
262 {
263 	Append(List2);
264 }
265 
~C4PacketList()266 C4PacketList::~C4PacketList()
267 {
268 	Clear();
269 }
270 
getPktCnt() const271 int32_t C4PacketList::getPktCnt() const
272 {
273 	int32_t iCnt = 0;
274 	for (C4IDPacket *pPkt = pFirst; pPkt; pPkt = pPkt->pNext)
275 		iCnt++;
276 	return iCnt;
277 }
278 
Add(C4IDPacket * pPkt)279 void C4PacketList::Add(C4IDPacket *pPkt)
280 {
281 	assert(!pPkt->pNext);
282 	(pLast ? pLast->pNext : pFirst) = pPkt;
283 	pLast = pPkt;
284 }
285 
AddHead(C4IDPacket * pPkt)286 void C4PacketList::AddHead(C4IDPacket *pPkt)
287 {
288 	assert(!pPkt->pNext);
289 	pPkt->pNext = pFirst;
290 	pFirst = pPkt;
291 	if (!pLast) pLast = pPkt;
292 }
293 
Add(C4PacketType eType,C4PacketBase * pPkt)294 void C4PacketList::Add(C4PacketType eType, C4PacketBase *pPkt)
295 {
296 	Add(new C4IDPacket(eType, pPkt));
297 }
298 
AddHead(C4PacketType eType,C4PacketBase * pPkt)299 void C4PacketList::AddHead(C4PacketType eType, C4PacketBase *pPkt)
300 {
301 	AddHead(new C4IDPacket(eType, pPkt));
302 }
303 
Take(C4PacketList & List)304 void C4PacketList::Take(C4PacketList &List)
305 {
306 	pFirst = List.pFirst;
307 	pLast = List.pLast;
308 	List.pFirst = List.pLast = nullptr;
309 }
310 
Append(const C4PacketList & List)311 void C4PacketList::Append(const C4PacketList &List)
312 {
313 	for (C4IDPacket *pPkt = List.firstPkt(); pPkt; pPkt = List.nextPkt(pPkt))
314 		Add(new C4IDPacket(*pPkt));
315 }
316 
Clear()317 void C4PacketList::Clear()
318 {
319 	while (pFirst)
320 		Delete(pFirst);
321 }
322 
Remove(C4IDPacket * pPkt)323 void C4PacketList::Remove(C4IDPacket *pPkt)
324 {
325 	if (pPkt == pFirst)
326 	{
327 		pFirst = pPkt->pNext;
328 		if (pPkt == pLast)
329 			pLast = nullptr;
330 	}
331 	else
332 	{
333 		C4IDPacket *pPrev;
334 		for (pPrev = pFirst; pPrev && pPrev->pNext != pPkt; pPrev = pPrev->pNext) {}
335 		if (pPrev)
336 		{
337 			pPrev->pNext = pPkt->pNext;
338 			if (pPkt == pLast)
339 				pLast = pPrev;
340 		}
341 	}
342 }
343 
Delete(C4IDPacket * pPkt)344 void C4PacketList::Delete(C4IDPacket *pPkt)
345 {
346 	Remove(pPkt);
347 	delete pPkt;
348 }
349 
CompileFunc(StdCompiler * pComp)350 void C4PacketList::CompileFunc(StdCompiler *pComp)
351 {
352 	// unpack packets
353 	if (pComp->isDeserializer())
354 	{
355 		// Read until no further sections available
356 		while (pComp->Name("IDPacket"))
357 		{
358 			// Read the packet
359 			C4IDPacket *pPkt = new C4IDPacket();
360 			try
361 			{
362 				pComp->Value(*pPkt);
363 				pComp->NameEnd();
364 			}
365 			catch (...)
366 			{
367 				delete pPkt;
368 				throw;
369 			}
370 			// Terminator?
371 			if (!pPkt->getPkt()) { delete pPkt; break; }
372 			// Add to list
373 			Add(pPkt);
374 		}
375 		pComp->NameEnd();
376 	}
377 	else
378 	{
379 		// Write all packets
380 		for (C4IDPacket *pPkt = pFirst; pPkt; pPkt = pPkt->pNext)
381 			pComp->Value(mkNamingAdapt(*pPkt, "IDPacket"));
382 		// Terminate, if no naming is available
383 		if (!pComp->hasNaming())
384 		{
385 			C4IDPacket Pkt;
386 			pComp->Value(mkNamingAdapt(Pkt, "IDPacket"));
387 		}
388 	}
389 }
390 
391 // *** C4PacketConn
392 
C4PacketConn()393 C4PacketConn::C4PacketConn()
394 		: iVer(C4XVER1*100 + C4XVER2)
395 {
396 }
397 
C4PacketConn(const C4ClientCore & nCCore,uint32_t inConnID,const char * szPassword)398 C4PacketConn::C4PacketConn(const C4ClientCore &nCCore, uint32_t inConnID, const char *szPassword)
399 		: iVer(C4XVER1*100 + C4XVER2),
400 		iConnID(inConnID),
401 		CCore(nCCore),
402 		Password(szPassword)
403 {
404 }
405 
CompileFunc(StdCompiler * pComp)406 void C4PacketConn::CompileFunc(StdCompiler *pComp)
407 {
408 	pComp->Value(mkNamingAdapt(CCore, "CCore"));
409 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iVer), "Version", -1));
410 	pComp->Value(mkNamingAdapt(Password, "Password", ""));
411 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iConnID), "ConnID", ~0u));
412 }
413 
414 // *** C4PacketConnRe
415 
416 C4PacketConnRe::C4PacketConnRe() = default;
417 
C4PacketConnRe(bool fnOK,bool fWrongPassword,const char * sznMsg)418 C4PacketConnRe::C4PacketConnRe(bool fnOK, bool fWrongPassword, const char *sznMsg)
419 		: fOK(fnOK),
420 		fWrongPassword(fWrongPassword),
421 		szMsg(sznMsg, true)
422 {
423 }
424 
CompileFunc(StdCompiler * pComp)425 void C4PacketConnRe::CompileFunc(StdCompiler *pComp)
426 {
427 	pComp->Value(mkNamingAdapt(fOK, "OK", true));
428 	pComp->Value(mkNamingAdapt(szMsg, "Message", ""));
429 	pComp->Value(mkNamingAdapt(fWrongPassword, "WrongPassword", false));
430 }
431 
432 // *** C4PacketFwd
433 
434 C4PacketFwd::C4PacketFwd() = default;
435 
C4PacketFwd(const StdBuf & Pkt)436 C4PacketFwd::C4PacketFwd(const StdBuf &Pkt)
437 		: Data(Pkt)
438 {
439 }
440 
DoFwdTo(int32_t iClient) const441 bool C4PacketFwd::DoFwdTo(int32_t iClient) const
442 {
443 	for (int32_t i = 0; i < iClientCnt; i++)
444 		if (iClients[i] == iClient)
445 			return !fNegativeList;
446 	return fNegativeList;
447 }
448 
SetData(const StdBuf & Pkt)449 void C4PacketFwd::SetData(const StdBuf &Pkt)
450 {
451 	Data = Pkt;
452 }
453 
SetListType(bool fnNegativeList)454 void C4PacketFwd::SetListType(bool fnNegativeList)
455 {
456 	fNegativeList = fnNegativeList;
457 }
458 
AddClient(int32_t iClient)459 void C4PacketFwd::AddClient(int32_t iClient)
460 {
461 	if (iClientCnt + 1 > C4NetMaxClients) return;
462 	// add
463 	iClients[iClientCnt++] = iClient;
464 }
465 
CompileFunc(StdCompiler * pComp)466 void C4PacketFwd::CompileFunc(StdCompiler *pComp)
467 {
468 	pComp->Value(mkNamingAdapt(fNegativeList, "Negative", false));
469 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iClientCnt), "ClientCnt", 0));
470 	pComp->Value(mkNamingAdapt(mkArrayAdaptMap(iClients, iClientCnt, mkIntPackAdapt<int32_t>), "Clients", -1));
471 	pComp->Value(mkNamingAdapt(Data, "Data"));
472 }
473 
474 // *** C4PacketJoinData
475 
CompileFunc(StdCompiler * pComp)476 void C4PacketJoinData::CompileFunc(StdCompiler *pComp)
477 {
478 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iClientID), "ClientID", C4ClientIDUnknown));
479 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iStartCtrlTick), "CtrlTick", -1));
480 	pComp->Value(mkNamingAdapt(mkParAdapt(GameStatus, true), "GameStatus"));
481 	pComp->Value(mkNamingAdapt(Dynamic, "Dynamic"));
482 	pComp->Value(mkNamingAdapt(ScenarioParameterDefs, "ParameterDefs"));
483 	pComp->Value(Parameters);
484 }
485 
486 // *** C4PacketPing
487 
C4PacketPing(uint32_t iPacketCounter,uint32_t iRemotePacketCounter)488 C4PacketPing::C4PacketPing(uint32_t iPacketCounter, uint32_t iRemotePacketCounter)
489 		: tTime(C4TimeMilliseconds::Now()),
490 		iPacketCounter(iPacketCounter)
491 {
492 }
493 
getTravelTime() const494 uint32_t C4PacketPing::getTravelTime() const
495 {
496 	return C4TimeMilliseconds::Now() - tTime;
497 }
498 
CompileFunc(StdCompiler * pComp)499 void C4PacketPing::CompileFunc(StdCompiler *pComp)
500 {
501 	uint32_t time = tTime.AsInt();
502 	pComp->Value(mkNamingAdapt(time, "Time", 0U));
503 	tTime = C4TimeMilliseconds(time);
504 
505 	pComp->Value(mkNamingAdapt(iPacketCounter, "PacketCounter", 0U));
506 }
507 
508 // *** C4PacketResStatus
509 
510 C4PacketResStatus::C4PacketResStatus() = default;
511 
C4PacketResStatus(int32_t iResID,const C4Network2ResChunkData & nChunks)512 C4PacketResStatus::C4PacketResStatus(int32_t iResID, const C4Network2ResChunkData &nChunks)
513 		: iResID(iResID), Chunks(nChunks)
514 {
515 
516 }
517 
CompileFunc(StdCompiler * pComp)518 void C4PacketResStatus::CompileFunc(StdCompiler *pComp)
519 {
520 	pComp->Value(mkNamingAdapt(iResID, "ResID"));
521 	pComp->Value(mkNamingAdapt(Chunks, "Chunks"));
522 }
523 
524 // *** C4PacketResDiscover
525 
526 C4PacketResDiscover::C4PacketResDiscover() = default;
527 
isIDPresent(int32_t iID) const528 bool C4PacketResDiscover::isIDPresent(int32_t iID) const
529 {
530 	for (int32_t i = 0; i < iDisIDCnt; i++)
531 		if (iDisIDs[i] == iID)
532 			return true;
533 	return false;
534 }
535 
AddDisID(int32_t iID)536 bool C4PacketResDiscover::AddDisID(int32_t iID)
537 {
538 	if (iDisIDCnt + 1 >= int32_t(sizeof(iDisIDs) / sizeof(*iDisIDs))) return false;
539 	// add
540 	iDisIDs[iDisIDCnt++] = iID;
541 	return true;
542 }
543 
CompileFunc(StdCompiler * pComp)544 void C4PacketResDiscover::CompileFunc(StdCompiler *pComp)
545 {
546 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iDisIDCnt), "DiscoverCnt", 0));
547 	pComp->Value(mkNamingAdapt(mkArrayAdapt(iDisIDs, iDisIDCnt), "Discovers", -1));
548 }
549 
550 // *** C4PacketResRequest
551 
C4PacketResRequest(int32_t inID,int32_t inChunk)552 C4PacketResRequest::C4PacketResRequest(int32_t inID, int32_t inChunk)
553 		: iReqID(inID), iReqChunk(inChunk)
554 {
555 
556 }
557 
CompileFunc(StdCompiler * pComp)558 void C4PacketResRequest::CompileFunc(StdCompiler *pComp)
559 {
560 	pComp->Value(mkNamingAdapt(iReqID, "ResID", -1));
561 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iReqChunk), "Chunk", -1));
562 }
563 
564 // *** C4PacketControlReq
565 
C4PacketControlReq(int32_t inCtrlTick)566 C4PacketControlReq::C4PacketControlReq(int32_t inCtrlTick)
567 		: iCtrlTick(inCtrlTick)
568 {
569 
570 }
571 
CompileFunc(StdCompiler * pComp)572 void C4PacketControlReq::CompileFunc(StdCompiler *pComp)
573 {
574 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iCtrlTick), "CtrlTick", -1));
575 }
576 
577 // *** C4PacketActivateReq
578 
CompileFunc(StdCompiler * pComp)579 void C4PacketActivateReq::CompileFunc(StdCompiler *pComp)
580 {
581 	pComp->Value(mkNamingAdapt(mkIntPackAdapt(iTick), "Tick", -1));
582 }
583 
584 
585 // *** C4PacketControlPkt
586 
CompileFunc(StdCompiler * pComp)587 void C4PacketControlPkt::CompileFunc(StdCompiler *pComp)
588 {
589 	pComp->Value(mkNamingAdapt(mkIntAdaptT<uint8_t>(eDelivery), "Delivery", CDT_Queue));
590 	pComp->Value(Ctrl);
591 }
592