h2-mod/src/game/scripting/lua/value_conversion.cpp

227 lines
4.4 KiB
C++
Raw Normal View History

2021-04-23 03:46:11 +02:00
#include <stdinc.hpp>
#include "value_conversion.hpp"
namespace scripting::lua
{
2021-04-23 14:33:01 +02:00
namespace
2021-04-23 03:46:11 +02:00
{
2021-04-23 19:11:43 +02:00
struct array_value
2021-04-23 03:46:11 +02:00
{
int index;
script_value value;
};
sol::lua_value entity_to_array(lua_State* state, unsigned int id)
{
auto table = sol::table::create(state);
auto metatable = sol::table::create(state);
std::unordered_map<std::string, array_value> values;
2021-04-23 19:11:43 +02:00
const auto offset = 40960 * (id & 3);
2021-04-23 03:46:11 +02:00
auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild;
auto idx = 1;
for (auto i = offset + current; current; i = offset + current)
{
const auto var = game::scr_VarGlob->childVariableValue[i];
if (var.type == game::SCRIPT_NONE)
{
current = var.nextSibling;
continue;
}
const auto string_value = (game::scr_string_t)((unsigned __int8)var.name_lo + (var.k.keys.name_hi << 8));
const auto* str = game::SL_ConvertToString(string_value);
std::string key = string_value < 0x40000 && str
? str
: std::to_string(idx++);
game::VariableValue variable{};
variable.type = var.type;
variable.u = var.u.u;
array_value value;
value.index = i;
value.value = variable;
values[key] = value;
current = var.nextSibling;
}
table["getkeys"] = [values]()
{
std::vector<std::string> _keys;
for (const auto& entry : values)
{
_keys.push_back(entry.first);
}
return _keys;
};
metatable[sol::meta_function::new_index] = [values](const sol::table t, const sol::this_state s,
const sol::lua_value& key_value, const sol::lua_value& value)
{
const auto key = key_value.is<int>()
? std::to_string(key_value.as<int>())
: key_value.as<std::string>();
if (values.find(key) == values.end())
{
return;
}
const auto variable = convert({s, value}).get_raw();
const auto i = values.at(key).index;
game::scr_VarGlob->childVariableValue[i].type = (char)variable.type;
game::scr_VarGlob->childVariableValue[i].u.u = variable.u;
};
metatable[sol::meta_function::index] = [values](const sol::table t, const sol::this_state s,
const sol::lua_value& key_value)
{
const auto key = key_value.is<int>()
? std::to_string(key_value.as<int>())
: key_value.as<std::string>();
if (values.find(key) == values.end())
{
2021-08-28 04:42:17 +02:00
return sol::lua_value{s, sol::lua_nil};
2021-04-23 03:46:11 +02:00
}
return convert(s, values.at(key).value);
};
metatable[sol::meta_function::length] = [values]()
{
return values.size();
};
table[sol::metatable_key] = metatable;
return {state, table};
2021-04-23 19:11:43 +02:00
}
2021-04-23 14:33:01 +02:00
bool is_istring(const sol::lua_value& value)
{
if (!value.is<std::string>())
{
return false;
}
const auto str = value.as<std::string>();
return str[0] == '&';
}
script_value string_to_istring(const sol::lua_value& value)
{
const auto str = value.as<std::string>().erase(0, 1);
const auto string_value = game::SL_GetString(str.data(), 0);
game::VariableValue variable{};
variable.type = game::SCRIPT_ISTRING;
variable.u.uintValue = string_value;
const auto _ = gsl::finally([&variable]()
{
game::RemoveRefToValue(variable.type, variable.u);
});
return script_value(variable);
2021-04-23 03:46:11 +02:00
}
2021-04-23 14:33:01 +02:00
}
2021-04-23 03:46:11 +02:00
script_value convert(const sol::lua_value& value)
{
if (value.is<int>())
{
return {value.as<int>()};
}
if (value.is<unsigned int>())
{
return {value.as<unsigned int>()};
}
if (value.is<bool>())
{
return {value.as<bool>()};
}
if (value.is<double>())
{
return {value.as<double>()};
}
if (value.is<float>())
{
return {value.as<float>()};
}
2021-04-23 14:33:01 +02:00
if (is_istring(value))
{
return string_to_istring(value);
}
2021-04-23 03:46:11 +02:00
if (value.is<std::string>())
{
return {value.as<std::string>()};
}
if (value.is<entity>())
{
return {value.as<entity>()};
}
if (value.is<vector>())
{
return {value.as<vector>()};
}
return {};
}
sol::lua_value convert(lua_State* state, const script_value& value)
{
if (value.is<int>())
{
return {state, value.as<int>()};
}
if (value.is<float>())
{
return {state, value.as<float>()};
}
if (value.is<std::string>())
{
return {state, value.as<std::string>()};
}
2021-04-23 19:11:43 +02:00
if (value.is<std::vector<script_value>>())
2021-04-23 03:46:11 +02:00
{
return entity_to_array(state, value.get_raw().u.uintValue);
2021-04-23 19:11:43 +02:00
}
2021-04-23 03:46:11 +02:00
if (value.is<entity>())
{
return {state, value.as<entity>()};
}
if (value.is<vector>())
{
return {state, value.as<vector>()};
}
2021-08-23 17:10:37 +02:00
return {state, sol::lua_nil};
2021-04-23 03:46:11 +02:00
}
}