1 /*
2  * cfg_game.c - storing and loading game setups
3  *
4  * $Id: cfg_game.c,v 1.25 2006/02/24 21:29:16 fzago Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "xblast.h"
25 
26 /*
27  * local variables
28  */
29 static DBRoot *dbLocal;
30 static DBRoot *dbRemote;
31 
32 static CFGGame defaultGame = {
33 	{
34 	 0,							/* ifreclives  */
35 	 1,							/* number of lives */
36 	 9,							/* number of victories */
37 	 20,						/* frames per seconed */
38 	 XBTrue,					/* select all levels */
39 	 XBTrue,					/* random level order */
40 	 XBTrue,					/* random player positions */
41 	 0,							/* level order */
42 	 8,							/* info wait time */
43 	 XBFalse,					/* record demo file */
44 	 XBTM_None,					/* no team game */
45 	 XBTrue,					/* XBCC not rated */
46 	 XBFalse,					/* bot */
47 	 XBFalse,					/* beep */
48 	 XBFalse,					/* Music */
49 	 2,							/* number of rec lives (of valid if 1. XBTrue) */
50 	 1,							/* mask bytes for dgram */
51 	 },
52 	{
53 	 0,							/* num of players */
54 	 {ATOM_INVALID,},			/* player name atom */
55 	 {XBPC_None,},				/* player control */
56 	 {XBPH_None,},				/* player host */
57 	 {XBPT_Invalid,},			/* player team */
58 	 {COLOR_INVALID,},			/* player team color */
59 	 {0,},						/* player PID */
60 	 {0,},						/* player id */
61 	 },
62 	{
63 	 "localhost",				/* hostname */
64 	 16168,						/* tcp-port */
65 	 XBFalse,					/* fixed udp-port */
66 	 XBTrue,					/* browse LAN */
67 	 XBTrue,					/* allow NAT for clients */
68 	 XBTrue,					/* connect to central */
69 	 XBFalse,					/* beep if new client */
70 	 0,							/* Music */
71 	 "unnamed",					/* name of the game */
72 	 },
73 	{
74 	 6,							/* max hosts */
75 	 6,							/* max players */
76 	 6,							/* num local players */
77 	 1,							/* max mask bytes */
78 	 {0, 0, 0},					/* version */
79 	 },
80 };
81 
82 /* conversion table for player control (alphanumeric sort by key) */
83 static DBToInt convControlTable[XBPC_NUM + 1] = {
84 	{"Joystick1", XBPC_Joystick1,},
85 	{"Joystick2", XBPC_Joystick2,},
86 	{"Joystick3", XBPC_Joystick3,},
87 	{"Joystick4", XBPC_Joystick4,},
88 	{"LeftKeyboard", XBPC_LeftKeyboard,},
89 	{"None", XBPC_None,},
90 	{"RightKeyboard", XBPC_RightKeyboard,},
91 	/* terminator */
92 	{NULL, XBPC_NUM},
93 };
94 
95 /* conversion table for player hosts (alphanumeric sort by key) */
96 static DBToInt convHostTable[XBPH_NUM + 1] = {
97 	{"Central", XBPH_Central,},
98 	{"Client1", XBPH_Client1,},
99 	{"Client2", XBPH_Client2,},
100 	{"Client3", XBPH_Client3,},
101 	{"Client4", XBPH_Client4,},
102 	{"Client5", XBPH_Client5,},
103 #ifdef SMPF
104 	{"Client6", XBPH_Client6,},
105 	{"Client7", XBPH_Client7,},
106 	{"Client8", XBPH_Client8,},
107 	{"Client9", XBPH_Client9,},
108 	{"Client10", XBPH_Client10,},
109 	{"Client11", XBPH_Client11,},
110 	{"Client12", XBPH_Client12,},
111 	{"Client13", XBPH_Client13,},
112 	{"Client14", XBPH_Client14,},
113 	{"Client15", XBPH_Client15,},
114 #endif
115 	{"Demo", XBPH_Demo,},
116 	{"Local", XBPH_Local,},
117 	{"None", XBPH_None,},
118 	{"Server", XBPH_Server,},
119 	/* terminator */
120 	{NULL, XBPH_NUM},
121 };
122 
123 /* conversion table for player teams (alphanumeric sort by key) */
124 static DBToInt convTeamTable[XBPT_NUM + 1] = {
125 	{"Blue", XBPT_Blue,},
126 	{"Green", XBPT_Green,},
127 	{"None", XBPT_None,},
128 	{"Red", XBPT_Red,},
129 	/* terminator */
130 	{NULL, XBPT_NUM,},
131 };
132 
133 /* conversion table for player teams (alphanumeric sort by key) */
134 static DBToInt convTeamModeTable[XBTM_NUM + 1] = {
135 	{"Hunt", XBTM_Hunt,},
136 	{"None", XBTM_None,},
137 	{"Team", XBTM_Team,},
138 	/* terminator */
139 	{NULL, XBTM_NUM,},
140 };
141 
142 /*
143  * convert type to database
144  */
145 static DBRoot *
GetDB(CFGType cfgType)146 GetDB (CFGType cfgType)
147 {
148 	switch (cfgType) {
149 	case CT_Local:
150 		return dbLocal;
151 	case CT_Remote:
152 		return dbRemote;
153 		/* case CT_Demo:   return dbDemo; */
154 	default:
155 		return NULL;
156 	}
157 }								/* GetDB */
158 
159 /*
160  *
161  */
162 static void
StoreAnyGameSetup(DBRoot * db,XBAtom atom,const CFGGameSetup * game)163 StoreAnyGameSetup (DBRoot * db, XBAtom atom, const CFGGameSetup * game)
164 {
165 	DBSection *section;
166 	const char *key;
167 
168 	/* sanity check */
169 	assert (db != NULL);
170 	assert (ATOM_INVALID != atom);
171 	assert (NULL != game);
172 	/* create new game section */
173 	section = DB_CreateSection (db, atom);
174 	assert (NULL != section);
175 	/* other stats */
176 	DB_CreateEntryInt (section, atomLives, game->numLives);
177 	DB_CreateEntryInt (section, atomRecLives, game->recLives);
178 	DB_CreateEntryBool (section, atomIfRecLives, game->ifRecLives);
179 	DB_CreateEntryInt (section, atomWins, game->numWins);
180 	DB_CreateEntryInt (section, atomFrameRate, game->frameRate);
181 	DB_CreateEntryBool (section, atomAllLevels, game->allLevels);
182 	DB_CreateEntryBool (section, atomRandomLevels, game->randomLevels);
183 	DB_CreateEntryBool (section, atomRandomPlayers, game->randomPlayers);
184 	DB_CreateEntryBool (section, atomRecordDemo, game->recordDemo);
185 	DB_CreateEntryBool (section, atomRatedGame, game->rated);
186 	DB_CreateEntryBool (section, atomBot, game->bot);
187 	DB_CreateEntryBool (section, atomBeep, game->beep);
188 	DB_CreateEntryInt (section, atomMusic, game->Music);
189 	DB_CreateEntryInt (section, atomInfoTime, game->infoTime);	// LRF
190 	DB_CreateEntryInt (section, atomLevelOrder, game->levelOrder);
191 	DB_CreateEntryInt (section, atomMaskBytes, game->maskBytes);
192 	/* team mode */
193 	if (NULL != (key = DB_IntToString (convTeamModeTable, (int)game->teamMode))) {
194 		DB_CreateEntryString (section, atomTeamMode, key);
195 	}
196 	else {
197 		DB_DeleteEntry (section, atomTeamMode);
198 	}
199 }								/* StoreAnyGameSetup */
200 
201 /*
202  *
203  */
204 void
StoreGameSetup(CFGType cfgType,XBAtom atom,const CFGGameSetup * game)205 StoreGameSetup (CFGType cfgType, XBAtom atom, const CFGGameSetup * game)
206 {
207 	StoreAnyGameSetup (GetDB (cfgType), atom, game);
208 }								/* StoreLocalGameSetup */
209 
210 /*
211  * store GamePlayers data from struct to any database
212  */
213 static void
StoreAnyGamePlayers(DBRoot * db,XBAtom atom,const CFGGamePlayers * game)214 StoreAnyGamePlayers (DBRoot * db, XBAtom atom, const CFGGamePlayers * game)
215 {
216 	int i;
217 	DBSection *section;
218 	const char *keyControl;
219 	const char *keyHost;
220 	const char *keyTeam;
221 
222 	/* sanity check */
223 	assert (db != NULL);
224 	assert (ATOM_INVALID != atom);
225 	assert (NULL != game);
226 	/* create new game section */
227 	section = DB_CreateSection (db, atom);
228 	assert (NULL != section);
229 	/* number of players */
230 	DB_CreateEntryInt (section, atomNumPlayers, game->num);
231 	/* players */
232 	for (i = 0; i < game->num; i++) {
233 		keyControl = DB_IntToString (convControlTable, (int)game->control[i]);
234 		keyHost = DB_IntToString (convHostTable, (int)game->host[i]);
235 		keyTeam = DB_IntToString (convTeamTable, (int)game->team[i]);
236 		if (NULL != keyHost && NULL != keyControl && NULL != keyTeam) {
237 			DB_CreateEntryString (section, atomArrayPlayer0[i], GUI_AtomToString (game->player[i]));
238 			DB_CreateEntryString (section, atomArrayControl0[i], keyControl);
239 			DB_CreateEntryString (section, atomArrayHost0[i], keyHost);
240 			DB_CreateEntryString (section, atomArrayTeam0[i], keyTeam);
241 		}
242 		else {
243 			DB_DeleteEntry (section, atomArrayPlayer0[i]);
244 			DB_DeleteEntry (section, atomArrayControl0[i]);
245 			DB_DeleteEntry (section, atomArrayHost0[i]);
246 			DB_DeleteEntry (section, atomArrayTeam0[i]);
247 		}
248 	}
249 	for (; i < MAX_PLAYER; i++) {
250 		DB_DeleteEntry (section, atomArrayPlayer0[i]);
251 		DB_DeleteEntry (section, atomArrayControl0[i]);
252 		DB_DeleteEntry (section, atomArrayHost0[i]);
253 		DB_DeleteEntry (section, atomArrayTeam0[i]);
254 	}
255 }								/* StoreAnyGamePlayers */
256 
257 /*
258  * copy GamePlayers data from struct to a config database
259  */
260 void
StoreGamePlayers(CFGType cfgType,XBAtom atom,const CFGGamePlayers * game)261 StoreGamePlayers (CFGType cfgType, XBAtom atom, const CFGGamePlayers * game)
262 {
263 	StoreAnyGamePlayers (GetDB (cfgType), atom, game);
264 }								/* StoreGamePlayers */
265 
266 /*
267  *
268  */
269 static void
StoreAnyGameHost(DBRoot * db,XBAtom atom,const CFGGameHost * host)270 StoreAnyGameHost (DBRoot * db, XBAtom atom, const CFGGameHost * host)
271 {
272 	DBSection *section;
273 	/* sanity check */
274 	assert (db != NULL);
275 	assert (ATOM_INVALID != atom);
276 	assert (NULL != host);
277 	/* create new game section */
278 	section = DB_CreateSection (db, atom);
279 	assert (NULL != section);
280 	/* other stats */
281 	if (NULL != host->name) {
282 		DB_CreateEntryString (section, atomHost, host->name);
283 	}
284 	else {
285 		DB_DeleteEntry (section, atomHost);
286 	}
287 	DB_CreateEntryInt (section, atomPort, host->port);
288 	DB_CreateEntryBool (section, atomFixedUdpPort, host->fixedUdpPort);
289 	DB_CreateEntryBool (section, atomBrowseLan, host->browseLan);
290 	DB_CreateEntryBool (section, atomAllowNat, host->allowNat);
291 	DB_CreateEntryBool (section, atomCentral, host->central);
292 	DB_CreateEntryBool (section, atomBeep, host->beep);
293 	if (NULL != host->game) {
294 		DB_CreateEntryString (section, atomGame, host->game);
295 	}
296 	else {
297 		DB_DeleteEntry (section, atomGame);
298 	}
299 }								/* StoreGameHost */
300 
301 /*
302  *
303  */
304 void
StoreGameHost(CFGType cfgType,XBAtom atom,const CFGGameHost * host)305 StoreGameHost (CFGType cfgType, XBAtom atom, const CFGGameHost * host)
306 {
307 	StoreAnyGameHost (GetDB (cfgType), atom, host);
308 }								/* StoreGameHost */
309 
310 /*
311  * store version data in any database
312  */
313 static void
StoreAnyGameVersion(DBRoot * db,XBAtom atom,const XBVersion * ver)314 StoreAnyGameVersion (DBRoot * db, XBAtom atom, const XBVersion * ver)
315 {
316 	DBSection *section;
317 	/* sanity check */
318 	assert (db != NULL);
319 	assert (ATOM_INVALID != atom);
320 	assert (NULL != ver);
321 	/* create new game section */
322 	section = DB_CreateSection (db, atom);
323 	assert (NULL != section);
324 	/* store version data */
325 	DB_CreateEntryInt (section, atomVersionMajor, (int)ver->major);
326 	DB_CreateEntryInt (section, atomVersionMinor, (int)ver->minor);
327 	DB_CreateEntryInt (section, atomVersionPatch, (int)ver->patch);
328 }								/* StoreAnyGameVersion */
329 
330 /*
331  * copy version data database directory
332  */
333 void
StoreGameVersion(CFGType cfgType,XBAtom atom,const XBVersion * ver)334 StoreGameVersion (CFGType cfgType, XBAtom atom, const XBVersion * ver)
335 {
336 	StoreAnyGameVersion (GetDB (cfgType), atom, ver);
337 }								/* StoreGameVersion */
338 
339 /*
340  * store constants in any database
341  */
342 static void
StoreAnyGameConst(DBRoot * db,XBAtom atom,const CFGGameConst * con)343 StoreAnyGameConst (DBRoot * db, XBAtom atom, const CFGGameConst * con)
344 {
345 	DBSection *section;
346 	/* sanity check */
347 	assert (db != NULL);
348 	assert (ATOM_INVALID != atom);
349 	assert (NULL != con);
350 	/* create new game section */
351 	section = DB_CreateSection (db, atom);
352 	assert (NULL != section);
353 	/* store version data */
354 	DB_CreateEntryInt (section, atomMaxHosts, con->maxhosts);
355 	DB_CreateEntryInt (section, atomMaxPlayers, con->maxplayers);
356 	DB_CreateEntryInt (section, atomMaxLocals, con->maxlocals);
357 	DB_CreateEntryInt (section, atomMaxMaskBytes, con->maxbytes);
358 	DB_CreateEntryInt (section, atomVersionMajor, (int)con->version.major);
359 	DB_CreateEntryInt (section, atomVersionMinor, (int)con->version.minor);
360 	DB_CreateEntryInt (section, atomVersionPatch, (int)con->version.patch);
361 }								/* StoreAnyGameConst */
362 
363 /*
364  * store constants in config database
365  */
366 void
StoreGameConst(CFGType cfgType,XBAtom atom,const CFGGameConst * con)367 StoreGameConst (CFGType cfgType, XBAtom atom, const CFGGameConst * con)
368 {
369 	StoreAnyGameConst (GetDB (cfgType), atom, con);
370 }								/* StoreGameConst */
371 
372 /*
373  * store local constants in config database
374  */
375 void
StoreGameConstLocal(CFGType cfgType,XBAtom atom)376 StoreGameConstLocal (CFGType cfgType, XBAtom atom)
377 {
378 	CFGGameConst con;
379 	con.maxhosts = MAX_HOSTS;
380 	con.maxplayers = MAX_PLAYER;
381 	con.maxlocals = NUM_LOCAL_PLAYER;
382 	con.maxbytes = MAX_MASK_BYTES;
383 	memcpy (&con.version, &Ver_Local, sizeof (XBVersion));
384 	StoreAnyGameConst (GetDB (cfgType), atom, &con);
385 }								/* StoreGameConstLocal */
386 
387 /*
388  * retrieve game setup from any database
389  */
390 static XBBool
RetrieveAnyGameSetup(const DBRoot * db,XBAtom atom,CFGGameSetup * game)391 RetrieveAnyGameSetup (const DBRoot * db, XBAtom atom, CFGGameSetup * game)
392 {
393 	const DBSection *section;
394 
395 	assert (NULL != db);
396 	assert (NULL != game);
397 	/* set defaults */
398 	memcpy (game, &defaultGame.setup, sizeof (CFGGameSetup));
399 	/* find according db section */
400 	section = DB_GetSection (db, atom);
401 	if (NULL == section) {
402 		return XBFalse;
403 	}
404 	/* copy values */
405 	(void)DB_GetEntryInt (section, atomLives, &game->numLives);
406 	(void)DB_GetEntryInt (section, atomRecLives, &game->recLives);
407 	(void)DB_GetEntryBool (section, atomIfRecLives, &game->ifRecLives);
408 	(void)DB_GetEntryInt (section, atomWins, &game->numWins);
409 	(void)DB_GetEntryInt (section, atomFrameRate, &game->frameRate);
410 	(void)DB_GetEntryBool (section, atomAllLevels, &game->allLevels);
411 	(void)DB_GetEntryBool (section, atomRandomLevels, &game->randomLevels);
412 	(void)DB_GetEntryBool (section, atomRandomPlayers, &game->randomPlayers);
413 	(void)DB_GetEntryBool (section, atomRecordDemo, &game->recordDemo);
414 	(void)DB_GetEntryBool (section, atomRatedGame, &game->rated);
415 	(void)DB_GetEntryInt (section, atomInfoTime, &game->infoTime);	// LRF
416 	(void)DB_GetEntryInt (section, atomLevelOrder, &game->levelOrder);
417 	(void)DB_GetEntryBool (section, atomBot, &game->bot);
418 	(void)DB_GetEntryBool (section, atomBeep, &game->beep);
419 	(void)DB_GetEntryInt (section, atomMusic, (int *)&game->Music);
420 	(void)DB_GetEntryInt (section, atomMaskBytes, &game->maskBytes);
421 	/* team mode */
422 	if (DCR_Okay !=
423 		DB_ConvertEntryInt (section, atomTeamMode, (int *)&game->teamMode, convTeamModeTable)) {
424 		game->teamMode = XBTM_None;
425 	}
426 	/* that's all */
427 	return XBTrue;
428 }								/* RetrieveGameConfig */
429 
430 /*
431  * retrieve game setup from config database
432  */
433 XBBool
RetrieveGameSetup(CFGType cfgType,XBAtom atom,CFGGameSetup * game)434 RetrieveGameSetup (CFGType cfgType, XBAtom atom, CFGGameSetup * game)
435 {
436 	return RetrieveAnyGameSetup (GetDB (cfgType), atom, game);
437 }								/* RetrieveGameSetup */
438 
439 /*
440  * fill default player data, call only once when accessing game players
441  */
442 static void
DefaultPlayerData(void)443 DefaultPlayerData (void)
444 {
445 	static int init = 0;
446 	int p;
447 	if (init == 0) {
448 		for (p = 1; p < MAX_PLAYER; p++) {
449 			defaultGame.players.player[p] = defaultGame.players.player[0];
450 			defaultGame.players.control[p] = defaultGame.players.control[0];
451 			defaultGame.players.host[p] = defaultGame.players.host[0];
452 			defaultGame.players.team[p] = defaultGame.players.team[0];
453 			defaultGame.players.PID[p] = defaultGame.players.PID[0];
454 			defaultGame.players.playerID[p] = defaultGame.players.playerID[0];
455 		}
456 		init = 1;
457 	}
458 }								/* DefaultPlayerData */
459 
460 /*
461  * copy GamePlayers data from any database to struct
462  */
463 static XBBool
RetrieveAnyGamePlayers(const DBRoot * db,XBAtom atom,CFGGamePlayers * game)464 RetrieveAnyGamePlayers (const DBRoot * db, XBAtom atom, CFGGamePlayers * game)
465 {
466 	int i;
467 	const DBSection *section;
468 	const char *s;
469 	assert (NULL != db);
470 	assert (NULL != game);
471 	/* set defaults */
472 	DefaultPlayerData ();
473 	memcpy (game, &defaultGame.players, sizeof (CFGGamePlayers));
474 	/* find according db section */
475 	section = DB_GetSection (db, atom);
476 	if (NULL == section) {
477 		return XBFalse;
478 	}
479 	/* get num players */
480 	if (!DB_GetEntryInt (section, atomNumPlayers, &game->num)) {
481 		game->num = 0;
482 	}
483 	/* check player max */
484 	if (game->num > MAX_PLAYER) {
485 		return XBFalse;
486 	}
487 	/* get players */
488 	for (i = 0; i < game->num; i++) {
489 		if (DB_GetEntryString (section, atomArrayPlayer0[i], &s)) {
490 			game->player[i] = GUI_StringToAtom (s);
491 		}
492 		else {
493 			game->player[i] = ATOM_INVALID;
494 		}
495 		if (DCR_Okay !=
496 			DB_ConvertEntryInt (section, atomArrayControl0[i], (int *)&game->control[i],
497 								convControlTable)) {
498 			game->control[i] = XBPC_None;
499 		}
500 		if (DCR_Okay !=
501 			DB_ConvertEntryInt (section, atomArrayHost0[i], (int *)&game->host[i], convHostTable)) {
502 			game->host[i] = XBPH_None;
503 		}
504 		if (DCR_Okay !=
505 			DB_ConvertEntryInt (section, atomArrayTeam0[i], (int *)&game->team[i], convTeamTable)) {
506 			game->team[i] = XBPT_Invalid;
507 		}
508 		switch (game->team[i]) {
509 		case XBPT_Red:
510 			game->teamColor[i] = COLOR_RED;
511 			break;
512 		case XBPT_Green:
513 			game->teamColor[i] = COLOR_GREEN;
514 			break;
515 		case XBPT_Blue:
516 			game->teamColor[i] = COLOR_BLUE;
517 			break;
518 		default:
519 			game->teamColor[i] = COLOR_INVALID;
520 			break;
521 		}
522 	}
523 	return XBTrue;
524 }								/* RetrieveGamePlayers */
525 
526 /*
527  * get local player selection
528  */
529 XBBool
RetrieveGamePlayers(CFGType cfgType,XBAtom atom,CFGGamePlayers * game)530 RetrieveGamePlayers (CFGType cfgType, XBAtom atom, CFGGamePlayers * game)
531 {
532 	return RetrieveAnyGamePlayers (GetDB (cfgType), atom, game);
533 }								/* RetrieveGamePlayers */
534 
535 /*
536  *
537  */
538 static XBBool
RetrieveAnyGameHost(const DBRoot * db,XBAtom atom,CFGGameHost * game)539 RetrieveAnyGameHost (const DBRoot * db, XBAtom atom, CFGGameHost * game)
540 {
541 	const DBSection *section;
542 	const char *s;
543 
544 	assert (NULL != db);
545 	assert (NULL != game);
546 	/* find according db section */
547 	section = DB_GetSection (db, atom);
548 	if (NULL == section) {
549 		return XBFalse;
550 	}
551 	/* get host data */
552 	memcpy (game, &defaultGame.host, sizeof (CFGGameHost));
553 	if (DB_GetEntryString (section, atomHost, &s)) {
554 		game->name = s;
555 	}
556 	(void)DB_GetEntryInt (section, atomPort, &game->port);
557 	(void)DB_GetEntryBool (section, atomFixedUdpPort, &game->fixedUdpPort);
558 	(void)DB_GetEntryBool (section, atomBrowseLan, &game->browseLan);
559 	(void)DB_GetEntryBool (section, atomAllowNat, &game->allowNat);
560 	(void)DB_GetEntryBool (section, atomCentral, &game->central);
561 	(void)DB_GetEntryString (section, atomGame, &game->game);
562 	(void)DB_GetEntryBool (section, atomBeep, &game->beep);
563 	return XBTrue;
564 }								/* RetrieveGameHost */
565 
566 /*
567  *
568  */
569 XBBool
RetrieveGameHost(CFGType cfgType,XBAtom atom,CFGGameHost * game)570 RetrieveGameHost (CFGType cfgType, XBAtom atom, CFGGameHost * game)
571 {
572 	return RetrieveAnyGameHost (GetDB (cfgType), atom, game);
573 }								/* RetrieveGameHost */
574 
575 /*
576  * get version data from any database
577  */
578 static XBBool
RetrieveAnyGameVersion(const DBRoot * db,XBAtom atom,XBVersion * ver)579 RetrieveAnyGameVersion (const DBRoot * db, XBAtom atom, XBVersion * ver)
580 {
581 	const DBSection *section;
582 	int maj, min, pat;
583 	assert (NULL != ver);
584 	/* find according db section */
585 	section = DB_GetSection (db, atom);
586 	if (NULL == section) {
587 		return XBFalse;
588 	}
589 	Version_Clear (ver);
590 	/* now extract version data */
591 	if (!DB_GetEntryInt (section, atomVersionMajor, &maj)) {
592 		return XBFalse;
593 	}
594 	if (!DB_GetEntryInt (section, atomVersionMinor, &min)) {
595 		return XBFalse;
596 	}
597 	if (!DB_GetEntryInt (section, atomVersionPatch, &pat)) {
598 		return XBFalse;
599 	}
600 	ver->major = maj & 0xFF;
601 	ver->minor = min & 0xFF;
602 	ver->patch = pat & 0xFF;
603 	return XBTrue;
604 }								/* RetrieveAnyGameVersion */
605 
606 /*
607  * get version data from config database
608  */
609 XBBool
RetrieveGameVersion(CFGType cfgType,XBAtom atom,XBVersion * ver)610 RetrieveGameVersion (CFGType cfgType, XBAtom atom, XBVersion * ver)
611 {
612 	return RetrieveAnyGameVersion (GetDB (cfgType), atom, ver);
613 }								/* RetrieveGameVersion */
614 
615 /*
616  * get game constants any database
617  */
618 static XBBool
RetrieveAnyGameConst(const DBRoot * db,XBAtom atom,CFGGameConst * con)619 RetrieveAnyGameConst (const DBRoot * db, XBAtom atom, CFGGameConst * con)
620 {
621 	const DBSection *section;
622 	int maj, min, pat;
623 	assert (NULL != con);
624 	/* set default */
625 	memcpy (con, &defaultGame.constants, sizeof (CFGGameConst));
626 	/* find according db section */
627 	section = DB_GetSection (db, atom);
628 	if (NULL == section) {
629 		return XBFalse;
630 	}
631 	/* extract constants */
632 	(void)DB_GetEntryInt (section, atomMaxHosts, &con->maxhosts);
633 	(void)DB_GetEntryInt (section, atomMaxPlayers, &con->maxplayers);
634 	(void)DB_GetEntryInt (section, atomMaxLocals, &con->maxlocals);
635 	(void)DB_GetEntryInt (section, atomMaxMaskBytes, &con->maxbytes);
636 	/* now extract version data */
637 	if (!DB_GetEntryInt (section, atomVersionMajor, &maj)) {
638 		return XBTrue;
639 	}
640 	if (!DB_GetEntryInt (section, atomVersionMinor, &min)) {
641 		return XBTrue;
642 	}
643 	if (!DB_GetEntryInt (section, atomVersionPatch, &pat)) {
644 		return XBTrue;
645 	}
646 	con->version.major = maj & 0xFF;
647 	con->version.minor = min & 0xFF;
648 	con->version.patch = pat & 0xFF;
649 	return XBTrue;
650 }								/* RetrieveAnyGameConst */
651 
652 /*
653  * get game constants from config database
654  */
655 XBBool
RetrieveGameConst(CFGType cfgType,XBAtom atom,CFGGameConst * con)656 RetrieveGameConst (CFGType cfgType, XBAtom atom, CFGGameConst * con)
657 {
658 	return RetrieveAnyGameConst (GetDB (cfgType), atom, con);
659 }								/* RetrieveGameConst */
660 
661 /*
662  * save game config at once
663  */
664 void
StoreGame(CFGType cfgType,XBAtom atom,const CFGGame * cfg)665 StoreGame (CFGType cfgType, XBAtom atom, const CFGGame * cfg)
666 {
667 	assert (NULL != cfg);
668 
669 	StoreGameSetup (cfgType, atom, &cfg->setup);
670 	StoreGamePlayers (cfgType, atom, &cfg->players);
671 	StoreGameHost (cfgType, atom, &cfg->host);
672 	StoreGameConst (cfgType, atom, &cfg->constants);
673 }								/* StoreGame */
674 
675 /*
676  * retrieve game config at once
677  */
678 XBBool
RetrieveGame(CFGType cfgType,XBAtom atom,CFGGame * cfg)679 RetrieveGame (CFGType cfgType, XBAtom atom, CFGGame * cfg)
680 {
681 	XBBool result = XBTrue;
682 
683 	assert (NULL != cfg);
684 
685 	if (!RetrieveGameSetup (cfgType, atom, &cfg->setup)) {
686 		result = XBFalse;
687 	}
688 	if (!RetrieveGamePlayers (cfgType, atom, &cfg->players)) {
689 		result = XBFalse;
690 	}
691 	if (!RetrieveGameHost (cfgType, atom, &cfg->host)) {
692 		result = XBFalse;
693 	}
694 	(void)RetrieveGameConst (cfgType, atom, &cfg->constants);
695 	return result;
696 }								/* RetrieveGame */
697 
698 /*
699  * load game config from file
700  */
701 void
LoadGameConfig(void)702 LoadGameConfig (void)
703 {
704 	/* remote database */
705 	dbRemote = DB_Create (DT_Config, atomRemoteGame);
706 	assert (dbRemote != NULL);
707 	/* local database */
708 	dbLocal = DB_Create (DT_Config, atomGame);
709 	assert (dbLocal != NULL);
710 	Dbg_Config ("loading local game config\n");
711 	if (DB_Load (dbLocal)) {
712 		return;
713 	}
714 	Dbg_Config ("failed to load local game config, setting defaults\n");
715 	/* set default values */
716 	DefaultPlayerData ();
717 	StoreGame (CT_Local, atomLocal, &defaultGame);
718 	StoreGame (CT_Local, atomServer, &defaultGame);
719 	StoreGame (CT_Local, atomClient, &defaultGame);
720 	/* and save it */
721 	DB_Store (dbLocal);
722 }								/* LoadGameConfig */
723 
724 /*
725  * save game config to file
726  */
727 void
SaveGameConfig(void)728 SaveGameConfig (void)
729 {
730 	assert (dbLocal != NULL);
731 	if (DB_Changed (dbLocal)) {
732 		Dbg_Config ("saving local game config\n");
733 		DB_Store (dbLocal);
734 	}
735 #ifdef DEBUG
736 	assert (dbRemote != NULL);
737 	if (DB_Changed (dbRemote)) {
738 		Dbg_Config ("saving remote game config\n");
739 		DB_Store (dbRemote);
740 	}
741 #endif
742 }								/* SaveGameConfig */
743 
744 /*
745  * remove game configs
746  */
747 void
FinishGameConfig(void)748 FinishGameConfig (void)
749 {
750 	if (NULL != dbLocal) {
751 		DB_Delete (dbLocal);
752 		dbLocal = NULL;
753 	}
754 	if (NULL != dbRemote) {
755 		DB_Delete (dbRemote);
756 		dbRemote = NULL;
757 	}
758 	Dbg_Config ("game config cleared!\n");
759 }								/* FinishGameConfig */
760 
761 /*
762  * put game config into telegram send queue
763  */
764 XBBool
SendGameConfig(CFGType cfgType,XBSndQueue * queue,XBTeleCOT cot,XBTeleIOB iob,XBAtom atom)765 SendGameConfig (CFGType cfgType, XBSndQueue * queue, XBTeleCOT cot, XBTeleIOB iob, XBAtom atom)
766 {
767 	const DBSection *section;
768 	int i;
769 	size_t len;
770 	XBTelegram *tele;
771 	char tmp[256];
772 
773 	assert (queue != NULL);
774 	/* get section with game data */
775 	section = DB_GetSection (GetDB (cfgType), atom);
776 	if (NULL == section) {
777 		return XBFalse;
778 	}
779 	/* now print and send data */
780 	i = 0;
781 	while (0 < (len = DB_PrintEntry (tmp, section, i))) {
782 		tele = Net_CreateTelegram (cot, XBT_ID_GameConfig, iob, tmp, len + 1);
783 		assert (tele != NULL);
784 		Net_SendTelegram (queue, tele);
785 		i++;
786 	}
787 	/* no data means end of section */
788 	tele = Net_CreateTelegram (cot, XBT_ID_GameConfig, iob, NULL, 0);
789 	assert (tele != NULL);
790 	Net_SendTelegram (queue, tele);
791 	return XBTrue;
792 }								/* SendGameConfig */
793 
794 /*
795  * delete a game config
796  */
797 void
DeleteGameConfig(CFGType cfgType,XBAtom atom)798 DeleteGameConfig (CFGType cfgType, XBAtom atom)
799 {
800 	DB_DeleteSection (GetDB (cfgType), atom);
801 }								/* DeleteGameConfig */
802 
803 /*
804  * add entry line to game config
805  */
806 void
AddToGameConfig(CFGType cfgType,XBAtom atom,const char * line)807 AddToGameConfig (CFGType cfgType, XBAtom atom, const char *line)
808 {
809 	DBSection *section;
810 
811 	/* sanity check */
812 	assert (ATOM_INVALID != atom);
813 	/* create new game section */
814 	section = DB_CreateSection (GetDB (cfgType), atom);
815 	assert (NULL != section);
816 	/* add line */
817 	(void)DB_ParseEntry (section, line);
818 }								/* AddToGameConfig */
819 
820 /*
821  * return hostname and port
822  */
823 const char *
GetHostName(CFGType cfgType,XBAtom atom)824 GetHostName (CFGType cfgType, XBAtom atom)
825 {
826 	CFGGameHost cfg;
827 	static char txt[256];
828 
829 	/* sanity check */
830 	assert (ATOM_INVALID != atom);
831 	/* get host config */
832 	if (!RetrieveGameHost (cfgType, atom, &cfg)) {
833 		strcpy (txt, "unknown");
834 	}
835 	else {
836 		sprintf (txt, "%s:%d", cfg.name, cfg.port);
837 	}
838 	return txt;
839 }								/* GetRemoteHostName */
840 
841  /*
842   * push a single ip into ip history database
843   */
844 void
StoreIpHistory(CFGGameHost * host,XBAtom atom)845 StoreIpHistory (CFGGameHost * host, XBAtom atom)
846 {
847 	DBSection *section;
848 	CFGGameHost hist[10];
849 	int i = 0;
850 	/* sanity check */
851 	assert (ATOM_INVALID != atom);
852 	assert (NULL != host);
853 	section = (DBSection *) DB_GetSection (GetDB (CT_Local), atom);
854 	/* get old history data */
855 	assert (NULL != section);
856 	RetrieveIpHistory (hist, atom);
857 	/* push back server data */
858 	for (i = 9; i > 0; i--) {
859 		hist[i].name = hist[i - 1].name;
860 		hist[i].port = hist[i - 1].port;
861 	}
862 	/* store latest host data */
863 	hist[0].port = host->port;
864 	hist[0].name = host->name;
865 	/* store back to database, backwards (important for pointer validity!) */
866 	for (i = 9; i >= 0; i--) {
867 		if (NULL != hist[i].name) {
868 			DB_CreateEntryString (section, atomGamehis[i], hist[i].name);
869 			DB_CreateEntryInt (section, atomPorthis[i], hist[i].port);
870 		}
871 		else {
872 			DB_DeleteEntry (section, atomGamehis[i]);
873 			DB_DeleteEntry (section, atomPorthis[i]);
874 		}
875 	}
876 	RetrieveIpHistory (hist, atom);
877 }								/* StoreIpHistory */
878 
879 /*
880  * retrieve all ip history data
881  */
882 XBBool
RetrieveIpHistory(CFGGameHost host[10],XBAtom atom)883 RetrieveIpHistory (CFGGameHost host[10], XBAtom atom)
884 {
885 	const DBSection *section;
886 	int i = 0;
887 	section = DB_GetSection (GetDB (CT_Local), atom);
888 	/* check if there is section with ip history data */
889 	if (NULL == section) {
890 		return XBFalse;
891 	}
892 	/* retrieve data */
893 	for (i = 0; i < 10; i++) {
894 		/* first default data for entry */
895 		host[i].name = NULL;
896 		host[i].game = NULL;
897 		host[i].port = 0;
898 		/* now update from database */
899 		(void)DB_GetEntryString (section, atomGamehis[i], &host[i].name);
900 		(void)DB_GetEntryInt (section, atomPorthis[i], &host[i].port);
901 	}
902 	return XBTrue;
903 }								/* RetrieveIpHistory */
904 
905 /*
906  * end of file cfg_game.c
907  */
908