Move hamdata.ini to gamedata (#597)
* Replace atoi by strtol in the config parser * Move hamdata.ini data to gamedata files * Reference the new files in master file * Remove all the parsing code and use config manager to get the offsets * Remove any hamdata.ini references
This commit is contained in:
@ -11,381 +11,46 @@
|
||||
// Ham Sandwich Module
|
||||
//
|
||||
|
||||
#include "amxxmodule.h"
|
||||
|
||||
#include <amxxmodule.h>
|
||||
#include "ham_const.h"
|
||||
#include "hooklist.h"
|
||||
#include "offsets.h"
|
||||
#include <amtl/am-string.h>
|
||||
|
||||
extern hook_t hooklist[];
|
||||
IGameConfig *CommonConfig;
|
||||
IGameConfigManager *ConfigManager;
|
||||
|
||||
enum
|
||||
{
|
||||
LEX_INVALID = 0,
|
||||
|
||||
LEX_UNKNOWN,
|
||||
|
||||
LEX_START_SEC,
|
||||
LEX_END_SEC,
|
||||
|
||||
LEX_MIRROR,
|
||||
|
||||
LEX_PEV,
|
||||
LEX_BASE,
|
||||
|
||||
LEX_END
|
||||
};
|
||||
|
||||
const char *tokens[] =
|
||||
{
|
||||
"", // LEX_INVALID
|
||||
|
||||
"", // LEX_UNKNOWN
|
||||
|
||||
"@section", // LEX_START_SEC
|
||||
"@end", // LEX_END_SEC
|
||||
|
||||
"@mirror", // LEX_MIRROR
|
||||
|
||||
"pev", // LEX_PEV
|
||||
"base", // LEX_BASE
|
||||
|
||||
"", // LEX_END
|
||||
};
|
||||
|
||||
static void trim_line(char *input);
|
||||
static void read_mirror(char *input);
|
||||
static void skip_to_end_of_section(FILE *fp);
|
||||
static int lex(char*& buffer);
|
||||
|
||||
int lex(char*& buffer)
|
||||
{
|
||||
trim_line(buffer);
|
||||
|
||||
size_t len;
|
||||
|
||||
for (int i=0; i<LEX_END; i++)
|
||||
{
|
||||
if (tokens[i]!=NULL && *(tokens[i])!='\0')
|
||||
{
|
||||
len=strlen(tokens[i]);
|
||||
if (strncmp(buffer,tokens[i],len)==0)
|
||||
{
|
||||
buffer+=len+1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return LEX_UNKNOWN;
|
||||
}
|
||||
|
||||
// How we handle "mirrors"
|
||||
// We just note down the current mod name, and every time
|
||||
// we come across a mirror with the destination that matches
|
||||
// the current mod name, we change the current mod name to
|
||||
// the source for that mirror.
|
||||
|
||||
char CurrentModName[64];
|
||||
|
||||
static void read_mirror(char *input)
|
||||
{
|
||||
char *data=input;
|
||||
char *data2;
|
||||
|
||||
char source[64];
|
||||
char dest[64];
|
||||
|
||||
char old;
|
||||
while ( *data!=' ' &&
|
||||
*data!='\t' &&
|
||||
*data!='\0')
|
||||
{
|
||||
|
||||
data++;
|
||||
}
|
||||
|
||||
old=*data;
|
||||
*data='\0';
|
||||
|
||||
// mark down the source
|
||||
ke::SafeSprintf(source, sizeof(source), "%s", input);
|
||||
|
||||
*data=old;
|
||||
|
||||
while ( *data==' ' ||
|
||||
*data=='\t')
|
||||
{
|
||||
data++;
|
||||
}
|
||||
data2=data;
|
||||
|
||||
while ( *data!=' ' &&
|
||||
*data!='\t' &&
|
||||
*data!='\0')
|
||||
{
|
||||
data++;
|
||||
}
|
||||
old=*data;
|
||||
*data='\0';
|
||||
|
||||
ke::SafeSprintf(dest, sizeof(dest), "%s", data2);
|
||||
|
||||
*data=old;
|
||||
|
||||
if (strcmp(dest, CurrentModName)==0)
|
||||
{
|
||||
ke::SafeSprintf(CurrentModName, sizeof(CurrentModName), "%s", source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void trim_line(char *input)
|
||||
{
|
||||
char *oldinput=input;
|
||||
char *start=input;
|
||||
|
||||
while ( *start==' ' ||
|
||||
*start=='\t' ||
|
||||
*start=='\r' ||
|
||||
*start=='\n')
|
||||
{
|
||||
start++;
|
||||
}
|
||||
|
||||
// Overwrite the whitespace
|
||||
|
||||
if (start != input)
|
||||
{
|
||||
while ((*input++=*start++)!='\0')
|
||||
/* do nothing */ ;
|
||||
}
|
||||
|
||||
start=oldinput;
|
||||
|
||||
start+=strlen(start) - 1;
|
||||
|
||||
while ( start >= oldinput &&
|
||||
( *start == '\0' ||
|
||||
*start == ' ' ||
|
||||
*start == '\r' ||
|
||||
*start == '\n' ||
|
||||
*start == '\t'))
|
||||
{
|
||||
start--;
|
||||
}
|
||||
start++;
|
||||
*start='\0';
|
||||
|
||||
// Now find any comments and cut off at the start
|
||||
|
||||
while (*start != '\0')
|
||||
{
|
||||
if (*start == ';')
|
||||
{
|
||||
*start='\0';
|
||||
break;
|
||||
}
|
||||
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
void skip_to_end_of_section(FILE *fp)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
buffer[0]='\0';
|
||||
|
||||
fgets(buffer, sizeof(buffer)-1, fp);
|
||||
|
||||
trim_line(buffer);
|
||||
|
||||
char *b=&buffer[0];
|
||||
if (lex(b)==LEX_END_SEC)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static const char* get_localinfo( const char* name , const char* def = 0 )
|
||||
{
|
||||
const char* b = LOCALINFO( (char*)name );
|
||||
if (((b==0)||(*b==0)) && def )
|
||||
SET_LOCALINFO((char*)name,(char*)(b = def) );
|
||||
return b;
|
||||
}
|
||||
int read_start_section(char *data)
|
||||
{
|
||||
if (strncasecmp(data, CurrentModName, strlen(CurrentModName))==0)
|
||||
{
|
||||
data+=strlen(CurrentModName)+1;
|
||||
trim_line(data);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (strcmp(data, "windows")==0)
|
||||
#elif defined(__linux__)
|
||||
if (strcmp(data, "linux")==0)
|
||||
#elif defined(__APPLE__)
|
||||
if (strcmp(data, "mac")==0)
|
||||
#endif
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int read_number(char *input)
|
||||
{
|
||||
char *end; /* Temporary pointer, needed for strtoul(). */
|
||||
|
||||
// if begins with 0x or 0X it's to be interpretted as hex
|
||||
if (*input=='0' &&
|
||||
(*(input+1)=='x' || *(input+1)=='X'))
|
||||
{
|
||||
return strtoul(input,&end,16);
|
||||
}
|
||||
|
||||
// otherwise it's to be interpretted as base 10
|
||||
return strtoul(input,&end,10);
|
||||
}
|
||||
void process_pev(char *data)
|
||||
{
|
||||
trim_line(data);
|
||||
Offsets.SetPev(read_number(data));
|
||||
}
|
||||
void process_base(char *data)
|
||||
{
|
||||
trim_line(data);
|
||||
Offsets.SetBase(read_number(data));
|
||||
}
|
||||
void process_key(char *data)
|
||||
{
|
||||
size_t size=0;
|
||||
|
||||
char *a=data;
|
||||
|
||||
while (*a != ' ' && *a != '\t' && *a != '\0')
|
||||
{
|
||||
a++;
|
||||
size++;
|
||||
}
|
||||
|
||||
if (size==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int set=0;
|
||||
for (int i=0; i< HAM_LAST_ENTRY_DONT_USE_ME_LOL; i++)
|
||||
{
|
||||
if (strncmp(data, hooklist[i].name, size)==0)
|
||||
{
|
||||
data+=size+1;
|
||||
|
||||
trim_line(data);
|
||||
int value=read_number(data);
|
||||
|
||||
hooklist[i].isset=1;
|
||||
hooklist[i].vtid=value;
|
||||
|
||||
|
||||
set=1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (set==0)
|
||||
{
|
||||
printf("stray key in process_key: %s\n", data);
|
||||
}
|
||||
|
||||
}
|
||||
int ReadConfig(void)
|
||||
{
|
||||
char FileName[512];
|
||||
ConfigManager = MF_GetConfigManager();
|
||||
|
||||
MF_BuildPathnameR(FileName,sizeof(FileName),"%s",get_localinfo("amxx_configsdir","addons/amxmodx/configs"));
|
||||
char error[256] = "";
|
||||
|
||||
strncat(FileName,"/hamdata.ini",sizeof(FileName)-1);
|
||||
|
||||
FILE *fp=fopen(FileName,"r");
|
||||
|
||||
|
||||
ke::SafeSprintf(CurrentModName, sizeof(CurrentModName), "%s", MF_GetModname());
|
||||
|
||||
if (!fp)
|
||||
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof error))
|
||||
{
|
||||
MF_Log("Unable to open \"%s\" for reading.", FileName);
|
||||
|
||||
MF_Log("common.games gamedata could not be read: %s", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char data[2048];
|
||||
TypeDescription value;
|
||||
|
||||
int insec=0;
|
||||
|
||||
while (!feof(fp))
|
||||
if (CommonConfig->GetOffset("pev", &value))
|
||||
{
|
||||
data[0]='\0';
|
||||
|
||||
fgets(data, sizeof(data)-1, fp);
|
||||
|
||||
char *b=&data[0];
|
||||
|
||||
switch(lex(b))
|
||||
{
|
||||
case LEX_PEV:
|
||||
{
|
||||
if (insec)
|
||||
{
|
||||
process_pev(b);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case LEX_BASE:
|
||||
{
|
||||
if (insec)
|
||||
{
|
||||
process_base(b);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case LEX_MIRROR:
|
||||
{
|
||||
read_mirror(b);
|
||||
break;
|
||||
};
|
||||
case LEX_START_SEC:
|
||||
{
|
||||
insec=read_start_section(b);
|
||||
|
||||
if (!insec)
|
||||
{
|
||||
skip_to_end_of_section(fp);
|
||||
}
|
||||
break;
|
||||
};
|
||||
case LEX_END_SEC:
|
||||
{
|
||||
insec=0;
|
||||
break;
|
||||
};
|
||||
case LEX_UNKNOWN:
|
||||
{
|
||||
if (insec)
|
||||
{
|
||||
process_key(b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Offsets.SetPev(value.fieldOffset);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
if (CommonConfig->GetOffset("base", &value))
|
||||
{
|
||||
Offsets.SetBase(value.fieldOffset);
|
||||
}
|
||||
|
||||
for (auto index = 0; index < HAM_LAST_ENTRY_DONT_USE_ME_LOL; ++index)
|
||||
{
|
||||
if (CommonConfig->GetOffset(hooklist[index].name, &value))
|
||||
{
|
||||
hooklist[index].isset = 1;
|
||||
hooklist[index].vtid = value.fieldOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ enum
|
||||
HAM_OK = 0,
|
||||
|
||||
HAM_INVALID_FUNC, // The function is not valid
|
||||
HAM_FUNC_NOT_CONFIGURED, // This function is not configured in hamdata.ini
|
||||
HAM_FUNC_NOT_CONFIGURED, // This function is not configured in gamedata
|
||||
HAM_FUNC_NOT_AVAILABLE, // This function is not more available in the mod
|
||||
|
||||
HAM_ERR_END
|
||||
|
@ -33,7 +33,7 @@ extern HLTypeConversion TypeConversion;
|
||||
return 0; \
|
||||
} else if (hooklist[x].isset == 0) { \
|
||||
char msg[1024]; \
|
||||
ke::SafeSprintf(msg, sizeof(msg), "Function %s is not configured in hamdata.ini.", hooklist[x].name); \
|
||||
ke::SafeSprintf(msg, sizeof(msg), "Function %s is not configured in gamedata.", hooklist[x].name); \
|
||||
FailPlugin(amx, x, HAM_FUNC_NOT_CONFIGURED, msg); \
|
||||
return 0; \
|
||||
}
|
||||
|
Reference in New Issue
Block a user