877 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			877 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
#if defined _autoexecconfig_included
 | 
						|
	#endinput
 | 
						|
#endif
 | 
						|
#define _autoexecconfig_included
 | 
						|
 | 
						|
 | 
						|
#include <sourcemod>
 | 
						|
 | 
						|
 | 
						|
// Append
 | 
						|
#define AUTOEXEC_APPEND_BAD_FILENAME    0
 | 
						|
#define AUTOEXEC_APPEND_FILE_NOT_FOUND  1
 | 
						|
#define AUTOEXEC_APPEND_BAD_HANDLE      2
 | 
						|
#define AUTOEXEC_APPEND_SUCCESS         3
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Find
 | 
						|
#define AUTOEXEC_FIND_BAD_FILENAME     10
 | 
						|
#define AUTOEXEC_FIND_FILE_NOT_FOUND   11
 | 
						|
#define AUTOEXEC_FIND_BAD_HANDLE       12
 | 
						|
#define AUTOEXEC_FIND_NOT_FOUND        13
 | 
						|
#define AUTOEXEC_FIND_SUCCESS          14
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Clean
 | 
						|
#define AUTOEXEC_CLEAN_FILE_NOT_FOUND  20
 | 
						|
#define AUTOEXEC_CLEAN_BAD_HANDLE      21
 | 
						|
#define AUTOEXEC_CLEAN_SUCCESS         22
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// General
 | 
						|
#define AUTOEXEC_NO_CONFIG             30
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Formatter
 | 
						|
#define AUTOEXEC_FORMAT_BAD_FILENAME   40
 | 
						|
#define AUTOEXEC_FORMAT_SUCCESS        41
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Global variables
 | 
						|
static char g_sConfigFile[PLATFORM_MAX_PATH];
 | 
						|
static char g_sRawFileName[PLATFORM_MAX_PATH];
 | 
						|
static char g_sFolderPath[PLATFORM_MAX_PATH];
 | 
						|
 | 
						|
static StringMap g_hConvarTrie = null;
 | 
						|
static bool g_bCacheEnabled = false;
 | 
						|
 | 
						|
static bool g_bCreateFile = false;
 | 
						|
static Handle g_hPluginHandle = null;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Workaround for now
 | 
						|
static int g_iLastFindResult;
 | 
						|
static int g_iLastAppendResult;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns the last result from the parser.
 | 
						|
 *
 | 
						|
 * @return			Returns one of the AUTOEXEC_FIND values or -1 if not set.
 | 
						|
*/
 | 
						|
stock int AutoExecConfig_GetFindResult()
 | 
						|
{
 | 
						|
	return g_iLastFindResult;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns the last result from the appender.
 | 
						|
 *
 | 
						|
 * @return			Returns one of the AUTOEXEC_APPEND values or -1 if not set.
 | 
						|
*/
 | 
						|
stock int AutoExecConfig_GetAppendResult()
 | 
						|
{
 | 
						|
	return g_iLastAppendResult;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Set if the config file should be created if it doesn't exist yet.
 | 
						|
 *
 | 
						|
 * @param create 	True if config file should be created, false otherwise.
 | 
						|
 * @noreturn
 | 
						|
 */
 | 
						|
stock void AutoExecConfig_SetCreateFile(bool create)
 | 
						|
{
 | 
						|
	g_bCreateFile = create;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns if the config file should be created if it doesn't exist.
 | 
						|
 *
 | 
						|
 * @return			Returns true, if the config file should be created or false if it should not.
 | 
						|
 */
 | 
						|
stock bool AutoExecConfig_GetCreateFile()
 | 
						|
{
 | 
						|
	return g_bCreateFile;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Set the plugin for which the config file should be created.
 | 
						|
 * Set to null to use the calling plugin.
 | 
						|
 * Used to print the correct filename in the top comment when creating the file.
 | 
						|
 *
 | 
						|
 * @param plugin 	The plugin to create convars for or null to use the calling plugin.
 | 
						|
 * @noreturn
 | 
						|
 */
 | 
						|
stock void AutoExecConfig_SetPlugin(Handle plugin)
 | 
						|
{
 | 
						|
	g_hPluginHandle = plugin;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns the plugin for which the config file is created.
 | 
						|
 *
 | 
						|
 * @return			The plugin handle
 | 
						|
 */
 | 
						|
stock Handle AutoExecConfig_GetPlugin()
 | 
						|
{
 | 
						|
	return g_hPluginHandle;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Set the global autoconfigfile used by functions of this file.
 | 
						|
 *
 | 
						|
 * @param file			Name of the config file, path and .cfg extension is being added if not given.
 | 
						|
 * @param folder		Folder under cfg/ to use.  By default this is "sourcemod."
 | 
						|
 * @return				True if formatter returned success, false otherwise.
 | 
						|
*/
 | 
						|
stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod")
 | 
						|
{
 | 
						|
	Format(g_sConfigFile, sizeof(g_sConfigFile), "%s", file);
 | 
						|
	
 | 
						|
	// Global buffers for cfg execution
 | 
						|
	strcopy(g_sRawFileName, sizeof(g_sRawFileName), file);
 | 
						|
	strcopy(g_sFolderPath, sizeof(g_sFolderPath), folder);
 | 
						|
	
 | 
						|
	
 | 
						|
	// Format the filename
 | 
						|
	return AutoExecConfig_FormatFileName(g_sConfigFile, sizeof(g_sConfigFile), folder) == AUTOEXEC_FORMAT_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Get the formatted autoconfigfile used by functions of this file.
 | 
						|
 *
 | 
						|
 * @param buffer		String to format.
 | 
						|
 * @param size			Maximum size of buffer
 | 
						|
 * @return				True if filename was set, false otherwise.
 | 
						|
*/
 | 
						|
stock bool AutoExecConfig_GetFile(char[] buffer,int size)
 | 
						|
{
 | 
						|
	if (strlen(g_sConfigFile) > 0)
 | 
						|
	{
 | 
						|
		strcopy(buffer, size, g_sConfigFile);
 | 
						|
		
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Security for decl users
 | 
						|
	buffer[0] = '\0';
 | 
						|
	
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Creates a convar and appends it to the autoconfigfile if not found.
 | 
						|
 * FCVAR_DONTRECORD will be skipped.
 | 
						|
 *
 | 
						|
 * @param name			Name of new convar.
 | 
						|
 * @param defaultValue	String containing the default value of new convar.
 | 
						|
 * @param description	Optional description of the convar.
 | 
						|
 * @param flags			Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
 | 
						|
 * @param hasMin		Optional boolean that determines if the convar has a minimum value.
 | 
						|
 * @param min			Minimum floating point value that the convar can have if hasMin is true.
 | 
						|
 * @param hasMax		Optional boolean that determines if the convar has a maximum value.
 | 
						|
 * @param max			Maximum floating point value that the convar can have if hasMax is true.
 | 
						|
 * @return				A handle to the newly created convar. If the convar already exists, a handle to it will still be returned.
 | 
						|
 * @error				Convar name is blank or is the same as an existing console command.
 | 
						|
*/
 | 
						|
stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="", int flags=0, bool hasMin=false, float min=0.0, bool hasMax=false, float max=0.0)
 | 
						|
{
 | 
						|
	// If configfile was set and convar has no dontrecord flag
 | 
						|
	if (!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0)
 | 
						|
	{
 | 
						|
		// Reset the results
 | 
						|
		g_iLastFindResult = -1;
 | 
						|
		g_iLastAppendResult = -1;
 | 
						|
		
 | 
						|
		
 | 
						|
		// Add it if not found
 | 
						|
		char buffer[64];
 | 
						|
		
 | 
						|
		g_iLastFindResult = AutoExecConfig_FindValue(name, buffer, sizeof(buffer), true);
 | 
						|
		
 | 
						|
		// We only add this convar if it doesn't exist, or the file doesn't exist and it should be auto-generated
 | 
						|
		if (g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile))
 | 
						|
		{
 | 
						|
			g_iLastAppendResult = AutoExecConfig_AppendValue(name, defaultValue, description, flags, hasMin, min, hasMax, max);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	// Create the convar
 | 
						|
	return CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Executes the autoconfigfile, and adds it to the OnConfigsExecuted forward.
 | 
						|
 * If we didn't created it already we let SourceMod create it.
 | 
						|
 *
 | 
						|
 * @noreturn
 | 
						|
*/
 | 
						|
stock void AutoExecConfig_ExecuteFile()
 | 
						|
{
 | 
						|
	// Only let sourcemod create the file, if we didn't do that already. 
 | 
						|
	AutoExecConfig(!g_bCreateFile, g_sRawFileName, g_sFolderPath);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Formats a autoconfigfile, prefixes path and adds .cfg extension if missed.
 | 
						|
 *
 | 
						|
 * @param buffer		String to format.
 | 
						|
 * @param size			Maximum size of buffer.
 | 
						|
 * @return				Returns one of the AUTOEXEC_FORMAT values..
 | 
						|
*/
 | 
						|
stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] folder="sourcemod")
 | 
						|
{
 | 
						|
	// No config set
 | 
						|
	if (strlen(g_sConfigFile) < 1)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_NO_CONFIG;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	// Can't be an cfgfile
 | 
						|
	if (StrContains(g_sConfigFile, ".cfg") == -1 && strlen(g_sConfigFile) < 4)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_FORMAT_BAD_FILENAME;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	// Pathprefix
 | 
						|
	char pathprefixbuffer[PLATFORM_MAX_PATH];
 | 
						|
	if (strlen(folder) > 0)
 | 
						|
	{
 | 
						|
		Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/%s/", folder);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/");
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	char filebuffer[PLATFORM_MAX_PATH];
 | 
						|
	filebuffer[0] = '\0';
 | 
						|
	
 | 
						|
	// Add path if file doesn't begin with it
 | 
						|
	if (StrContains(buffer, pathprefixbuffer) != 0)
 | 
						|
	{
 | 
						|
		StrCat(filebuffer, sizeof(filebuffer), pathprefixbuffer);
 | 
						|
	}
 | 
						|
	
 | 
						|
	StrCat(filebuffer, sizeof(filebuffer), g_sConfigFile);
 | 
						|
	
 | 
						|
	
 | 
						|
	// Add .cfg extension if file doesn't end with it
 | 
						|
	if (StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0)
 | 
						|
	{
 | 
						|
		StrCat(filebuffer, sizeof(filebuffer), ".cfg");
 | 
						|
	}
 | 
						|
	
 | 
						|
	strcopy(buffer, size, filebuffer);
 | 
						|
	
 | 
						|
	return AUTOEXEC_FORMAT_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Appends a convar to the global autoconfigfile
 | 
						|
 *
 | 
						|
 * @param name			Name of new convar.
 | 
						|
 * @param defaultValue	String containing the default value of new convar.
 | 
						|
 * @param description	Optional description of the convar.
 | 
						|
 * @param flags			Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
 | 
						|
 * @param hasMin		Optional boolean that determines if the convar has a minimum value.
 | 
						|
 * @param min			Minimum floating point value that the convar can have if hasMin is true.
 | 
						|
 * @param hasMax		Optional boolean that determines if the convar has a maximum value.
 | 
						|
 * @param max			Maximum floating point value that the convar can have if hasMax is true.
 | 
						|
 * @return				Returns one of the AUTOEXEC_APPEND values
 | 
						|
*/
 | 
						|
stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValue, const char[] description, int flags, bool hasMin, float min, bool hasMax, float max)
 | 
						|
{
 | 
						|
	// No config set
 | 
						|
	if (strlen(g_sConfigFile) < 1)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_NO_CONFIG;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	char filebuffer[PLATFORM_MAX_PATH];
 | 
						|
	strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile);
 | 
						|
	
 | 
						|
	
 | 
						|
	//PrintToServer("pathbuffer: %s", filebuffer);
 | 
						|
	
 | 
						|
	bool bFileExists = FileExists(filebuffer);
 | 
						|
	
 | 
						|
	if (g_bCreateFile || bFileExists)
 | 
						|
	{
 | 
						|
		// If the file already exists we open it in append mode, otherwise we use a write mode which creates the file
 | 
						|
		File fFile = OpenFile(filebuffer, (bFileExists ? "a" : "w"));
 | 
						|
		char writebuffer[2048];
 | 
						|
		
 | 
						|
		
 | 
						|
		if (fFile == null)
 | 
						|
		{
 | 
						|
			return AUTOEXEC_APPEND_BAD_HANDLE;
 | 
						|
		}
 | 
						|
		
 | 
						|
		// We just created the file, so add some header about version and stuff
 | 
						|
		if (g_bCreateFile && !bFileExists)
 | 
						|
		{
 | 
						|
			fFile.WriteLine( "// This file was auto-generated by AutoExecConfig read and append beta");
 | 
						|
			
 | 
						|
			GetPluginFilename(g_hPluginHandle, writebuffer, sizeof(writebuffer));
 | 
						|
			Format(writebuffer, sizeof(writebuffer), "// ConVars for plugin \"%s\"", writebuffer);
 | 
						|
			fFile.WriteLine(writebuffer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		// Spacer
 | 
						|
		fFile.WriteLine("\n");
 | 
						|
		
 | 
						|
 | 
						|
		// This is used for multiline comments
 | 
						|
		int newlines = GetCharCountInStr('\n', description);
 | 
						|
		if (newlines == 0)
 | 
						|
		{
 | 
						|
			// We have no newlines, we can write the description to the file as is
 | 
						|
			Format(writebuffer, sizeof(writebuffer), "// %s", description);
 | 
						|
			fFile.WriteLine(writebuffer);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			char[][] newlineBuf = new char[newlines +1][2048];
 | 
						|
			ExplodeString(description, "\n", newlineBuf, newlines +1, 2048, false);
 | 
						|
			
 | 
						|
			// Each newline gets a commented newline
 | 
						|
			for (int i; i <= newlines; i++)
 | 
						|
			{
 | 
						|
				if (strlen(newlineBuf[i]) > 0)
 | 
						|
				{
 | 
						|
					fFile.WriteLine("// %s", newlineBuf[i]);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Descspacer
 | 
						|
		fFile.WriteLine("// -");
 | 
						|
		
 | 
						|
		
 | 
						|
		// Default
 | 
						|
		Format(writebuffer, sizeof(writebuffer), "// Default: \"%s\"", defaultValue);
 | 
						|
		fFile.WriteLine(writebuffer);
 | 
						|
		
 | 
						|
		
 | 
						|
		// Minimum
 | 
						|
		if (hasMin)
 | 
						|
		{		
 | 
						|
			Format(writebuffer, sizeof(writebuffer), "// Minimum: \"%f\"", min);
 | 
						|
			fFile.WriteLine(writebuffer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Maximum
 | 
						|
		if (hasMax)
 | 
						|
		{
 | 
						|
			Format(writebuffer, sizeof(writebuffer), "// Maximum: \"%f\"", max);
 | 
						|
			fFile.WriteLine(writebuffer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Write end and defaultvalue
 | 
						|
		Format(writebuffer, sizeof(writebuffer), "%s \"%s\"", name, defaultValue);
 | 
						|
		fFile.WriteLine(writebuffer);
 | 
						|
		
 | 
						|
		
 | 
						|
		fFile.Close();
 | 
						|
		
 | 
						|
		
 | 
						|
		// Clean up the file
 | 
						|
		//AutoExecConfig_CleanFile(filebuffer, false);
 | 
						|
		
 | 
						|
		
 | 
						|
		return AUTOEXEC_APPEND_SUCCESS;
 | 
						|
	}
 | 
						|
	
 | 
						|
	return AUTOEXEC_APPEND_FILE_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns a convars value from the global autoconfigfile
 | 
						|
 *
 | 
						|
 * @param cvar				Cvar to search for.
 | 
						|
 * @param value				Buffer to store result into.
 | 
						|
 * @param size				Maximum size of buffer.
 | 
						|
 * @param caseSensitive		Whether or not the search should be case sensitive.
 | 
						|
 * @return					Returns one of the AUTOEXEC_FIND values
 | 
						|
*/
 | 
						|
stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bool caseSensitive=false)
 | 
						|
{
 | 
						|
	// Security for decl users
 | 
						|
	value[0] = '\0';
 | 
						|
	
 | 
						|
	
 | 
						|
	// No config set
 | 
						|
	if (strlen(g_sConfigFile) < 1)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_NO_CONFIG;
 | 
						|
	}
 | 
						|
	
 | 
						|
	if (g_bCacheEnabled)
 | 
						|
	{
 | 
						|
		char sTrieValue[64];
 | 
						|
		
 | 
						|
		if (g_hConvarTrie.GetString(cvar, sTrieValue, sizeof(sTrieValue)))
 | 
						|
		{
 | 
						|
			strcopy(value, size, sTrieValue);
 | 
						|
			
 | 
						|
			return AUTOEXEC_FIND_SUCCESS;
 | 
						|
		}
 | 
						|
		
 | 
						|
		return AUTOEXEC_FIND_NOT_FOUND;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	char filebuffer[PLATFORM_MAX_PATH];
 | 
						|
	strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile);
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	//PrintToServer("pathbuffer: %s", filebuffer);
 | 
						|
	
 | 
						|
	bool bFileExists = FileExists(filebuffer);
 | 
						|
	
 | 
						|
	// We want to create the config file and it doesn't exist yet.
 | 
						|
	if (g_bCreateFile && !bFileExists)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_FIND_FILE_NOT_FOUND;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	if (bFileExists)
 | 
						|
	{
 | 
						|
		File fFile = OpenFile(filebuffer, "r");
 | 
						|
		int valuestart;
 | 
						|
		int valueend;
 | 
						|
		int cvarend;
 | 
						|
		
 | 
						|
		// Just an reminder to self, leave the values that high
 | 
						|
		char sConvar[64];
 | 
						|
		char sValue[64];
 | 
						|
		char readbuffer[2048];
 | 
						|
		char copybuffer[2048];
 | 
						|
		
 | 
						|
		if (fFile == null)
 | 
						|
		{
 | 
						|
			return AUTOEXEC_FIND_BAD_HANDLE;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		while (!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer)))
 | 
						|
		{
 | 
						|
			// Is a comment or not valid
 | 
						|
			if (IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || !IsCharAlpha(readbuffer[0]))
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			// Has not enough spaces, must have at least 1
 | 
						|
			if (GetCharCountInStr(' ', readbuffer) < 1)
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			
 | 
						|
			// Ignore cvars which aren't quoted
 | 
						|
			if (GetCharCountInStr('"', readbuffer) != 2)
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			
 | 
						|
			// Get the start of the value
 | 
						|
			if ( (valuestart = StrContains(readbuffer, "\"")) == -1 )
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			// Get the end of the value
 | 
						|
			if ( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 )
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			// Get the start of the cvar, 
 | 
						|
			if ( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart)
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			// Skip if cvarendindex is before valuestartindex
 | 
						|
			if (cvarend >= valuestart)
 | 
						|
			{
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			
 | 
						|
			
 | 
						|
			// Convar
 | 
						|
			// Tempcopy for security
 | 
						|
			strcopy(copybuffer, sizeof(copybuffer), readbuffer);
 | 
						|
			copybuffer[cvarend] = '\0';
 | 
						|
			
 | 
						|
			strcopy(sConvar, sizeof(sConvar), copybuffer);
 | 
						|
			
 | 
						|
 | 
						|
			// Value
 | 
						|
			// Tempcopy for security
 | 
						|
			strcopy(copybuffer, sizeof(copybuffer), readbuffer[valuestart+1]);
 | 
						|
			copybuffer[valueend] = '\0';
 | 
						|
			
 | 
						|
			strcopy(sValue, sizeof(sValue), copybuffer);
 | 
						|
			
 | 
						|
			
 | 
						|
			//PrintToServer("Cvar %s has a value of %s", sConvar, sValue);
 | 
						|
			
 | 
						|
			if (StrEqual(sConvar, cvar, caseSensitive))
 | 
						|
			{
 | 
						|
				Format(value, size, "%s", sConvar);
 | 
						|
				
 | 
						|
				fFile.Close();
 | 
						|
				return AUTOEXEC_FIND_SUCCESS;
 | 
						|
			}					
 | 
						|
		}
 | 
						|
		
 | 
						|
		fFile.Close();	
 | 
						|
		return AUTOEXEC_FIND_NOT_FOUND;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	return AUTOEXEC_FIND_FILE_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Cleans the global autoconfigfile from too much spaces
 | 
						|
 *
 | 
						|
 * @return					One of the AUTOEXEC_CLEAN values.
 | 
						|
*/
 | 
						|
stock int AutoExecConfig_CleanFile()
 | 
						|
{
 | 
						|
	// No config set
 | 
						|
	if (strlen(g_sConfigFile) < 1)
 | 
						|
	{
 | 
						|
		return AUTOEXEC_NO_CONFIG;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	char sfile[PLATFORM_MAX_PATH];
 | 
						|
	strcopy(sfile, sizeof(sfile), g_sConfigFile);
 | 
						|
	
 | 
						|
	
 | 
						|
	// Security
 | 
						|
	if (!FileExists(sfile))
 | 
						|
	{
 | 
						|
		return AUTOEXEC_CLEAN_FILE_NOT_FOUND;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	char sfile2[PLATFORM_MAX_PATH];
 | 
						|
	Format(sfile2, sizeof(sfile2), "%s_tempcopy", sfile);
 | 
						|
	
 | 
						|
	
 | 
						|
	char readbuffer[2048];
 | 
						|
	int count;
 | 
						|
	bool firstreached;
 | 
						|
	
 | 
						|
	
 | 
						|
	// Open files
 | 
						|
	File fFile1 = OpenFile(sfile, "r");
 | 
						|
	File fFile2 = OpenFile(sfile2, "w");
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	// Check filehandles
 | 
						|
	if (fFile1 == null || fFile2 == null)
 | 
						|
	{
 | 
						|
		if (fFile1 != null)
 | 
						|
		{
 | 
						|
			//PrintToServer("Handle1 invalid");
 | 
						|
			fFile1.Close();
 | 
						|
		}
 | 
						|
		
 | 
						|
		if (fFile2 != null)
 | 
						|
		{
 | 
						|
			//PrintToServer("Handle2 invalid");
 | 
						|
			fFile2.Close();
 | 
						|
		}
 | 
						|
		
 | 
						|
		return AUTOEXEC_CLEAN_BAD_HANDLE;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	while (!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer)))
 | 
						|
	{
 | 
						|
		// Is space
 | 
						|
		if (IsCharSpace(readbuffer[0]))
 | 
						|
		{
 | 
						|
			count++;
 | 
						|
		}
 | 
						|
		// No space, count from start
 | 
						|
		else
 | 
						|
		{
 | 
						|
			count = 0;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Don't write more than 1 space if seperation after informations have been reached
 | 
						|
		if (count < 2 || !firstreached)
 | 
						|
		{
 | 
						|
			ReplaceString(readbuffer, sizeof(readbuffer), "\n", "");
 | 
						|
			fFile2.WriteLine(readbuffer);
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// First bigger seperation after informations has been reached
 | 
						|
		if (count == 2)
 | 
						|
		{
 | 
						|
			firstreached = true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	fFile1.Close();
 | 
						|
	fFile2.Close();
 | 
						|
	
 | 
						|
	
 | 
						|
	// This might be a risk, for now it works
 | 
						|
	DeleteFile(sfile);
 | 
						|
	RenameFile(sfile, sfile2);
 | 
						|
	
 | 
						|
	return AUTOEXEC_CLEAN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns how many times the given char occures in the given string.
 | 
						|
 *
 | 
						|
 * @param str		String to search for in.
 | 
						|
 * @return			Occurences of the given char found in string.
 | 
						|
*/
 | 
						|
stock static int GetCharCountInStr(int character, const char[] str)
 | 
						|
{
 | 
						|
	int len = strlen(str);
 | 
						|
	int count;
 | 
						|
	
 | 
						|
	for (int i; i < len; i++)
 | 
						|
	{
 | 
						|
		if (str[i] == character)
 | 
						|
		{
 | 
						|
			count++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Reads the existing config file and caches any convars and values that were found.
 | 
						|
 *
 | 
						|
 * @param str		String to search for in.
 | 
						|
 * @return			True when config existed and could be read, false otherwise.
 | 
						|
*/
 | 
						|
stock bool AutoExecConfig_CacheConvars()
 | 
						|
{
 | 
						|
	if (g_hConvarTrie == null)
 | 
						|
	{
 | 
						|
		g_hConvarTrie = new StringMap();
 | 
						|
	}
 | 
						|
		
 | 
						|
	// No config set
 | 
						|
	if (strlen(g_sConfigFile) < 1)
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	char filebuffer[PLATFORM_MAX_PATH];
 | 
						|
	strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile);
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	//PrintToServer("pathbuffer: %s", filebuffer);
 | 
						|
	
 | 
						|
	bool bFileExists = FileExists(filebuffer);
 | 
						|
	
 | 
						|
	// We want to create the config file and it doesn't exist yet.
 | 
						|
	if (!bFileExists)
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	
 | 
						|
	File fFile = OpenFile(filebuffer, "r");
 | 
						|
	int valuestart;
 | 
						|
	int valueend;
 | 
						|
	int cvarend;
 | 
						|
	
 | 
						|
	// Just an reminder to self, leave the values that high
 | 
						|
	char sConvar[64];
 | 
						|
	char sValue[64];
 | 
						|
	char readbuffer[2048];
 | 
						|
	char copybuffer[2048];
 | 
						|
	
 | 
						|
	if (fFile == null)
 | 
						|
	{
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	while (!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer)))
 | 
						|
	{
 | 
						|
		// Is a comment or not valid
 | 
						|
		if (IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || !IsCharAlpha(readbuffer[0]))
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Has not enough spaces, must have at least 1
 | 
						|
		if (GetCharCountInStr(' ', readbuffer) < 1)
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		
 | 
						|
		// Ignore cvars which aren't quoted
 | 
						|
		if (GetCharCountInStr('"', readbuffer) != 2)
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		
 | 
						|
		// Get the start of the value
 | 
						|
		if ( (valuestart = StrContains(readbuffer, "\"")) == -1 )
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Get the end of the value
 | 
						|
		if ( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 )
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Get the start of the cvar, 
 | 
						|
		if ( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart)
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Skip if cvarendindex is before valuestartindex
 | 
						|
		if (cvarend >= valuestart)
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		// Convar
 | 
						|
		// Tempcopy for security
 | 
						|
		strcopy(copybuffer, sizeof(copybuffer), readbuffer);
 | 
						|
		copybuffer[cvarend] = '\0';
 | 
						|
		
 | 
						|
		strcopy(sConvar, sizeof(sConvar), copybuffer);
 | 
						|
		
 | 
						|
 | 
						|
		// Value
 | 
						|
		// Tempcopy for security
 | 
						|
		strcopy(copybuffer, sizeof(copybuffer), readbuffer[valuestart+1]);
 | 
						|
		copybuffer[valueend] = '\0';
 | 
						|
		
 | 
						|
		strcopy(sValue, sizeof(sValue), copybuffer);
 | 
						|
		
 | 
						|
		
 | 
						|
		//PrintToServer("Cvar %s has a value of %s", sConvar, sValue);
 | 
						|
		
 | 
						|
		char sTrieValue[64];
 | 
						|
		if (!g_hConvarTrie.GetString(sConvar, sTrieValue, sizeof(sTrieValue)))
 | 
						|
		{
 | 
						|
			//PrintToServer("Adding convar %s to trie", sConvar);
 | 
						|
			g_hConvarTrie.SetString(sConvar, sValue);
 | 
						|
		}					
 | 
						|
	}
 | 
						|
	
 | 
						|
	fFile.Close();	
 | 
						|
	
 | 
						|
	g_bCacheEnabled = true;
 | 
						|
	
 | 
						|
	return true;
 | 
						|
}
 |