core/GameConfigs.cpp
author David Anderson <dvander@alliedmods.net>
Thu Jun 21 23:06:37 2007 +0000 (2007-06-21)
changeset 997 2fc3152c3118
parent 973 0407a17cb219
child 1043 6e253ddd10c4
permissions -rw-r--r--
bumped menu api again - added feature to get menu end reason
dvander@547
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@547
     3
 * ===============================================================
dvander@547
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@547
     5
 * ===============================================================
dvander@547
     6
 *
dvander@547
     7
 * This file is not open source and may not be copied without explicit
dvander@547
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@547
     9
 * in whole or significant part.
dvander@547
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@547
    11
 *
dvander@547
    12
 * Version: $Id$
dvander@547
    13
 */
dvander@547
    14
dvander@547
    15
#include <string.h>
dvander@547
    16
#include <stdlib.h>
dvander@592
    17
#include "GameConfigs.h"
dvander@591
    18
#include "TextParsers.h"
dvander@547
    19
#include "sm_stringutil.h"
dvander@547
    20
#include "sourcemod.h"
dvander@547
    21
#include "sourcemm_api.h"
dvander@592
    22
#include "HalfLife2.h"
dvander@592
    23
#include "Logger.h"
dvander@547
    24
#include "ShareSys.h"
dvander@947
    25
#include "MemoryUtils.h"
dvander@947
    26
#include "LibrarySys.h"
dvander@949
    27
#include "HandleSys.h"
dvander@947
    28
dvander@947
    29
#if defined PLATFORM_LINUX
dvander@947
    30
#include <dlfcn.h>
dvander@947
    31
#endif
dvander@547
    32
dvander@616
    33
GameConfigManager g_GameConfigs;
dvander@547
    34
IGameConfig *g_pGameConf = NULL;
dvander@547
    35
char g_mod[255];
dvander@547
    36
dvander@547
    37
#define PSTATE_NONE						0
dvander@547
    38
#define PSTATE_GAMES					1
dvander@547
    39
#define PSTATE_GAMEDEFS					2
dvander@547
    40
#define PSTATE_GAMEDEFS_OFFSETS			3
dvander@547
    41
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET	4
dvander@548
    42
#define PSTATE_GAMEDEFS_KEYS			5
dvander@947
    43
#define PSTATE_GAMEDEFS_SUPPORTED		6
dvander@947
    44
#define PSTATE_GAMEDEFS_SIGNATURES		7
dvander@947
    45
#define PSTATE_GAMEDEFS_SIGNATURES_SIG	8
dvander@547
    46
dvander@547
    47
#if defined PLATFORM_WINDOWS
dvander@547
    48
#define PLATFORM_NAME	"windows"
dvander@547
    49
#elif defined PLATFORM_LINUX
dvander@547
    50
#define PLATFORM_NAME	"linux"
dvander@547
    51
#endif
dvander@547
    52
dvander@947
    53
struct TempSigInfo
dvander@947
    54
{
dvander@947
    55
	void Reset()
dvander@947
    56
	{
dvander@947
    57
		library[0] = '\0';
dvander@947
    58
		sig[0] = '\0';
dvander@947
    59
	}
dvander@947
    60
	char sig[512];
dvander@947
    61
	char library[64];
dvander@947
    62
} s_TempSig;
dvander@947
    63
dvander@547
    64
CGameConfig::CGameConfig(const char *file)
dvander@547
    65
{
dvander@547
    66
	m_pFile = sm_strdup(file);
dvander@547
    67
	m_pOffsets = sm_trie_create();
dvander@547
    68
	m_pProps = sm_trie_create();
dvander@548
    69
	m_pKeys = sm_trie_create();
dvander@947
    70
	m_pSigs = sm_trie_create();
dvander@548
    71
	m_pStrings = new BaseStringTable(512);
faluco@641
    72
	m_RefCount = 0;
dvander@547
    73
}
dvander@547
    74
dvander@547
    75
CGameConfig::~CGameConfig()
dvander@547
    76
{
dvander@547
    77
	sm_trie_destroy(m_pOffsets);
dvander@547
    78
	sm_trie_destroy(m_pProps);
dvander@548
    79
	sm_trie_destroy(m_pKeys);
dvander@947
    80
	sm_trie_destroy(m_pSigs);
dvander@547
    81
	delete [] m_pFile;
dvander@548
    82
	delete m_pStrings;
dvander@547
    83
}
dvander@547
    84
dvander@547
    85
SMCParseResult CGameConfig::ReadSMC_NewSection(const char *name, bool opt_quotes)
dvander@547
    86
{
dvander@547
    87
	if (m_IgnoreLevel)
dvander@547
    88
	{
dvander@547
    89
		m_IgnoreLevel++;
dvander@547
    90
		return SMCParse_Continue;
dvander@547
    91
	}
dvander@947
    92
dvander@547
    93
	switch (m_ParseState)
dvander@547
    94
	{
dvander@547
    95
	case PSTATE_NONE:
dvander@547
    96
		{
dvander@547
    97
			if (strcmp(name, "Games") == 0)
dvander@547
    98
			{
dvander@547
    99
				m_ParseState = PSTATE_GAMES;
dvander@547
   100
			} else {
dvander@547
   101
				m_IgnoreLevel++;
dvander@547
   102
			}
dvander@547
   103
			break;
dvander@547
   104
		}
dvander@547
   105
	case PSTATE_GAMES:
dvander@547
   106
		{
dvander@547
   107
			if ((strcmp(name, "*") == 0)
dvander@947
   108
				|| (strcmp(name, "#default") == 0)
dvander@547
   109
				|| (strcmp(name, g_mod) == 0))
dvander@547
   110
			{
dvander@547
   111
				m_ParseState = PSTATE_GAMEDEFS;
dvander@547
   112
				strncopy(m_mod, name, sizeof(m_mod));
dvander@547
   113
			} else {
dvander@547
   114
				m_IgnoreLevel++;
dvander@547
   115
			}
dvander@547
   116
			break;
dvander@547
   117
		}
dvander@547
   118
	case PSTATE_GAMEDEFS:
dvander@547
   119
		{
dvander@547
   120
			if (strcmp(name, "Offsets") == 0)
dvander@547
   121
			{
dvander@547
   122
				m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
dvander@947
   123
			}
dvander@947
   124
			else if (strcmp(name, "Keys") == 0)
dvander@947
   125
			{
dvander@548
   126
				m_ParseState = PSTATE_GAMEDEFS_KEYS;
dvander@947
   127
			}
dvander@947
   128
			else if ((strcmp(name, "#supported") == 0)
dvander@947
   129
					 && (strcmp(m_mod, "#default") == 0))
dvander@947
   130
			{
dvander@947
   131
				m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
dvander@947
   132
				/* Ignore this section unless we get a game. */
dvander@947
   133
				bShouldBeReadingDefault = false;
dvander@947
   134
			}
dvander@947
   135
			else if (strcmp(name, "Signatures") == 0)
dvander@947
   136
			{
dvander@947
   137
				m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
dvander@947
   138
			}
dvander@947
   139
			else
dvander@947
   140
			{
dvander@547
   141
				m_IgnoreLevel++;
dvander@547
   142
			}
dvander@547
   143
			break;
dvander@547
   144
		}
dvander@547
   145
	case PSTATE_GAMEDEFS_OFFSETS:
dvander@547
   146
		{
dvander@547
   147
			m_prop[0] = '\0';
dvander@547
   148
			m_class[0] = '\0';
dvander@547
   149
			strncopy(m_offset, name, sizeof(m_offset));
dvander@547
   150
			m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
dvander@547
   151
			break;
dvander@547
   152
		}
dvander@947
   153
	case PSTATE_GAMEDEFS_SIGNATURES:
dvander@947
   154
		{
dvander@947
   155
			strncopy(m_offset, name, sizeof(m_offset));
dvander@947
   156
			s_TempSig.Reset();
dvander@947
   157
			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
dvander@947
   158
			break;
dvander@947
   159
		}
dvander@547
   160
	/* No sub-sections allowed:
dvander@547
   161
	 case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
dvander@548
   162
	 case PSTATE_GAMEDEFS_KEYS:
dvander@947
   163
	 case PSTATE_GAMEDEFS_SUPPORTED:
dvander@947
   164
	 case PSTATE_GAMEDEFS_SIGNATURES_SIG:
dvander@547
   165
	 */
dvander@547
   166
	default:
dvander@547
   167
		{
dvander@547
   168
			/* If we don't know what we got, start ignoring */
dvander@547
   169
			m_IgnoreLevel++;
dvander@547
   170
			break;
dvander@547
   171
		}
dvander@547
   172
	}
dvander@547
   173
dvander@547
   174
	return SMCParse_Continue;
dvander@547
   175
}
dvander@547
   176
dvander@547
   177
SMCParseResult CGameConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
dvander@547
   178
{
dvander@547
   179
	if (m_IgnoreLevel)
dvander@547
   180
	{
dvander@547
   181
		return SMCParse_Continue;
dvander@547
   182
	}
dvander@547
   183
dvander@547
   184
	if (m_ParseState == PSTATE_GAMEDEFS_OFFSETS_OFFSET)
dvander@547
   185
	{
dvander@547
   186
		if (strcmp(key, "class") == 0)
dvander@547
   187
		{
dvander@547
   188
			strncopy(m_class, value, sizeof(m_class));
dvander@547
   189
		} else if (strcmp(key, "prop") == 0) {
dvander@547
   190
			strncopy(m_prop, value, sizeof(m_prop));
dvander@547
   191
		} else if (strcmp(key, PLATFORM_NAME) == 0) {
dvander@547
   192
			int val = atoi(value);
dvander@547
   193
			sm_trie_insert(m_pOffsets, m_offset, (void *)val);
dvander@547
   194
		}
dvander@548
   195
	} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
dvander@548
   196
		int id = m_pStrings->AddString(value);
dvander@548
   197
		sm_trie_insert(m_pKeys, key, (void *)id);
dvander@947
   198
	} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
dvander@947
   199
		if (strcmp(key, "game") == 0
dvander@947
   200
			&& strcmp(value, g_mod) == 0)
dvander@947
   201
		{
dvander@947
   202
			bShouldBeReadingDefault = true;
dvander@947
   203
		}
dvander@947
   204
	} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
dvander@947
   205
		if (strcmp(key, PLATFORM_NAME) == 0)
dvander@947
   206
		{
dvander@947
   207
			strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig));
dvander@947
   208
		} else if (strcmp(key, "library") == 0) {
dvander@947
   209
			strncopy(s_TempSig.library, value, sizeof(s_TempSig.library));
dvander@947
   210
		}
dvander@547
   211
	}
dvander@547
   212
dvander@547
   213
	return SMCParse_Continue;
dvander@547
   214
}
dvander@547
   215
dvander@547
   216
SMCParseResult CGameConfig::ReadSMC_LeavingSection()
dvander@547
   217
{
dvander@547
   218
	if (m_IgnoreLevel)
dvander@547
   219
	{
dvander@547
   220
		m_IgnoreLevel--;
dvander@547
   221
		return SMCParse_Continue;
dvander@547
   222
	}
dvander@547
   223
dvander@547
   224
	switch (m_ParseState)
dvander@547
   225
	{
dvander@547
   226
	case PSTATE_GAMES:
dvander@547
   227
		{
dvander@547
   228
			m_ParseState = PSTATE_NONE;
dvander@547
   229
			break;
dvander@547
   230
		}
dvander@547
   231
	case PSTATE_GAMEDEFS:
dvander@547
   232
		{
dvander@547
   233
			m_ParseState = PSTATE_GAMES;
dvander@547
   234
			break;
dvander@547
   235
		}
dvander@548
   236
	case PSTATE_GAMEDEFS_KEYS:
dvander@547
   237
	case PSTATE_GAMEDEFS_OFFSETS:
dvander@547
   238
		{
dvander@547
   239
			m_ParseState = PSTATE_GAMEDEFS;
dvander@547
   240
			break;
dvander@547
   241
		}
dvander@547
   242
	case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
dvander@547
   243
		{
dvander@547
   244
			/* Parse the offset... */
dvander@547
   245
			if (m_class[0] != '\0'
dvander@547
   246
				&& m_prop[0] != '\0')
dvander@547
   247
			{
dvander@547
   248
				SendProp *pProp = g_HL2.FindInSendTable(m_class, m_prop);
dvander@547
   249
				if (pProp)
dvander@547
   250
				{
dvander@547
   251
					int val = pProp->GetOffset();
dvander@547
   252
					sm_trie_insert(m_pOffsets, m_offset, (void *)val);
dvander@547
   253
					sm_trie_insert(m_pProps, m_offset, pProp);
dvander@547
   254
				} else {
dvander@547
   255
					/* Check if it's a non-default game and no offsets exist */
dvander@947
   256
					if (((strcmp(m_mod, "*") != 0) && strcmp(m_mod, "#default") != 0)
dvander@547
   257
						&& (!sm_trie_retrieve(m_pOffsets, m_offset, NULL)))
dvander@547
   258
					{
dvander@547
   259
						g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", 
dvander@547
   260
							m_class,
dvander@547
   261
							m_prop,
dvander@547
   262
							m_pFile,
dvander@547
   263
							m_mod);
dvander@547
   264
					}
dvander@547
   265
				}
dvander@547
   266
			}
dvander@547
   267
			m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
dvander@547
   268
			break;
dvander@547
   269
		}
dvander@947
   270
	case PSTATE_GAMEDEFS_SUPPORTED:
dvander@947
   271
		{
dvander@947
   272
			if (!bShouldBeReadingDefault)
dvander@947
   273
			{
dvander@947
   274
				/* If we shouldn't read the rest of this section, set the ignore level. */
dvander@947
   275
				m_IgnoreLevel = 1;
dvander@947
   276
			}
dvander@947
   277
			m_ParseState = PSTATE_GAMEDEFS;
dvander@947
   278
			break;
dvander@947
   279
		}
dvander@969
   280
	case PSTATE_GAMEDEFS_SIGNATURES:
dvander@969
   281
		{
dvander@969
   282
			m_ParseState = PSTATE_GAMEDEFS;
dvander@969
   283
			break;
dvander@969
   284
		}
dvander@947
   285
	case PSTATE_GAMEDEFS_SIGNATURES_SIG:
dvander@947
   286
		{
dvander@947
   287
			if (s_TempSig.library[0] == '\0')
dvander@947
   288
			{
dvander@947
   289
				/* assume server */
dvander@947
   290
				strncopy(s_TempSig.library, "server", sizeof(s_TempSig.library));
dvander@947
   291
			}
dvander@947
   292
			void *addrInBase = NULL;
dvander@947
   293
			if (strcmp(s_TempSig.library, "server") == 0)
dvander@947
   294
			{
dvander@951
   295
				addrInBase = (void *)g_SMAPI->serverFactory(false);
dvander@947
   296
			} else if (strcmp(s_TempSig.library, "engine") == 0) {
dvander@951
   297
				addrInBase = (void *)g_SMAPI->engineFactory(false);
dvander@947
   298
			}
dvander@947
   299
			void *final_addr = NULL;
dvander@947
   300
			if (addrInBase == NULL)
dvander@947
   301
			{
dvander@947
   302
				g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", 
dvander@947
   303
					s_TempSig.library, 
dvander@947
   304
					m_pFile);
dvander@947
   305
			} else {
dvander@947
   306
#if defined PLATFORM_LINUX
dvander@951
   307
				if (s_TempSig.sig[0] == '@')
dvander@947
   308
				{
dvander@947
   309
					Dl_info info;
dvander@947
   310
					/* GNU only: returns 0 on error, inconsistent! >:[ */
dvander@973
   311
					if (dladdr(addrInBase, &info) != 0)
dvander@947
   312
					{
dvander@947
   313
						void *handle = dlopen(info.dli_fname, RTLD_NOW);
dvander@947
   314
						if (handle)
dvander@947
   315
						{
dvander@951
   316
							final_addr = dlsym(handle, &s_TempSig.sig[1]);
dvander@947
   317
							dlclose(handle);
dvander@947
   318
						} else {
dvander@947
   319
							g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
dvander@947
   320
								s_TempSig.library,
dvander@947
   321
								m_pFile);
dvander@947
   322
						}
dvander@947
   323
					} else {
dvander@947
   324
						g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
dvander@947
   325
							s_TempSig.library,
dvander@947
   326
							m_pFile);
dvander@947
   327
					}
dvander@947
   328
					if (!final_addr)
dvander@947
   329
					{
dvander@947
   330
						g_Logger.LogError("[SM] Unable to find named symbol (symbol \"%s\") (library \"%s\") (gameconf \"%s\")",
dvander@951
   331
							&s_TempSig.sig[1],
dvander@947
   332
							s_TempSig.library,
dvander@947
   333
							m_pFile);
dvander@947
   334
					}
dvander@947
   335
				}
dvander@947
   336
				if (final_addr)
dvander@947
   337
				{
dvander@947
   338
					goto skip_find;
dvander@947
   339
				}
dvander@947
   340
#endif
dvander@947
   341
				/* First, preprocess the signature */
dvander@947
   342
				char real_sig[255];
dvander@947
   343
				size_t real_bytes;
dvander@947
   344
				size_t length;
dvander@947
   345
dvander@947
   346
				real_bytes = 0;
dvander@947
   347
				length = strlen(s_TempSig.sig);
dvander@947
   348
dvander@947
   349
				for (size_t i=0; i<length; i++)
dvander@947
   350
				{
dvander@947
   351
					if (real_bytes >= sizeof(real_sig))
dvander@947
   352
					{
dvander@947
   353
						break;
dvander@947
   354
					}
dvander@947
   355
					real_sig[real_bytes++] = s_TempSig.sig[i];
dvander@947
   356
					if (s_TempSig.sig[i] == '\\'
dvander@947
   357
						&& s_TempSig.sig[i+1] == 'x')
dvander@947
   358
					{
dvander@947
   359
						if (i + 3 >= length)
dvander@947
   360
						{
dvander@947
   361
							continue;
dvander@947
   362
						}
dvander@947
   363
						/* Get the hex part */
dvander@947
   364
						char s_byte[3];
dvander@947
   365
						int r_byte;
dvander@947
   366
						s_byte[0] = s_TempSig.sig[i+2];
dvander@947
   367
						s_byte[1] = s_TempSig.sig[i+3];
dvander@947
   368
						s_byte[2] = '\0';
dvander@947
   369
						/* Read it as an integer */
dvander@947
   370
						sscanf(s_byte, "%x", &r_byte);
dvander@947
   371
						/* Save the value */
dvander@947
   372
						real_sig[real_bytes-1] = r_byte;
dvander@947
   373
						/* Adjust index */
dvander@947
   374
						i += 3;
dvander@947
   375
					}
dvander@947
   376
				}
dvander@947
   377
dvander@947
   378
				if (real_bytes < 1)
dvander@947
   379
				{
dvander@969
   380
					g_Logger.LogError("[SM] Invalid signature (name \"%s\") (gameconf \"%s\")",
dvander@947
   381
						m_offset,
dvander@947
   382
						m_pFile);
dvander@947
   383
				} else {
dvander@947
   384
					final_addr = g_MemUtils.FindPattern(addrInBase, real_sig, real_bytes);
dvander@947
   385
					if (!final_addr)
dvander@947
   386
					{
dvander@947
   387
						g_Logger.LogError("[SM] Unable to find signature (name \"%s\") (gameconf \"%s\")", 
dvander@947
   388
							m_offset,
dvander@947
   389
							m_pFile);
dvander@947
   390
					}
dvander@947
   391
				}
dvander@947
   392
			}
dvander@947
   393
dvander@947
   394
#if defined PLATFORM_LINUX
dvander@947
   395
skip_find:
dvander@947
   396
#endif
dvander@947
   397
			sm_trie_insert(m_pSigs, m_offset, final_addr);
dvander@964
   398
			m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
dvander@947
   399
dvander@947
   400
			break;
dvander@947
   401
		}
dvander@547
   402
	}
dvander@547
   403
dvander@547
   404
	return SMCParse_Continue;
dvander@547
   405
}
dvander@547
   406
dvander@547
   407
bool CGameConfig::Reparse(char *error, size_t maxlength)
dvander@547
   408
{
dvander@547
   409
	SMCParseError err;
dvander@547
   410
dvander@547
   411
	char path[PLATFORM_MAX_PATH];
dvander@947
   412
	g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile);
dvander@947
   413
	/* Backwards compatibility */
dvander@947
   414
	if (!g_LibSys.PathExists(path))
dvander@947
   415
	{
dvander@947
   416
		g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
dvander@947
   417
	}
dvander@547
   418
dvander@548
   419
	/* Initialize parse states */
dvander@547
   420
	m_IgnoreLevel = 0;
dvander@947
   421
	bShouldBeReadingDefault = true;
dvander@547
   422
	m_ParseState = PSTATE_NONE;
dvander@548
   423
	/* Reset cached data */
dvander@548
   424
	m_pStrings->Reset();
dvander@547
   425
	sm_trie_clear(m_pOffsets);
dvander@548
   426
	sm_trie_clear(m_pProps);
dvander@548
   427
	sm_trie_clear(m_pKeys);
dvander@547
   428
dvander@547
   429
	if ((err=g_TextParser.ParseFile_SMC(path, this, NULL, NULL))
dvander@547
   430
		!= SMCParse_Okay)
dvander@547
   431
	{
dvander@547
   432
		if (error && (err != SMCParse_Custom))
dvander@547
   433
		{
dvander@547
   434
			const char *str = g_TextParser.GetSMCErrorString(err);
dvander@551
   435
			snprintf(error, maxlength, "%s", str);
dvander@547
   436
		}
dvander@547
   437
		return false;
dvander@547
   438
	}
dvander@547
   439
dvander@547
   440
	return true;
dvander@547
   441
}
dvander@547
   442
dvander@547
   443
bool CGameConfig::GetOffset(const char *key, int *value)
dvander@547
   444
{
dvander@547
   445
	void *obj;
dvander@547
   446
dvander@547
   447
	if (!sm_trie_retrieve(m_pOffsets, key, &obj))
dvander@547
   448
	{
dvander@547
   449
		return false;
dvander@547
   450
	}
dvander@547
   451
dvander@547
   452
	*value = (int)obj;
dvander@547
   453
	
dvander@547
   454
	return true;
dvander@547
   455
}
dvander@547
   456
dvander@547
   457
const char *CGameConfig::GetKeyValue(const char *key)
dvander@547
   458
{
dvander@548
   459
	void *obj;
dvander@548
   460
	if (!sm_trie_retrieve(m_pKeys, key, &obj))
dvander@548
   461
	{
dvander@548
   462
		return NULL;
dvander@548
   463
	}
dvander@548
   464
	return m_pStrings->GetString((int)obj);
dvander@547
   465
}
dvander@547
   466
dvander@547
   467
SendProp *CGameConfig::GetSendProp(const char *key)
dvander@547
   468
{
dvander@547
   469
	SendProp *pProp;
dvander@547
   470
dvander@547
   471
	if (!sm_trie_retrieve(m_pProps, key, (void **)&pProp))
dvander@547
   472
	{
dvander@547
   473
		return NULL;
dvander@547
   474
	}
dvander@547
   475
dvander@547
   476
	return pProp;
dvander@547
   477
}
dvander@547
   478
dvander@947
   479
bool CGameConfig::GetMemSig(const char *key, void **addr)
dvander@947
   480
{
dvander@947
   481
	return sm_trie_retrieve(m_pSigs, key, addr);
dvander@947
   482
}
dvander@947
   483
dvander@547
   484
void CGameConfig::IncRefCount()
dvander@547
   485
{
dvander@547
   486
	m_RefCount++;
dvander@547
   487
}
dvander@547
   488
dvander@547
   489
unsigned int CGameConfig::DecRefCount()
dvander@547
   490
{
dvander@547
   491
	m_RefCount--;
dvander@547
   492
	return m_RefCount;
dvander@547
   493
}
dvander@547
   494
dvander@616
   495
GameConfigManager::GameConfigManager()
dvander@547
   496
{
dvander@547
   497
	m_pLookup = sm_trie_create();
dvander@547
   498
}
dvander@547
   499
dvander@616
   500
GameConfigManager::~GameConfigManager()
dvander@547
   501
{
dvander@547
   502
	sm_trie_destroy(m_pLookup);
dvander@547
   503
}
dvander@547
   504
dvander@616
   505
void GameConfigManager::OnSourceModStartup(bool late)
dvander@547
   506
{
dvander@547
   507
	LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
dvander@547
   508
ds@729
   509
	strncopy(g_mod, g_SourceMod.GetGameFolderName(), sizeof(g_mod));
dvander@547
   510
}
dvander@547
   511
dvander@616
   512
void GameConfigManager::OnSourceModAllInitialized()
dvander@547
   513
{
dvander@547
   514
	/* NOW initialize the game file */
dvander@547
   515
	CGameConfig *pGameConf = (CGameConfig *)g_pGameConf;
dvander@547
   516
	
dvander@547
   517
	char error[255];
dvander@547
   518
	if (!pGameConf->Reparse(error, sizeof(error)))
dvander@547
   519
	{
dvander@547
   520
		/* :TODO: log */
dvander@547
   521
	}
dvander@547
   522
dvander@547
   523
	g_ShareSys.AddInterface(NULL, this);
dvander@547
   524
}
dvander@547
   525
dvander@616
   526
void GameConfigManager::OnSourceModAllShutdown()
dvander@547
   527
{
dvander@547
   528
	CloseGameConfigFile(g_pGameConf);
dvander@547
   529
}
dvander@547
   530
dvander@616
   531
bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength)
dvander@547
   532
{
dvander@547
   533
	CGameConfig *pConfig;
dvander@547
   534
dvander@547
   535
	if (sm_trie_retrieve(m_pLookup, file, (void **)&pConfig))
dvander@547
   536
	{
dvander@547
   537
		pConfig->IncRefCount();
dvander@547
   538
		*_pConfig = pConfig;
dvander@547
   539
		return true;
dvander@547
   540
	}
dvander@547
   541
dvander@547
   542
	pConfig = new CGameConfig(file);
dvander@547
   543
dvander@547
   544
	/* :HACKHACK: Don't parse the main config file */
dvander@547
   545
	bool retval = true;
dvander@547
   546
	if (_pConfig != &g_pGameConf)
dvander@547
   547
	{
dvander@547
   548
		retval = pConfig->Reparse(error, maxlength);
dvander@547
   549
	}
dvander@547
   550
dvander@547
   551
	m_cfgs.push_back(pConfig);
dvander@547
   552
	sm_trie_insert(m_pLookup, file, pConfig);
dvander@547
   553
dvander@547
   554
	pConfig->IncRefCount();
dvander@547
   555
dvander@547
   556
	*_pConfig = pConfig;
dvander@547
   557
dvander@547
   558
	return retval;
dvander@547
   559
}
dvander@547
   560
dvander@616
   561
void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
dvander@547
   562
{
dvander@547
   563
	CGameConfig *pConfig = (CGameConfig *)cfg;
dvander@547
   564
dvander@547
   565
	if (pConfig->DecRefCount() == 0)
dvander@547
   566
	{
dvander@971
   567
		sm_trie_delete(m_pLookup, pConfig->m_pFile);
dvander@547
   568
		delete pConfig;
dvander@547
   569
	}
dvander@547
   570
}
dvander@949
   571
dvander@949
   572
extern HandleType_t g_GameConfigsType;
dvander@949
   573
dvander@949
   574
IGameConfig *GameConfigManager::ReadHandle(Handle_t hndl, IdentityToken_t *ident, HandleError *err)
dvander@949
   575
{
dvander@949
   576
	HandleSecurity sec(ident, g_pCoreIdent);
dvander@949
   577
	IGameConfig *conf = NULL;
dvander@949
   578
	HandleError _err = g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&conf);
dvander@949
   579
dvander@949
   580
	if (err)
dvander@949
   581
	{
dvander@949
   582
		*err = _err;
dvander@949
   583
	}
dvander@949
   584
dvander@949
   585
	return conf;
dvander@949
   586
}