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