Program Listing for File script_globals.cpp¶
↰ Return to documentation for file (blam\components\haloscript\script_globals.cpp
)
#include "haloscript.h"
#include <regex>
#include <fstream>
#include "components/core/utils/converters/converters.h"
#include "components/core/utils/io/io.h"
#include "components/core/config/config.h"
#include "components/core/logger/logger.h"
#include "components/3rdparty/rapidxml/rapidxml.hpp"
using namespace BlamScript::Globals;
std::map<std::string, ScriptGlobal> globals;
std::map<std::string, ScriptGlobal>* BlamScript::Globals::GetGlobalsList()
{
return &globals;
}
bool BlamScript::Globals::GlobalExists(std::string id)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == id)
{
return true;
}
}
return false;
}
std::string BlamScript::Globals::GetGvarTypeLabel(GvarType type)
{
switch (type)
{
case GvarType::Boolean:
return "boolean";
case GvarType::Int:
return "int";
case GvarType::Short:
return "short";
case GvarType::Long:
return "long";
case GvarType::String:
return "string";
case GvarType::Object:
return "object";
case GvarType::Float:
return "float";
default:
return "unknown";
}
}
void BlamScript::Globals::RegisterGvar(ScriptGlobal var)
{
switch (var.type)
{
case GvarType::Boolean:
{
var.boolean_value = Blam::Converters::StringToBool(var.value_raw);
break;
}
case GvarType::Short:
{
bool contains_letter = std::regex_match(var.value_raw, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = bstoi(var.value_raw);
if (value > 32767 || value < -32768)
{
Blam::Logger::LogEvent("### ERROR tried to register short gvar " + var.name + " with invalid value " + var.value_raw, WSV_ERROR);
}
else
{
var.short_value = (short)value;
}
}
break;
}
case GvarType::Long:
{
bool contains_letter = std::regex_match(var.value_raw, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = bstoi(var.value_raw);
if (value > 2147483647/* || value < -2147483648*/)
{
Blam::Logger::LogEvent("### ERROR tried to register long gvar " + var.name + " with invalid value " + var.value_raw, WSV_ERROR);
}
else
{
var.long_value = (long)value;
}
}
break;
}
case GvarType::Int:
{
bool contains_letter = std::regex_match(var.value_raw, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = bstoi(var.value_raw);
if (value > 2147483647/* || value < -2147483648*/)
{
Blam::Logger::LogEvent("### ERROR tried to register int gvar " + var.name + " with invalid value " + var.value_raw, WSV_ERROR);
}
else
{
var.int_value = (int)value;
}
}
break;
}
case GvarType::Float:
{
bool contains_letter = std::regex_match(var.value_raw, std::regex("[^0-9]"));
if (!contains_letter)
{
float value = bstof(var.value_raw);
var.float_value = value;
}
break;
}
break;
}
globals.insert(std::pair<std::string, ScriptGlobal>(var.name, var));
}
void BlamScript::Globals::RegisterGvar(std::string name, std::string value_raw, GvarType type)
{
ScriptGlobal var;
var.name = name;
var.value_raw = value_raw;
var.type = type;
globals.insert(std::pair<std::string, ScriptGlobal>(name, var));
}
void BlamScript::Globals::RegisterGvar(std::string name, std::string value_raw, GvarType type, std::string info)
{
ScriptGlobal var;
var.name = name;
var.value_raw = value_raw;
var.type = type;
var.info = info;
globals.insert(std::pair<std::string, ScriptGlobal>(name, var));
}
ScriptGlobal* BlamScript::Globals::GetGlobal(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second;
}
}
return nullptr;
}
bool BlamScript::Globals::LoadGlobalsFromFile()
{
using namespace rapidxml;
std::string file_path = Blam::Config::GetConfig()->GetString("game_data_root") + GVARS_FILE;
if (Blam::Utils::IO::file_exists(file_path))
{
xml_document<> font_xml_file;
//read file into vector buffer
std::ifstream font_file(file_path);
std::vector<char> buffer((std::istreambuf_iterator<char>(font_file)), std::istreambuf_iterator<char>());
buffer.push_back('\0');
//load document
font_xml_file.parse<0>(&buffer[0]);
//get root node
xml_node<>* root_node = font_xml_file.first_node("globals");
for (xml_node<>* global_node = root_node->first_node("global"); global_node; global_node = global_node->next_sibling())
{
xml_attribute<char>* id_attribute = global_node->first_attribute("id");
xml_attribute<char>* type_attribute = global_node->first_attribute("type");
xml_attribute<char>* info_attribute = global_node->first_attribute("info");
xml_attribute<char>* protected_attribute = global_node->first_attribute("protected");
std::string value = global_node->value();
std::string id = "";
std::string info = "";
GvarType type;
bool _protected = false;
bool valid_global = true;
// get id attribute
if (id_attribute)
{
id = id_attribute->value();
}
else
{
Blam::Logger::LogEvent("### ERROR global variable '" + id + "' does not contain an id attribute, global will NOT be loaded!", WSV_ERROR);
valid_global = false;
}
// get type attribute
if (type_attribute)
{
if (Blam::Utils::String::to_lower(type_attribute->value()) == "string")
{
type = GvarType::String;
}
else if (Blam::Utils::String::to_lower(type_attribute->value()) == "short")
{
type = GvarType::Short;
}
else if (Blam::Utils::String::to_lower(type_attribute->value()) == "long")
{
type = GvarType::Long;
}
else if (Blam::Utils::String::to_lower(type_attribute->value()) == "boolean")
{
type = GvarType::Boolean;
}
else if (Blam::Utils::String::to_lower(type_attribute->value()) == "int")
{
type = GvarType::Int;
}
else if (Blam::Utils::String::to_lower(type_attribute->value()) == "float")
{
type = GvarType::Float;
}
else
{
Blam::Logger::LogEvent("### WARNING global variable '" + id + "' has invalid type '" + Blam::Utils::String::to_lower(type_attribute->value()) + "', setting to string. this may have unexpected consequences", WSV_WARNING);
type = GvarType::String;
}
}
else
{
Blam::Logger::LogEvent("### ERROR global variable '" + id + "' does not contain a type attribute, setting to string. this may have unexpected consequences", WSV_ERROR);
type = GvarType::String;
}
// get info attribute
if (info_attribute)
{
info = info_attribute->value();
}
else
{
Blam::Logger::LogEvent("global variable '" + id + "' does not contain an info attribute. consider providing one");
}
// get protected attribute
if (protected_attribute)
{
_protected = Blam::Converters::StringToBool(protected_attribute->value());
}
if (valid_global)
{
ScriptGlobal global;
global.name = id;
global.type = type;
global.value_raw = value;
global.read_only = _protected;
RegisterGvar(global);
}
}
Blam::Logger::LogEvent("successfully loaded " + std::to_string(globals.size()) + " global variables");
return true;
}
Blam::Logger::LogEvent("### ERROR failed to locate gvars.xml at path '" + file_path + "'", WSV_ERROR);
return false;
}
#pragma region global retrieval
bool* BlamScript::Globals::GetGlobalAsBoolean(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.boolean_value;
}
}
return nullptr;
}
std::string* BlamScript::Globals::GetGlobalAsString(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.value_raw;
}
}
//return "could not find global: '" + name + "'";
return nullptr;
}
short* BlamScript::Globals::GetGlobalAsShort(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.short_value;
}
}
return 0;
}
long* BlamScript::Globals::GetGlobalAsLong(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.long_value;
}
}
return 0;
}
int* BlamScript::Globals::GetGlobalAsInteger(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.int_value;
}
}
return 0;
}
float* BlamScript::Globals::GetGlobalAsFloat(std::string name)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->first == name)
{
return &i->second.float_value;
}
}
return 0;
}
#pragma endregion
#pragma region global updating
GvarUpdateResult BlamScript::Globals::UpdateGlobalWrap(std::string name, std::string new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (!i->second.read_only)
{
switch (i->second.type)
{
case GvarType::String:
{
i->second.value_raw = new_value;
return GvarUpdateResult::Ok;
}
case GvarType::Boolean:
{
std::string new_value_lower = Blam::Utils::String::to_lower(new_value);
if (new_value_lower == "true" || new_value_lower == "1" || new_value_lower == "t" || new_value_lower == "yes" || new_value_lower == "y")
{
i->second.boolean_value = true;
i->second.value_raw = "true";
return GvarUpdateResult::Ok;
}
else if (new_value_lower == "false" || new_value_lower == "0" || new_value_lower == "f" || new_value_lower == "no" || new_value_lower == "n")
{
i->second.boolean_value = false;
i->second.value_raw = "false";
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidArgs;
}
}
case GvarType::Short:
{
bool contains_letter = std::regex_match(new_value, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = stoi(new_value);
if (value > 32767 || value < -32768)
{
return GvarUpdateResult::OutOfBounds;
}
else
{
i->second.value_raw = new_value;
i->second.short_value = (short)value;
return GvarUpdateResult::Ok;
}
}
else
{
return GvarUpdateResult::InvalidArgs;
}
}
case GvarType::Long:
{
bool contains_letter = std::regex_match(new_value, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = stoi(new_value);
if (value > 2147483647 || value < -2147483648)
{
return GvarUpdateResult::OutOfBounds;
}
else
{
i->second.value_raw = new_value;
i->second.long_value = value;
return GvarUpdateResult::Ok;
}
}
else
{
return GvarUpdateResult::InvalidArgs;
}
}
case GvarType::Int:
{
bool contains_letter = std::regex_match(new_value, std::regex("[^0-9]"));
if (!contains_letter)
{
long value = stoi(new_value);
if (value > 2147483647 || value < -2147483648)
{
return GvarUpdateResult::OutOfBounds;
}
else
{
i->second.value_raw = new_value;
i->second.int_value = (int)value;
return GvarUpdateResult::Ok;
}
}
else
{
return GvarUpdateResult::InvalidArgs;
}
}
case GvarType::Float:
{
bool contains_letter = std::regex_match(new_value, std::regex("[^0-9]"));
if (!contains_letter)
{
float value = bstof(new_value);
i->second.value_raw = new_value;
i->second.float_value = value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidArgs;
}
}
default:
{
return GvarUpdateResult::InvalidType;
}
}
}
else
{
return GvarUpdateResult::GlobalIsProtected;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, std::string new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::String)
{
i->second.value_raw = new_value;
return GvarUpdateResult::Ok;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, bool new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::Boolean)
{
i->second.value_raw = std::to_string(new_value);
i->second.boolean_value = new_value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidType;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, short new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::Short)
{
i->second.value_raw = std::to_string(new_value);
i->second.short_value = new_value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidType;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, long new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::Long)
{
i->second.value_raw = std::to_string(new_value);
i->second.long_value = new_value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidType;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, int new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::Int)
{
i->second.value_raw = std::to_string(new_value);
i->second.int_value = new_value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidType;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
GvarUpdateResult BlamScript::Globals::UpdateGlobal(std::string name, float new_value)
{
for (std::map<std::string, ScriptGlobal>::iterator i = globals.begin(); i != globals.end(); i++)
{
if (i->second.name == name)
{
if (i->second.type == GvarType::Float)
{
i->second.value_raw = std::to_string(new_value);
i->second.float_value = new_value;
return GvarUpdateResult::Ok;
}
else
{
return GvarUpdateResult::InvalidType;
}
}
}
return GvarUpdateResult::UnknownGlobal;
}
#pragma endregion