1 /**
2  * @file
3  * @brief definitions common between client and server, but not game lib
4  */
5 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 */
25 
26 #pragma once
27 
28 #include "../shared/ufotypes.h"
29 #include "../shared/byte.h"
30 #include "../shared/shared.h"
31 #include "../shared/mathlib.h"
32 #include "../shared/defines.h"
33 #include "cvar.h"
34 #include "mem.h"
35 
36 #define UFO_VERSION "2.5"
37 #define GAME_TITLE "UFO:AI"
38 #define GAME_TITLE_LONG "UFO:Alien Invasion"
39 
40 #ifdef _WIN32
41 #  define BUILDSTRING_OS "Win32"
42 #  ifndef SO_EXT
43 #    define SO_EXT "dll"
44 #  endif
45 
46 #elif defined __linux__
47 #  define BUILDSTRING_OS "Linux"
48 #  ifndef SO_EXT
49 #    define SO_EXT "so"
50 #  endif
51 
52 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
53 #  define BUILDSTRING_OS "FreeBSD"
54 #  ifndef SO_EXT
55 #    define SO_EXT "so"
56 #  endif
57 
58 #elif defined __sun
59 #  define BUILDSTRING_OS "Solaris"
60 #  ifndef SO_EXT
61 #    define SO_EXT "so"
62 #  endif
63 
64 #elif defined (__APPLE__) || defined (MACOSX)
65 #  define BUILDSTRING_OS "MacOSX"
66 #  ifndef SO_EXT
67 #    define SO_EXT "dylib"
68 #  endif
69 
70 #elif defined ANDROID
71 #  define BUILDSTRING_OS "Android"
72 #  ifndef SO_EXT
73 #    define SO_EXT "so"
74 #  endif
75 
76 #else
77 #  define BUILDSTRING_OS "Unknown"
78 #endif
79 
80 #if defined __alpha__ || defined __alpha || defined _M_ALPHA
81 #  define CPUSTRING "Alpha"
82 #elif defined __amd64__ || defined __amd64 || defined __x86_64__ || defined __x86_64 || defined _M_X64
83 #  define CPUSTRING "AMD64"
84 #elif defined __arm__ || defined __thumb__ || defined _ARM
85 #  define CPUSTRING "ARM"
86 #elif defined i386 || defined __i386__ || defined __i386 || defined _M_IX86 || defined __X86__ || defined _X86_ || defined __THW_INTEL__ || defined __I86__ || defined __INTEL__
87 #  define CPUSTRING "IA-32"
88 #elif defined __ia64__ || defined _IA64 || defined __IA64__ || defined __ia64 || defined _M_IA64
89 #  define CPUSTRING "IA-64"
90 #elif defined __mips__ || defined mips || defined __mips || defined __MIPS__
91 #  define CPUSTRING "MIPS"
92 #elif defined __powerpc || defined __powerpc__ || defined __POWERPC__ || defined __ppc__ || defined _M_PPC || defined _ARCH_PPC
93 #  define CPUSTRING "PowerPC"
94 #elif defined __sparc__ || defined __sparc
95 #  define CPUSTRING "SPARC"
96 #else
97 #  define CPUSTRING "Unknown"
98 #endif
99 
100 #ifdef DEBUG
101 #  define BUILDSTRING_VARIANT "DEBUG"
102 #else
103 #  define BUILDSTRING_VARIANT "RELEASE"
104 #endif
105 
106 #ifdef UFO_REVISION
107 #  define BUILDSTRING BUILDSTRING_OS " " BUILDSTRING_VARIANT " build " UFO_REVISION
108 #else
109 #  define BUILDSTRING BUILDSTRING_OS " " BUILDSTRING_VARIANT
110 #endif
111 
112 #define MASTER_SERVER "http://ufoai.org/" /* sponsored by NineX */
113 
114 /*
115 ==============================================================
116 PROTOCOL
117 ==============================================================
118 */
119 
120 /* protocol.h -- communications protocols */
121 
122 #define	PROTOCOL_VERSION	18
123 
124 #define	PORT_CLIENT	27901
125 #define	PORT_SERVER	27910
126 
127 /**
128  * @brief server to client
129  * the svc_strings[] array in cl_parse.c should mirror this
130  */
131 enum svc_ops_e {
132 	svc_bad,
133 
134 	/** the rest are private to the client and server */
135 	svc_nop,
136 	svc_ping,
137 	svc_disconnect,
138 	svc_reconnect,
139 	svc_print,					/**< [byte] id [string] null terminated string */
140 	svc_stufftext,				/**< [string] stuffed into client's console buffer, should be \n terminated */
141 	svc_serverdata,				/**< [long] protocol, spawncount, playernum, mapname, ... */
142 	svc_configstring,			/**< [short] [string] */
143 	svc_event,					/**< event like move or inventory usage - see EV_* and @sa CL_ParseEvent */
144 	svc_oob = 0xff
145 };
146 
147 #define MAX_SVC_STUFFTEXT 1024
148 #define MAX_SVC_PRINT 1024
149 #define MAX_SVC_RECONNECT 256
150 #define MAX_SVC_DISCONNECT 256
151 #define MAX_CLC_STRINGCMD 512
152 
153 typedef int32_t svc_ops_t;
154 
155 /*============================================== */
156 
157 /**
158  * @brief client to server
159  */
160 enum clc_ops_e {
161 	clc_bad,
162 	clc_nop,
163 	clc_ack,					/**< answer on a ping */
164 	clc_endround,
165 	clc_teaminfo,
166 	clc_initactorstates,
167 	clc_action,
168 	clc_userinfo,				/**< [[userinfo string] */
169 	clc_stringcmd,				/**< [string] message */
170 	clc_oob = svc_oob			/**< out of band - connectionless */
171 };
172 
173 #define SOUND_ATTN_NONE 0.0f /**< full volume the entire level */
174 #define SOUND_ATTN_NORM	1.0f
175 #define SOUND_ATTN_IDLE 1.2f
176 #define SOUND_ATTN_STATIC 3.0f /**< dimish very rapidly with distance */
177 #define SOUND_ATTN_MAX SOUND_ATTN_STATIC
178 
179 #include "../ports/system.h"
180 #include "cmd.h"
181 #include "cvar.h"
182 #include "cmodel.h"
183 #include "filesys.h"
184 #include "scripts.h"
185 #include "net.h"
186 #include "dbuffer.h"
187 #include "netpack.h"
188 
189 /*
190 ==============================================================
191 MISC
192 ==============================================================
193 */
194 
195 #define ANGLE2SHORT(x)		((int)((x)*65536/360) & 65535)
196 #define SHORT2ANGLE(x)		((x)*(360.0/65536))
197 
198 #define	ERR_FATAL	0			/* exit the entire game with a popup window */
199 #define	ERR_DROP	1			/* print to console and disconnect from game */
200 #define	ERR_QUIT	2			/* not an error, just a normal exit */
201 
202 #define Q_COLOR_ESCAPE	'^'
203 #define Q_IsColorString(p)	((p) && *(p) == Q_COLOR_ESCAPE && *((p) + 1) && isalnum(*((p) + 1)))
204 
205 #define S_COLOR_BLACK	"^0"
206 #define S_COLOR_RED	"^1"
207 #define S_COLOR_GREEN	"^2"
208 #define S_COLOR_YELLOW	"^3"
209 #define S_COLOR_BLUE	"^4"
210 #define S_COLOR_CYAN	"^5"
211 #define S_COLOR_MAGENTA	"^6"
212 #define S_COLOR_WHITE	"^7"
213 
214 #define CON_COLOR_BLACK		0
215 #define CON_COLOR_RED		1
216 #define CON_COLOR_GREEN		2
217 #define CON_COLOR_YELLOW	3
218 #define CON_COLOR_BLUE		4
219 #define CON_COLOR_CYAN		5
220 #define CON_COLOR_MAGENTA	6
221 #define CON_COLOR_WHITE		7
222 #define MAX_COLORS			8
223 
224 void Com_BeginRedirect(struct net_stream *stream, char* buffer, int buffersize);
225 void Com_EndRedirect(void);
226 void Com_vPrintf(const char* fmt, va_list);
227 
228 typedef void (*exceptionCallback_t)(void);
229 
230 /**
231  * Thrown by Com_Drop().
232  */
233 struct comDrop_t {};
234 class comRestart_t {
235 public:
236 	const char* gamedir;
comRestart_t(const char * _gamedir)237 	comRestart_t (const char* _gamedir) : gamedir(_gamedir ? strdup(_gamedir) : nullptr) {}
~comRestart_t()238 	virtual ~comRestart_t () { free(static_cast<void*>(const_cast<char*>(gamedir))); }
239 };
240 
241 void Com_Drop(void) __attribute__((noreturn));
242 void Com_Quit(void);
243 void Com_BreakIntoDebugger(void);
244 void Com_WriteConfigToFile(const char* filename);
245 void Cvar_WriteVariables(qFILE *f);
246 
247 int Com_ServerState(void);
248 void Com_SetServerState(int state);
249 void Com_SetRandomSeed(unsigned int seed);
250 const char* Com_UnsignedIntToBinary(uint32_t x);
251 const char* Com_ByteToBinary(byte x);
252 
253 #include "md4.h"
254 const char* Com_MD5File(const char* fn, int length = 0);
255 const char* Com_MD5Buffer(const byte* buf, size_t len);
256 
257 extern cvar_t* http_proxy;
258 extern cvar_t* http_timeout;
259 extern cvar_t* developer;
260 extern cvar_t* sv_dedicated;
261 extern cvar_t* sv_maxclients;
262 extern cvar_t* sv_gametype;
263 extern cvar_t* masterserver_url;
264 extern cvar_t* port;
265 
266 extern cvar_t* sys_priority;
267 extern cvar_t* sys_affinity;
268 extern cvar_t* sys_os;
269 extern cvar_t* hwclass;
270 
271 /* Time information. */
272 /**
273  * @brief Engine-side time information in the game.
274  * @note Use this in your custom structs that need to get saved or sent over the network.
275  * @sa dateLong_t	For runtime use (human readable).
276  * @sa CP_DateConvertLong
277  */
278 typedef struct date_s {
279 	int day;	/**< Number of elapsed days since 1st january of year 0 */
280 	int sec;	/**< Number of elapsed seconds since the beginning of current day */
281 } date_t;
282 
283 /* Time Constants */
284 #define DAYS_PER_YEAR		365
285 #define DAYS_PER_YEAR_AVG	365.25
286 /** DAYS_PER_MONTH -> @sa monthLength[] array in campaign.c */
287 #define MONTHS_PER_YEAR		12
288 #define SEASONS_PER_YEAR	4
289 #define SECONDS_PER_DAY		86400	/**< (24 * 60 * 60) */
290 #define SECONDS_PER_HOUR	3600	/**< (60 * 60) */
291 #define SECONDS_PER_MINUTE	60		/**< (60) */
292 #define MINUTES_PER_HOUR	60		/**< (60) */
293 #define HOURS_PER_DAY		24
294 
295 #define MAXCMDLINE 256
296 
297 typedef void (*vPrintfPtr_t)(const char* fmt, va_list ap);
298 vPrintfPtr_t Qcommon_GetPrintFunction(void);
299 void Qcommon_SetPrintFunction(vPrintfPtr_t func);
300 
301 void Qcommon_Init(int argc, char** argv);
302 void Qcommon_Frame(void);
303 void Qcommon_Shutdown(void);
304 void Com_SetGameType(void);
305 void Com_ReadFromPipe(void);
306 float Com_GrenadeTarget(const vec3_t from, const vec3_t at, float speed, bool launched, bool rolled, vec3_t v0);
307 bool Com_CheckConfigStringIndex(int index);
308 void Con_Print(const char* txt);
309 
310 /* Event timing */
311 
312 typedef void event_func(int now, void* data);
313 typedef bool event_check_func(int now, void* data);
314 typedef bool event_delay_func(int now, void* data);
315 typedef void event_notify_delay_func(int now, void* data, int delay);
316 /**
317  * @return @c true to keep the event, @c false to remove it from the queue
318  */
319 typedef bool event_filter(int when, event_func* func, event_check_func* check, void* data);
320 typedef void event_clean_func(void* data);
321 
322 struct scheduleEvent_t {
323 	int when;
324 	int delayFollowing;
325 	event_func* func;
326 	event_check_func* check;
327 	/**
328 	 * @brief Called when the check failed and we have to delay events in the queue
329 	 * @return @c false if there should be no delay for this event, @c true if it should
330 	 * get delayed
331 	 * @param[in] now The current time
332 	 * @param[in] data The event userdata
333 	 */
334 	event_delay_func *delay;
335 	event_notify_delay_func *notifyDelay;
336 	void* notifyDelayUserData;
337 	event_clean_func *clean;
338 	void* data;
339 };
340 
341 typedef SharedPtr<scheduleEvent_t> ScheduleEventPtr;
342 
343 ScheduleEventPtr Schedule_Event(int when, event_func* func, event_check_func* check, event_clean_func *clean, void* data);
344 int CL_FilterEventQueue(event_filter *filter);
345 
346 /*
347 ==============================================================
348 CLIENT / SERVER SYSTEMS
349 ==============================================================
350 */
351 
352 void CL_Init(void);
353 void CL_Drop(void);
354 void CL_Shutdown(void);
355 int CL_Milliseconds(void);
356 void CL_Frame(int now, void* data);
357 void CL_SlowFrame(int now, void* data);
358 bool CL_ParseClientData(const char* type, const char* name, const char** text);
359 void SCR_BeginLoadingPlaque(void);
360 void SCR_EndLoadingPlaque(void);
361 void CL_InitAfter(void);
362 
363 void SV_Init(void);
364 void SV_Clear(void);
365 void SV_Shutdown(const char* finalmsg, bool reconnect);
366 void SV_ShutdownWhenEmpty(void);
367 void SV_Frame(int now, void*);
368 mapData_t* SV_GetMapData(void);
369 mapTiles_t* SV_GetMapTiles(void);
370 
371 /*============================================================================ */
372 
373 extern memPool_t* com_aliasSysPool;
374 extern memPool_t* com_cmdSysPool;
375 extern memPool_t* com_cmodelSysPool;
376 extern memPool_t* com_cvarSysPool;
377 extern memPool_t* com_fileSysPool;
378 extern memPool_t* com_genericPool;
379 extern memPool_t* com_networkPool;
380 
381 /*============================================================================ */
382 
383 int Com_Argc(void);
384 const char* Com_Argv(int arg);		/* range and null checked */
385 void Com_ClearArgv(int arg);
386 const char* Com_MacroExpandString(const char* text);
387 void Com_UploadCrashDump(const char* crashDumpFile);
388 bool Com_CheckDuplicateFile(const char* file, const char* wildcard);
389 
390 bool Com_ConsoleCompleteCommand(const char* s, char* target, size_t bufSize, uint32_t* pos, uint32_t offset);
391 
392 void Key_Init(void);
393 
394 
395 /** Remove element at index from array of size n.  n gets adjusted to the new
396  * array size, so must be an lvalue */
397 #define REMOVE_ELEM(array, index, n)                                               \
398 do {                                                                               \
399 	size_t idx__ = (index);                                                          \
400 	size_t n__   = --(n);                                                            \
401 	assert(idx__ <= n__);                                                            \
402 	memmove((array) + idx__, (array) + idx__ + 1, (n__ - idx__) * sizeof(*(array))); \
403 	OBJZERO((array)[n__]);                                                           \
404 } while (0)
405 
406 /** Same as REMOVE_ELEM() and also updates the idx attribute of every moved
407  * element */
408 #define REMOVE_ELEM_ADJUST_IDX(array, index, n) \
409 do {                                            \
410 	size_t idx__ = (index);                       \
411 	size_t n__;                                   \
412 	size_t i__;                                   \
413 	REMOVE_ELEM(array, index, n);                 \
414 	n__ = (n);                                    \
415 	for (i__ = idx__; i__ < n__; ++i__)           \
416 		--(array)[i__].idx;                         \
417 } while (0)
418 
419 #define HASH_Add(hash, elem, index) \
420 do { \
421 	const int hashIndex = (index); \
422 	assert(hashIndex >= 0); \
423 	assert(hashIndex < lengthof(hash)); \
424 	(elem)->hash_next = (hash)[hashIndex]; \
425 	(hash)[hashIndex] = (elem); \
426 } while (0)
427 
428 #define HASH_Delete(anchor) (*(anchor) = (*(anchor))->hash_next)
429