add mysql + update build

This commit is contained in:
alice
2025-08-11 17:52:46 +02:00
parent 589c5b5a48
commit 459ecf1695
28 changed files with 1242 additions and 171 deletions

View File

@@ -55,70 +55,21 @@ namespace scripting
}
}
array_value::array_value(unsigned int parent_id, unsigned int id)
: id_(id)
, parent_id_(parent_id)
array_value::array_value(const array* array, const script_value& key)
: array_(array)
, key_(key)
{
if (!this->id_)
{
return;
}
game::VariableValue variable_{};
if (game::environment::is_sp())
{
const auto variable = &game::scr_VarGlob->variableList_sp[this->id_ + 0x6000];
variable_.type = variable->w.type & 0x1F;
variable_.u = variable->u.u;
}
else
{
const auto variable = &game::scr_VarGlob->variableList_mp[this->id_ + 0x8000];
variable_.type = variable->w.type & 0x1F;
variable_.u = variable->u.u;
}
this->value_ = variable_;
const auto value = this->array_->get(key);
this->script_value::operator=(value);
}
void array_value::operator=(const script_value& value)
{
if (!this->id_)
{
return;
}
const auto& value_0 = value.get_raw();
game::VariableValue previous{};
if (game::environment::is_sp())
{
const auto variable = &game::scr_VarGlob->variableList_sp[this->id_ + 0x6000];
previous.type = variable->w.type & 0x1F;
previous.u = variable->u.u;
variable->w.type |= value_0.type;
variable->u.u = value_0.u;
}
else
{
const auto variable = &game::scr_VarGlob->variableList_mp[this->id_ + 0x8000];
previous.type = variable->w.type & 0x1F;
previous.u = variable->u.u;
variable->w.type |= value_0.type;
variable->u.u = value_0.u;
}
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_0);
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, previous.type, previous.u);
this->value_ = value_0;
this->array_->set(this->key_, value);
this->script_value::operator=(value);
}
array::array(const unsigned int id)
array::array(const std::uint32_t id)
: id_(id)
{
this->add();
@@ -198,18 +149,18 @@ namespace scripting
return SELECT_VALUE(get_keys_sp, get_keys_mp)(this->id_);
}
int array::size() const
std::uint32_t array::size() const
{
return static_cast<int>(game::Scr_GetSelf(game::SCRIPTINSTANCE_SERVER, this->id_));
}
unsigned int array::push(const script_value& value) const
std::uint32_t array::push_back(const script_value& value) const
{
this->set(this->size(), value);
return this->size();
}
void array::erase(const unsigned int index) const
void array::erase(const std::uint32_t index) const
{
const auto variable_id = game::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
if (variable_id)
@@ -228,13 +179,6 @@ namespace scripting
}
}
script_value array::pop() const
{
const auto value = this->get(this->size() - 1);
this->erase(this->size() - 1);
return value;
}
script_value array::get(const std::string& key) const
{
const auto string_value = game::SL_GetString(key.data(), 0, game::SCRIPTINSTANCE_SERVER);
@@ -263,6 +207,24 @@ namespace scripting
return variable_;
}
void array::erase(const script_value& key) const
{
if (key.is<int>())
{
return this->erase(key.as<int>());
}
if (key.is<std::string>())
{
return this->erase(key.as<std::string>());
}
}
void array::erase(const array_iterator& iter) const
{
this->erase(iter->first);
}
script_value array::get(const unsigned int index) const
{
const auto variable_id = game::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
@@ -294,15 +256,15 @@ namespace scripting
{
if (key.is<int>())
{
this->get(key.as<int>());
return this->get(key.as<int>());
}
if (key.is<std::string>())
{
this->get(key.as<std::string>());
return this->get(key.as<std::string>());
}
return {};
throw std::runtime_error(std::format("invalid key type '{}'", key.type_name()));
}
void array::set(const std::string& key, const script_value& value) const
@@ -340,7 +302,7 @@ namespace scripting
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, previous.type, previous.u);
}
void array::set(const unsigned int index, const script_value& value) const
void array::set(const std::uint32_t index, const script_value& value) const
{
const auto& value_ = value.get_raw();
const auto variable_id = this->get_value_id(index);
@@ -375,25 +337,27 @@ namespace scripting
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, previous.type, previous.u);
}
void array::set(const script_value& key, const script_value& _value) const
void array::set(const script_value& key, const script_value& value) const
{
if (key.is<int>())
{
this->set(key.as<int>(), _value);
return this->set(key.as<int>(), value);
}
if (key.is<std::string>())
{
this->set(key.as<std::string>(), _value);
return this->set(key.as<std::string>(), value);
}
throw std::runtime_error(std::format("invalid key type '{}'", key.type_name()));
}
unsigned int array::get_entity_id() const
std::uint32_t array::get_entity_id() const
{
return this->id_;
}
unsigned int array::get_value_id(const std::string& key) const
std::uint32_t array::get_value_id(const std::string& key) const
{
const auto string_value = game::SL_GetString(key.data(), 0, game::SCRIPTINSTANCE_SERVER);
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
@@ -406,7 +370,7 @@ namespace scripting
return variable_id;
}
unsigned int array::get_value_id(const unsigned int index) const
std::uint32_t array::get_value_id(const std::uint32_t index) const
{
const auto variable_id = game::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
if (!variable_id)
@@ -421,4 +385,34 @@ namespace scripting
{
return entity(this->id_);
}
array_value array::operator[](const script_value& key) const
{
return array_value(this, key);
}
array_iterator array::begin() const
{
const auto keys = this->get_keys();
return array_iterator(this, keys, 0);
}
array_iterator array::end() const
{
return array_iterator(this);
}
array_iterator array::find(const script_value& key) const
{
const auto keys = this->get_keys();
for (auto i = 0u; i < keys.size(); i++)
{
if (keys[i] == key)
{
return array_iterator(this, keys, i);
}
}
return array_iterator(this);
}
}

View File

@@ -1,23 +1,57 @@
#pragma once
#include "script_value.hpp"
#include "container_iterator.hpp"
namespace scripting
{
class array_value : public script_value
{
public:
array_value(unsigned int, unsigned int);
void operator=(const script_value&);
array_value(const array* array, const script_value& key);
void operator=(const script_value& value);
template <typename T>
T as() const
{
try
{
return script_value::as<T>();
}
catch (const std::exception& e)
{
throw std::runtime_error(std::format("array value '{}' {}", this->key_.to_string(), e.what()));
}
}
private:
unsigned int id_;
unsigned int parent_id_;
script_value key_;
const array* array_;
};
template <typename IteratorType>
class array_iterator_base : public IteratorType
{
public:
array_iterator_base(const array* container)
: IteratorType(container)
{
}
array_iterator_base(const array* container, const std::vector<script_value>& keys, const std::int64_t key_index)
: IteratorType(container, keys, key_index)
{
}
};
using array_iterator = array_iterator_base<container_iterator<array, script_value, array_value>>;
class array final
{
public:
array();
array(const unsigned int);
array(const std::uint32_t id);
array(const array& other);
array(array&& other) noexcept;
@@ -28,58 +62,46 @@ namespace scripting
array& operator=(array&& other) noexcept;
std::vector<script_value> get_keys() const;
int size() const;
std::uint32_t size() const;
unsigned int push(const script_value&) const;
void erase(const unsigned int) const;
void erase(const std::string&) const;
script_value pop() const;
std::uint32_t push_back(const script_value& value) const;
template <typename ...Args>
void emplace_back(Args&&... args)
{
this->push_back(std::forward<Args>(args)...);
}
void erase(const std::uint32_t index) const;
void erase(const std::string& key) const;
void erase(const script_value& key) const;
void erase(const array_iterator& iter) const;
script_value get(const script_value&) const;
script_value get(const std::string&) const;
script_value get(const unsigned int) const;
script_value get(const std::uint32_t) const;
void set(const script_value&, const script_value&) const;
void set(const std::string&, const script_value&) const;
void set(const unsigned int, const script_value&) const;
void set(const std::uint32_t, const script_value&) const;
unsigned int get_entity_id() const;
std::uint32_t get_entity_id() const;
unsigned int get_value_id(const std::string&) const;
unsigned int get_value_id(const unsigned int) const;
std::uint32_t get_value_id(const std::string&) const;
std::uint32_t get_value_id(const std::uint32_t) const;
entity get_raw() const;
array_value operator[](const int index) const
{
return {this->id_, this->get_value_id(index)};
}
array_value operator[](const script_value& key) const;
array_value operator[](const std::string& key) const
{
return {this->id_, this->get_value_id(key)};
}
template <typename I = int, typename S = std::string>
array_value operator[](const script_value& key) const
{
if (key.is<I>())
{
return {this->id_, this->get_value_id(key.as<I>())};
}
if (key.is<S>())
{
return {this->id_, this->get_value_id(key.as<S>())};
}
throw std::runtime_error("Invalid key type");
}
array_iterator begin() const;
array_iterator end() const;
array_iterator find(const script_value& key) const;
private:
void add() const;
void release() const;
unsigned int id_{};
std::uint32_t id_{};
};
}

View File

@@ -0,0 +1,99 @@
#pragma once
#include "script_value.hpp"
namespace scripting
{
template <typename ContainerType, typename KeyType, typename ValueType>
class container_iterator
{
public:
static constexpr std::int64_t container_iterator_end_key = -1;
container_iterator(const ContainerType* container)
: container_(container)
, key_index_(container_iterator_end_key)
{
}
container_iterator(const ContainerType* container, const std::vector<KeyType>& keys, const std::int64_t key_index)
: container_(container)
, keys_(keys)
, key_index_(key_index)
{
this->update_pair();
}
std::pair<KeyType, ValueType>& operator*()
{
return this->pair_.value();
}
std::pair<KeyType, ValueType>* operator->()
{
return &this->pair_.value();
}
const std::pair<KeyType, ValueType>& operator*() const
{
return this->pair_.value();
}
const std::pair<KeyType, ValueType>* operator->() const
{
return &this->pair_.value();
}
container_iterator& operator++()
{
if (this->key_index_ == container_iterator_end_key)
{
return *this;
}
const auto size = this->keys_.size();
if (this->key_index_ + 1 >= size)
{
this->key_index_ = container_iterator_end_key;
return *this;
}
this->key_index_++;
this->update_pair();
return *this;
}
container_iterator operator++(int)
{
const auto pre = *this;
this->operator++();
return pre;
}
friend bool operator==(const container_iterator& a, const container_iterator& b)
{
return a.container_ == b.container_ && a.key_index_ == b.key_index_;
};
friend bool operator!=(const container_iterator& a, const container_iterator& b)
{
return a.container_ != b.container_ || a.key_index_ != b.key_index_;
};
private:
void update_pair()
{
const auto index = static_cast<size_t>(this->key_index_);
const auto& key = this->keys_[index];
const auto value = this->container_->operator[](key);
this->pair_.emplace(std::make_pair(key, value));
}
const ContainerType* container_;
std::int64_t key_index_;
std::vector<KeyType> keys_;
std::optional<std::pair<KeyType, ValueType>> pair_;
};
}

View File

@@ -147,12 +147,30 @@ namespace scripting
return this->is<int>();
}
template <>
bool script_value::is<unsigned short>() const
{
return this->is<int>();
}
template <>
bool script_value::is<bool>() const
{
return this->is<int>();
}
template <>
bool script_value::is<short>() const
{
return this->is<int>();
}
template <>
bool script_value::is<char>() const
{
return this->is<int>();
}
template <>
int script_value::get() const
{
@@ -171,6 +189,24 @@ namespace scripting
return this->get_raw().u.uintValue != 0;
}
template <>
unsigned short script_value::get() const
{
return static_cast<unsigned short>(this->get_raw().u.uintValue);
}
template <>
short script_value::get() const
{
return static_cast<short>(this->get_raw().u.intValue);
}
template <>
char script_value::get() const
{
return static_cast<char>(this->get_raw().u.intValue);
}
/***********************************************
* Float
**********************************************/
@@ -178,7 +214,8 @@ namespace scripting
template <>
bool script_value::is<float>() const
{
return this->get_raw().type == game::SCRIPT_FLOAT;
const auto type = this->get_raw().type;
return type == game::SCRIPT_FLOAT || type == game::SCRIPT_INTEGER;
}
template <>
@@ -190,12 +227,24 @@ namespace scripting
template <>
float script_value::get() const
{
const auto type = this->get_raw().type;
if (type == game::SCRIPT_INTEGER)
{
return static_cast<float>(this->get_raw().u.intValue);
}
return this->get_raw().u.floatValue;
}
template <>
double script_value::get() const
{
const auto type = this->get_raw().type;
if (type == game::SCRIPT_INTEGER)
{
return static_cast<double>(this->get_raw().u.intValue);
}
return static_cast<double>(this->get_raw().u.floatValue);
}
@@ -320,6 +369,12 @@ namespace scripting
return this->get_raw().type == game::SCRIPT_VECTOR;
}
template <>
bool script_value::is<float*>() const
{
return this->is<vector>();
}
template <>
vector script_value::get() const
{
@@ -413,4 +468,24 @@ namespace scripting
return std::vector<function_argument>::operator[](index);
}
function_argument function_arguments::operator[](const size_t index) const
{
if (index >= values_.size())
{
return {values_, {}, index, false};
}
return {values_, values_[index], index, true};
}
arguments function_arguments::get_raw() const
{
return this->values_;
}
size_t function_arguments::size() const
{
return this->values_.size();
}
}

View File

@@ -137,9 +137,20 @@ namespace scripting
template <typename T>
T get() const
{
if (std::is_constructible<T, std::string>::value && this->is<std::string>()) \
if constexpr (std::is_pointer<T>::value)
{
return T(this->as<std::string>());
if (this->is<unsigned int>())
{
return reinterpret_cast<T>(this->as<unsigned int>());
}
}
if constexpr (std::is_constructible<T, std::string>::value)
{
if (this->is<std::string>())
{
return T(this->as<std::string>());
}
}
throw std::runtime_error("Invalid type");
@@ -157,7 +168,15 @@ public: \
template <typename T>
bool is() const
{
if (std::is_constructible<T, std::string>::value && this->is<std::string>()) \
if constexpr (std::is_pointer<T>::value)
{
if (this->is<unsigned int>())
{
return true;
}
}
if (std::is_constructible<T, std::string>::value && this->is<std::string>())
{
return true;
}
@@ -168,7 +187,9 @@ public: \
ADD_TYPE(bool)
ADD_TYPE(int)
ADD_TYPE(unsigned int)
ADD_TYPE(unsigned short)
ADD_TYPE(float)
ADD_TYPE(float*)
ADD_TYPE(double)
ADD_TYPE(const char*)
ADD_TYPE(std::string)
@@ -193,6 +214,17 @@ public: \
return get<T>();
}
template <typename T>
T as_or(const T& default_value) const
{
if (!this->is<T>())
{
return default_value;
}
return get<T>();
}
std::string type_name() const
{
return get_typename(this->get_raw());
@@ -205,7 +237,7 @@ public: \
for (const auto& value : container)
{
array_.push(value);
array_.emplace_back(value);
}
game::VariableValue value{};
@@ -223,6 +255,14 @@ public: \
std::string to_string() const;
friend bool operator==(const script_value& a, const script_value& b)
{
const auto& value_raw_a = a.get_raw();
const auto& value_raw_b = b.get_raw();
return value_raw_a.type != value_raw_b.type && value_raw_a.u.uintValue == value_raw_b.u.uintValue;
}
const game::VariableValue& get_raw() const;
variable_value value_{};
@@ -265,14 +305,29 @@ public: \
}
}
template <typename T, typename I = int>
T* as_ptr() const
{
const auto value = script_value::as<I>();
if (value == nullptr)
{
throw std::runtime_error("is null");
}
return reinterpret_cast<T*>(value);
}
template <>
variadic_args as() const
{
variadic_args args{this->index_};
for (auto i = this->index_; i < this->values_.size(); i++)
{
args.push_back({this->values_, this->values_[i], i, true});
args.emplace_back(this->values_, this->values_[i], i, true);
}
return args;
}
@@ -285,7 +340,7 @@ public: \
operator C<T, std::allocator<T>>() const
{
const auto container_type = get_c_typename<C<T, std::allocator<T>>>();
if (!script_value::as<ArrayType>())
if (!script_value::is<ArrayType>())
{
const auto type = get_typename(this->get_raw());
@@ -297,15 +352,15 @@ public: \
C<T, std::allocator<T>> container{};
const auto array = script_value::as<ArrayType>();
for (auto i = 0; i < array.size(); i++)
for (auto i = 0u; i < array.size(); i++)
{
try
{
container.push_back(array.get(i).as<T>());
container.emplace_back(array.get(i).as<T>());
}
catch (const std::exception& e)
{
throw std::runtime_error(utils::string::va("element %d of parameter %d of type '%s' %s",
throw std::runtime_error(utils::string::va("element %d of parameter %d of type '%s' %s",
i, this->index_, container_type.data(), e.what()));
}
}
@@ -323,6 +378,7 @@ public: \
arguments values_{};
size_t index_{};
bool exists_{};
};
class function_arguments
@@ -330,16 +386,14 @@ public: \
public:
function_arguments(const arguments& values);
function_argument operator[](const size_t index) const
{
if (index >= values_.size())
{
return {values_, {}, index, false};
}
function_argument operator[](const size_t index) const;
arguments get_raw() const;
size_t size() const;
return {values_, values_[index], index, true};
}
private:
arguments values_{};
};
}