shavit-credits/scripting/include/convar_class.inc

327 lines
8.8 KiB
SourcePawn

/*
MIT License
Copyright (c) 2019 KiD Fearless
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#if defined _convar_class_included
#endinput
#endif
#define _convar_class_included
// todo: track previous default values
static ArrayList _ConvarList;
enum struct convar_t
{
char name[255];
ConVar cvar;
char description[512];
char defValue[512];
bool GetMin(float& input)
{
return this.cvar.GetBounds(ConVarBound_Lower, input);
}
bool GetMax(float& input)
{
return this.cvar.GetBounds(ConVarBound_Upper, input);
}
void SetMin(bool set, float& input = 0.0)
{
this.cvar.SetBounds(ConVarBound_Lower, set, input);
}
void SetMax(bool set, float& input = 0.0)
{
this.cvar.SetBounds(ConVarBound_Upper, set, input);
}
}
methodmap Convar < ConVar
{
public Convar(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, convar_t convar = {})
{
if(_ConvarList == null)
{
_ConvarList = new ArrayList(sizeof(convar_t));
}
ConVar cvar = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max);
convar_t savedValue;
savedValue.cvar = cvar;
strcopy(savedValue.name, sizeof(savedValue.name), name);
strcopy(savedValue.description, 512, description);
strcopy(savedValue.defValue, sizeof(savedValue.defValue), defaultValue);
// Can't set default values :T
savedValue.SetMin(hasMin, min);
savedValue.SetMax(hasMax, max);
convar = savedValue;
_ConvarList.PushArray(savedValue);
return view_as<Convar>(cvar);
}
public static bool CreateConfig(const char[] fileName = "", const char[] folder = "sourcemod", const bool clearWhenDone = true)
{
char localFolder[PLATFORM_MAX_PATH];
FormatEx(localFolder, PLATFORM_MAX_PATH, "cfg/%s", folder);
if(!DirExists(localFolder))
{
if(!CreateDirectory(localFolder, 755))
{
LogError("Error: Failed to create folder '%s'", localFolder);
}
}
if(_ConvarList == null)
{
LogError("Error: No convars found. did you run .CreateConfig() before adding convars?");
return false;
}
_ConvarList.Sort(Sort_Ascending, Sort_String);
// Check if the file exists.
char local[PLATFORM_MAX_PATH];
if(fileName[0] == 0)
{
char pluginName[PLATFORM_MAX_PATH];
GetPluginFilename(GetMyHandle(), pluginName, PLATFORM_MAX_PATH);
ReplaceString(pluginName, PLATFORM_MAX_PATH, ".smx", "");
ReplaceString(pluginName, PLATFORM_MAX_PATH, "\\", "/");
int start = FindCharInString(pluginName, '/', true);
FormatEx(local, PLATFORM_MAX_PATH, "cfg/%s/plugin.%s.cfg", folder, pluginName[start+1]);
}
else
{
FormatEx(local, sizeof(local), "cfg/%s/%s.cfg", folder, fileName);
}
bool fileExists = FileExists(local);
if (!fileExists)
{
// Create first time file
File file = OpenFile(local, "wt");
if (file != null)
{
fileExists = true;
// get the plugin name
char pluginName[64];
GetPluginFilename(GetMyHandle(), pluginName, 64);
// Write warning
file.WriteLine("// This file was auto-generated by KiD's Convar Class. Only plugin convars are allowed.");
file.WriteLine("// ConVars for plugin \"%s\"\n\n", pluginName);
// Loop through all of our convars
for (int i = 0; i < _ConvarList.Length; ++i)
{
// get the current convar and description
convar_t convar;
_ConvarList.GetArray(i, convar);
// don't write to file if flag is set
if (convar.cvar.Flags & FCVAR_DONTRECORD != 0)
{
continue;
}
// format newlines as comments
ReplaceString(convar.description, 512, "\n", "\n// ");
// write the values and bounds to the file if they exist
file.WriteLine("// %s", convar.description);
file.WriteLine("// -");
file.WriteLine("// Default: \"%s\"", convar.defValue);
float x;
if (convar.GetMin(x))
{
file.WriteLine("// Minimum: \"%02f\"", x);
}
if (convar.GetMax(x))
{
file.WriteLine("// Maximum: \"%02f\"", x);
}
file.WriteLine("%s \"%s\"\n", convar.name, convar.defValue);
}
// end with newline
file.WriteLine("");
delete file;
}
else
{
// writing failed, notify developer.
char pluginName[64];
GetPluginFilename(GetMyHandle(), pluginName, 64);
LogError("Failed to auto generate config for %s at '%s', make sure the directory has write permission.", pluginName, local);
if(clearWhenDone)
{
delete _ConvarList;
}
return false;
}
}
// file already exists, just update the description and defaults
else
{
// open the file for reading
File file = OpenFile(local, "r");
// create a stringmap to hold our current convars.
StringMap convars = new StringMap();
char line[512];
int currentLine = 0;
while(!file.EndOfFile() && file.ReadLine(line, 512))
{
TrimString(line);
++currentLine;
// check if the line contains a valid statement
if(line[0] != '/' && line[0] != '\n' && line[0] != 0)
{
char buffers[2][512];
// only convars should be in here. which should contain convar [space] value.
if(ExplodeString(line, " ", buffers, 2, 512, true) == 2)
{
// remove any trailing whitespace. should be none
TrimString(buffers[0]);
TrimString(buffers[1]);
// remove the quotes from the values
StripQuotes(buffers[0]);
StripQuotes(buffers[1]);
// since convars are only ever strings we store it as strings.
convars.SetString(buffers[0], buffers[1]);
}
else
{
// someone put something in there that shouldn't be. Yell at the dev for doing stupid stuff.
LogError("Error exploding convar string: '%s' on line: %i", line, currentLine);
}
}
}
// close our file
delete file;
// yay duplicate code
// rewrite the cfg with old convars removed and new convars added.
/* Attempt to recreate it */
DeleteFile(local);
file = OpenFile(local, "wt");
if (file != null)
{
fileExists = true;
char pluginName[64];
GetPluginFilename(GetMyHandle(), pluginName, 64);
file.WriteLine("// This file was auto-generated by KiD's Convar Class. Only plugin convars are allowed.");
file.WriteLine("// ConVars for plugin \"%s\"\n\n", pluginName);
float x;
for (int i = 0; i < _ConvarList.Length; ++i)
{
convar_t convar;
_ConvarList.GetArray(i, convar);
if (convar.cvar.Flags & FCVAR_DONTRECORD != 0)
{
continue;
}
ReplaceString(convar.description, 512, "\n", "\n// ");
file.WriteLine("// %s", convar.description);
file.WriteLine("// -");
file.WriteLine("// Default: \"%s\"", convar.defValue);
if (convar.GetMin(x))
{
file.WriteLine("// Minimum: \"%02f\"", x);
}
if (convar.GetMax(x))
{
file.WriteLine("// Maximum: \"%02f\"", x);
}
// only difference is that now we check for a stored value.
char storedValue[512];
if(convars.GetString(convar.name, storedValue, 512))
{
file.WriteLine("%s \"%s\"\n", convar.name, storedValue);
}
else
{
file.WriteLine("%s \"%s\"\n", convar.name, convar.defValue);
}
}
file.WriteLine("");
delete file;
}
else
{
char pluginName[64];
GetPluginFilename(GetMyHandle(), pluginName, 64);
LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pluginName);
if(clearWhenDone)
{
delete _ConvarList;
}
delete convars;
return false;
}
delete convars;
}
if(fileExists)
{
ServerCommand("exec \"%s\"", local[4]);
}
if(clearWhenDone)
{
delete _ConvarList;
}
return true;
}
public static void AutoExecConfig(const char[] fileName = "", const char[] folder = "sourcemod", const bool clearWhenDone = true)
{
if(Convar.CreateConfig(fileName, folder, clearWhenDone))
{
AutoExecConfig(false, fileName, folder);
}
}
public void Close()
{
delete _ConvarList;
}
}