diff --git a/src/game/scripting/context.cpp b/src/game/scripting/context.cpp index 4e2a27f..2f87e03 100644 --- a/src/game/scripting/context.cpp +++ b/src/game/scripting/context.cpp @@ -1,38 +1,35 @@ -#include "std_include.hpp" -#include "context_initializer.hpp" - -namespace game -{ - namespace scripting - { - context::context() : executer_(this), scheduler_(this), parameters_(this), event_handler_(this) - { - context_initializer::initialize(this); - } - - executer* context::get_executer() - { - return &this->executer_; - } - - scheduler* context::get_scheduler() - { - return &this->scheduler_; - } - - parameters* context::get_parameters() - { - return &this->parameters_; - } - - event_handler* context::get_event_handler() - { - return &this->event_handler_; - } - - chaiscript::ChaiScript* context::get_chai() - { - return &this->chai_; - } - } -} +#include "std_include.hpp" +#include "context_initializer.hpp" + +namespace game::scripting +{ + context::context() : executer_(this), scheduler_(this), parameters_(this), event_handler_(this) + { + context_initializer::initialize(this); + } + + executer* context::get_executer() + { + return &this->executer_; + } + + scheduler* context::get_scheduler() + { + return &this->scheduler_; + } + + parameters* context::get_parameters() + { + return &this->parameters_; + } + + event_handler* context::get_event_handler() + { + return &this->event_handler_; + } + + chaiscript::ChaiScript* context::get_chai() + { + return &this->chai_; + } +} diff --git a/src/game/scripting/context.hpp b/src/game/scripting/context.hpp index 56cd620..b2e8e5d 100644 --- a/src/game/scripting/context.hpp +++ b/src/game/scripting/context.hpp @@ -1,32 +1,29 @@ -#pragma once -#include "executer.hpp" -#include "scheduler.hpp" -#include "parameters.hpp" -#include "event_handler.hpp" - -namespace game -{ - namespace scripting - { - class context final - { - public: - context(); - - chaiscript::ChaiScript* get_chai(); - - executer* get_executer(); - scheduler* get_scheduler(); - parameters* get_parameters(); - event_handler* get_event_handler(); - - private: - chaiscript::ChaiScript chai_; - - executer executer_; - scheduler scheduler_; - parameters parameters_; - event_handler event_handler_; - }; - } -} +#pragma once +#include "executer.hpp" +#include "scheduler.hpp" +#include "parameters.hpp" +#include "event_handler.hpp" + +namespace game::scripting +{ + class context final + { + public: + context(); + + chaiscript::ChaiScript* get_chai(); + + executer* get_executer(); + scheduler* get_scheduler(); + parameters* get_parameters(); + event_handler* get_event_handler(); + + private: + chaiscript::ChaiScript chai_; + + executer executer_; + scheduler scheduler_; + parameters parameters_; + event_handler event_handler_; + }; +} diff --git a/src/game/scripting/context_initializer.cpp b/src/game/scripting/context_initializer.cpp index 88d5711..413a5e8 100644 --- a/src/game/scripting/context_initializer.cpp +++ b/src/game/scripting/context_initializer.cpp @@ -1,244 +1,238 @@ -#include "std_include.hpp" -#include "context_initializer.hpp" - -namespace game -{ - namespace scripting - { - namespace context_initializer - { - void initialize_entity(context* context) - { - const auto chai = context->get_chai(); - - chai->add(chaiscript::user_type(), "_entity"); - chai->add(chaiscript::constructor(), "_entity"); - chai->add(chaiscript::constructor(), "_entity"); - - chai->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity& - { - return lhs = rhs; - }), "="); - - chai->add(chaiscript::fun(&entity::get), "get"); - chai->add(chaiscript::fun(&entity::set), "set"); - - chai->add(chaiscript::fun(&entity::on_notify), "onNotify"); - chai->add(chaiscript::fun([](const entity& ent, const std::string& event, - const std::function)>& - callback) - { - return ent.on_notify(event, callback, false); - }), "onNotify"); - - chai->add(chaiscript::fun([context](const std::string& event, - const std::function)>& - callback) - { - generic_event_listener listener; - listener.event = event; - listener.is_volatile = false; - listener.callback = callback; - - return context->get_event_handler()->add_event_listener(listener); - }), "onNotify"); - - chai->add(chaiscript::fun([context](const std::string& event, - const std::function)>& - callback, const bool is_volatile) - { - generic_event_listener listener; - listener.event = event; - listener.is_volatile = is_volatile; - listener.callback = callback; - - return context->get_event_handler()->add_event_listener(listener); - }), "onNotify"); - - // Notification - chai->add(chaiscript::fun(&entity::notify), "vectorNotify"); - chai->add(chaiscript::fun([](const entity& ent, const std::string& event) - { - return ent.notify(event, {}); - }), "notify"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& event, - const chaiscript::Boxed_Value& a1) - { - return ent.notify(event, {a1}); - }), "notify"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& event, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2) - { - return ent.notify(event, {a1, a2}); - }), "notify"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& event, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3) - { - return ent.notify(event, {a1, a2, a3}); - }), "notify"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& event, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4) - { - return ent.notify(event, {a1, a2, a3, a4}); - }), "notify"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& event, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4, - const chaiscript::Boxed_Value& a5) - { - return ent.notify(event, {a1, a2, a3, a4, a5}); - }), "notify"); - - // Instance call - chai->add(chaiscript::fun(&entity::call), "vectorCall"); - chai->add(chaiscript::fun([](const entity& ent, const std::string& function) - { - return ent.call(function, {}); - }), "call"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& function, - const chaiscript::Boxed_Value& a1) - { - return ent.call(function, {a1}); - }), "call"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2) - { - return ent.call(function, {a1, a2}); - }), "call"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3) - { - return ent.call(function, {a1, a2, a3}); - }), "call"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4) - { - return ent.call(function, {a1, a2, a3, a4}); - }), "call"); - - chai->add(chaiscript::fun( - [](const entity& ent, const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4, - const chaiscript::Boxed_Value& a5) - { - return ent.call(function, {a1, a2, a3, a4, a5}); - }), "call"); - - // Global call - chai->add(chaiscript::fun( - [context](const std::string& function, - const std::vector& arguments) - { - return context->get_executer()->call(function, 0, arguments); - }), "vectorCall"); - chai->add(chaiscript::fun([context](const std::string& function) - { - return context->get_executer()->call(function, 0, {}); - }), "call"); - - chai->add(chaiscript::fun( - [context](const std::string& function, - const chaiscript::Boxed_Value& a1) - { - return context->get_executer()->call(function, 0, {a1}); - }), "call"); - - chai->add(chaiscript::fun( - [context](const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2) - { - return context->get_executer()->call(function, 0, {a1, a2}); - }), "call"); - - chai->add(chaiscript::fun( - [context](const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3) - { - return context->get_executer()->call(function, 0, {a1, a2, a3}); - }), "call"); - - chai->add(chaiscript::fun( - [context](const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4) - { - return context->get_executer()->call(function, 0, {a1, a2, a3, a4}); - }), "call"); - - chai->add(chaiscript::fun( - [context](const std::string& function, - const chaiscript::Boxed_Value& a1, - const chaiscript::Boxed_Value& a2, - const chaiscript::Boxed_Value& a3, - const chaiscript::Boxed_Value& a4, - const chaiscript::Boxed_Value& a5) - { - return context->get_executer()->call(function, 0, {a1, a2, a3, a4, a5}); - }), "call"); - } - - void initialize(context* context) - { - initialize_entity(context); - - const auto chai = context->get_chai(); - - chai->add(chaiscript::fun([](const std::string& string) - { - printf("%s\n", string.data()); - }), "print"); - - chai->add(chaiscript::fun([](const std::string& string) - { - MessageBoxA(nullptr, string.data(), nullptr, 0); - }), "alert"); - - const auto level_id = *native::levelEntityId; - chai->add_global(chaiscript::var(entity(context, level_id)), "level"); - } - } - } -} +#include "std_include.hpp" +#include "context_initializer.hpp" + +namespace game::scripting::context_initializer +{ + void initialize_entity(context* context) + { + const auto chai = context->get_chai(); + + chai->add(chaiscript::user_type(), "_entity"); + chai->add(chaiscript::constructor(), "_entity"); + chai->add(chaiscript::constructor(), "_entity"); + + chai->add(chaiscript::fun([](entity& lhs, const entity& rhs) -> entity& + { + return lhs = rhs; + }), "="); + + chai->add(chaiscript::fun(&entity::get), "get"); + chai->add(chaiscript::fun(&entity::set), "set"); + + chai->add(chaiscript::fun(&entity::on_notify), "onNotify"); + chai->add(chaiscript::fun([](const entity& ent, const std::string& event, + const std::function)>& + callback) + { + return ent.on_notify(event, callback, false); + }), "onNotify"); + + chai->add(chaiscript::fun([context](const std::string& event, + const std::function)>& + callback) + { + generic_event_listener listener; + listener.event = event; + listener.is_volatile = false; + listener.callback = callback; + + return context->get_event_handler()->add_event_listener(listener); + }), "onNotify"); + + chai->add(chaiscript::fun([context](const std::string& event, + const std::function)>& + callback, const bool is_volatile) + { + generic_event_listener listener; + listener.event = event; + listener.is_volatile = is_volatile; + listener.callback = callback; + + return context->get_event_handler()->add_event_listener(listener); + }), "onNotify"); + + // Notification + chai->add(chaiscript::fun(&entity::notify), "vectorNotify"); + chai->add(chaiscript::fun([](const entity& ent, const std::string& event) + { + return ent.notify(event, {}); + }), "notify"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& event, + const chaiscript::Boxed_Value& a1) + { + return ent.notify(event, {a1}); + }), "notify"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& event, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2) + { + return ent.notify(event, {a1, a2}); + }), "notify"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& event, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3) + { + return ent.notify(event, {a1, a2, a3}); + }), "notify"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& event, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4) + { + return ent.notify(event, {a1, a2, a3, a4}); + }), "notify"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& event, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4, + const chaiscript::Boxed_Value& a5) + { + return ent.notify(event, {a1, a2, a3, a4, a5}); + }), "notify"); + + // Instance call + chai->add(chaiscript::fun(&entity::call), "vectorCall"); + chai->add(chaiscript::fun([](const entity& ent, const std::string& function) + { + return ent.call(function, {}); + }), "call"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& function, + const chaiscript::Boxed_Value& a1) + { + return ent.call(function, {a1}); + }), "call"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2) + { + return ent.call(function, {a1, a2}); + }), "call"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3) + { + return ent.call(function, {a1, a2, a3}); + }), "call"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4) + { + return ent.call(function, {a1, a2, a3, a4}); + }), "call"); + + chai->add(chaiscript::fun( + [](const entity& ent, const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4, + const chaiscript::Boxed_Value& a5) + { + return ent.call(function, {a1, a2, a3, a4, a5}); + }), "call"); + + // Global call + chai->add(chaiscript::fun( + [context](const std::string& function, + const std::vector& arguments) + { + return context->get_executer()->call(function, 0, arguments); + }), "vectorCall"); + chai->add(chaiscript::fun([context](const std::string& function) + { + return context->get_executer()->call(function, 0, {}); + }), "call"); + + chai->add(chaiscript::fun( + [context](const std::string& function, + const chaiscript::Boxed_Value& a1) + { + return context->get_executer()->call(function, 0, {a1}); + }), "call"); + + chai->add(chaiscript::fun( + [context](const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2) + { + return context->get_executer()->call(function, 0, {a1, a2}); + }), "call"); + + chai->add(chaiscript::fun( + [context](const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3) + { + return context->get_executer()->call(function, 0, {a1, a2, a3}); + }), "call"); + + chai->add(chaiscript::fun( + [context](const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4) + { + return context->get_executer()->call(function, 0, {a1, a2, a3, a4}); + }), "call"); + + chai->add(chaiscript::fun( + [context](const std::string& function, + const chaiscript::Boxed_Value& a1, + const chaiscript::Boxed_Value& a2, + const chaiscript::Boxed_Value& a3, + const chaiscript::Boxed_Value& a4, + const chaiscript::Boxed_Value& a5) + { + return context->get_executer()->call(function, 0, {a1, a2, a3, a4, a5}); + }), "call"); + } + + void initialize(context* context) + { + initialize_entity(context); + + const auto chai = context->get_chai(); + + chai->add(chaiscript::fun([](const std::string& string) + { + printf("%s\n", string.data()); + }), "print"); + + chai->add(chaiscript::fun([](const std::string& string) + { + MessageBoxA(nullptr, string.data(), nullptr, 0); + }), "alert"); + + const auto level_id = *native::levelEntityId; + chai->add_global(chaiscript::var(entity(context, level_id)), "level"); + } +} diff --git a/src/game/scripting/context_initializer.hpp b/src/game/scripting/context_initializer.hpp index 416c9d8..8075246 100644 --- a/src/game/scripting/context_initializer.hpp +++ b/src/game/scripting/context_initializer.hpp @@ -1,13 +1,7 @@ -#pragma once -#include "context.hpp" - -namespace game -{ - namespace scripting - { - namespace context_initializer - { - void initialize(context* context); - } - } -} +#pragma once +#include "context.hpp" + +namespace game::scripting::context_initializer +{ + void initialize(context* context); +} diff --git a/src/game/scripting/entity.cpp b/src/game/scripting/entity.cpp index 17e65f7..2cdc52f 100644 --- a/src/game/scripting/entity.cpp +++ b/src/game/scripting/entity.cpp @@ -1,21 +1,57 @@ #include "std_include.hpp" #include "context.hpp" -namespace game +namespace game::scripting { - namespace scripting + entity::entity() : entity(nullptr, 0) { - entity::entity() : entity(nullptr, 0) + } + + entity::entity(const entity& other) : entity(other.context_, other.entity_id_) + { + } + + entity::entity(entity&& other) noexcept + { + if (&other == this) return; + + this->context_ = other.context_; + this->entity_id_ = other.entity_id_; + + other.context_ = nullptr; + other.entity_id_ = 0; + } + + entity::entity(context* context, const unsigned int entity_id) : context_(context), entity_id_(entity_id) + { + this->add(); + } + + entity::~entity() + { + this->release(); + } + + entity& entity::operator=(const entity& other) + { + if (&other != this) { + this->release(); + + this->context_ = other.context_; + this->entity_id_ = other.entity_id_; + + this->add(); } - entity::entity(const entity& other) : entity(other.context_, other.entity_id_) - { - } + return *this; + } - entity::entity(entity&& other) noexcept + entity& entity::operator=(entity&& other) noexcept + { + if (&other != this) { - if (&other == this) return; + this->release(); this->context_ = other.context_; this->entity_id_ = other.entity_id_; @@ -24,111 +60,72 @@ namespace game other.entity_id_ = 0; } - entity::entity(context* context, const unsigned int entity_id) : context_(context), entity_id_(entity_id) + return *this; + } + + event_listener_handle entity::on_notify(const std::string& event, + const std::function)>& + callback, + const bool is_volatile) + const + { + event_listener listener; + listener.event = event; + listener.callback = callback; + listener.entity_id = this->entity_id_; + listener.is_volatile = is_volatile; + + return this->context_->get_event_handler()->add_event_listener(listener); + } + + unsigned int entity::get_entity_id() const + { + return this->entity_id_; + } + + native::scr_entref_t entity::get_entity_reference() const + { + return game::native::Scr_GetEntityIdRef(this->get_entity_id()); + } + + chaiscript::Boxed_Value entity::call(const std::string& function, + const std::vector& arguments) const + { + return this->context_->get_executer()->call(function, this->get_entity_id(), arguments); + } + + void entity::notify(const std::string& event, + const std::vector& arguments) const + { + this->context_->get_executer()->notify(event, this->get_entity_id(), arguments); + } + + void entity::set(const std::string& field, const chaiscript::Boxed_Value& value) const + { + this->context_->get_executer()->set_entity_field(field, this->get_entity_id(), value); + } + + chaiscript::Boxed_Value entity::get(const std::string& field) const + { + return this->context_->get_executer()->get_entity_field(field, this->get_entity_id()); + } + + void entity::add() const + { + if (this->entity_id_) { - this->add(); + native::VariableValue value; + value.type = native::SCRIPT_OBJECT; + value.u.entityId = this->entity_id_; + native::AddRefToValue(&value); } + } - entity::~entity() + void entity::release() const + { + if (this->entity_id_) { - this->release(); - } - - entity& entity::operator=(const entity& other) - { - if (&other != this) - { - this->release(); - - this->context_ = other.context_; - this->entity_id_ = other.entity_id_; - - this->add(); - } - - return *this; - } - - entity& entity::operator=(entity&& other) noexcept - { - if (&other != this) - { - this->release(); - - this->context_ = other.context_; - this->entity_id_ = other.entity_id_; - - other.context_ = nullptr; - other.entity_id_ = 0; - } - - return *this; - } - - event_listener_handle entity::on_notify(const std::string& event, - const std::function)>& - callback, - const bool is_volatile) - const - { - event_listener listener; - listener.event = event; - listener.callback = callback; - listener.entity_id = this->entity_id_; - listener.is_volatile = is_volatile; - - return this->context_->get_event_handler()->add_event_listener(listener); - } - - unsigned int entity::get_entity_id() const - { - return this->entity_id_; - } - - native::scr_entref_t entity::get_entity_reference() const - { - return game::native::Scr_GetEntityIdRef(this->get_entity_id()); - } - - chaiscript::Boxed_Value entity::call(const std::string& function, - const std::vector& arguments) const - { - return this->context_->get_executer()->call(function, this->get_entity_id(), arguments); - } - - void entity::notify(const std::string& event, - const std::vector& arguments) const - { - this->context_->get_executer()->notify(event, this->get_entity_id(), arguments); - } - - void entity::set(const std::string& field, const chaiscript::Boxed_Value& value) const - { - this->context_->get_executer()->set_entity_field(field, this->get_entity_id(), value); - } - - chaiscript::Boxed_Value entity::get(const std::string& field) const - { - return this->context_->get_executer()->get_entity_field(field, this->get_entity_id()); - } - - void entity::add() const - { - if (this->entity_id_) - { - native::VariableValue value; - value.type = native::SCRIPT_OBJECT; - value.u.entityId = this->entity_id_; - native::AddRefToValue(&value); - } - } - - void entity::release() const - { - if (this->entity_id_) - { - native::RemoveRefToValue(native::SCRIPT_OBJECT, {static_cast(this->entity_id_)}); - } + native::RemoveRefToValue(native::SCRIPT_OBJECT, {static_cast(this->entity_id_)}); } } } diff --git a/src/game/scripting/entity.hpp b/src/game/scripting/entity.hpp index ced3201..2e90e5e 100644 --- a/src/game/scripting/entity.hpp +++ b/src/game/scripting/entity.hpp @@ -1,45 +1,42 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - class context; - class event_listener_handle; - - class entity final - { - public: - entity(); - entity(const entity& other); - entity(entity&& other) noexcept; - entity(context* context, unsigned int entity_id); - ~entity(); - - entity& operator=(const entity& other); - entity& operator=(entity&& other) noexcept; - - event_listener_handle on_notify(const std::string& event, - const std::function)>& callback, - bool is_volatile) const; - - unsigned int get_entity_id() const; - game::native::scr_entref_t get_entity_reference() const; - - chaiscript::Boxed_Value call(const std::string& function, - const std::vector& arguments) const; - void notify(const std::string& event, const std::vector& arguments) const; - - void set(const std::string& field, const chaiscript::Boxed_Value& value) const; - chaiscript::Boxed_Value get(const std::string& field) const; - - private: - context* context_; - unsigned int entity_id_; - - void add() const; - void release() const; - }; - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting +{ + class context; + class event_listener_handle; + + class entity final + { + public: + entity(); + entity(const entity& other); + entity(entity&& other) noexcept; + entity(context* context, unsigned int entity_id); + ~entity(); + + entity& operator=(const entity& other); + entity& operator=(entity&& other) noexcept; + + event_listener_handle on_notify(const std::string& event, + const std::function)>& callback, + bool is_volatile) const; + + unsigned int get_entity_id() const; + game::native::scr_entref_t get_entity_reference() const; + + chaiscript::Boxed_Value call(const std::string& function, + const std::vector& arguments) const; + void notify(const std::string& event, const std::vector& arguments) const; + + void set(const std::string& field, const chaiscript::Boxed_Value& value) const; + chaiscript::Boxed_Value get(const std::string& field) const; + + private: + context* context_; + unsigned int entity_id_; + + void add() const; + void release() const; + }; +} diff --git a/src/game/scripting/event.hpp b/src/game/scripting/event.hpp index 7b2160f..da918cd 100644 --- a/src/game/scripting/event.hpp +++ b/src/game/scripting/event.hpp @@ -1,16 +1,13 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - class event final - { - public: - std::string name; - unsigned int entity_id; - std::vector arguments; - }; - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting +{ + class event final + { + public: + std::string name; + unsigned int entity_id; + std::vector arguments; + }; +} diff --git a/src/game/scripting/event_handler.cpp b/src/game/scripting/event_handler.cpp index e9e09b8..4c97895 100644 --- a/src/game/scripting/event_handler.cpp +++ b/src/game/scripting/event_handler.cpp @@ -1,123 +1,120 @@ #include "std_include.hpp" #include "context.hpp" -namespace game +namespace game::scripting { - namespace scripting + event_handler::event_handler(context* context) : context_(context) { - event_handler::event_handler(context* context) : context_(context) + const auto chai = this->context_->get_chai(); + + chai->add(chaiscript::user_type(), "_event_listener_handle"); + chai->add(chaiscript::constructor(), "_event_listener_handle"); + chai->add(chaiscript::constructor(), + "_event_listener_handle"); + + chai->add(chaiscript::fun( + [](event_listener_handle& lhs, const event_listener_handle& rhs) -> event_listener_handle& + { + return lhs = rhs; + }), "="); + + chai->add(chaiscript::fun([this](const event_listener_handle& handle) { - const auto chai = this->context_->get_chai(); + this->remove(handle); + }), "clear"); + } - chai->add(chaiscript::user_type(), "_event_listener_handle"); - chai->add(chaiscript::constructor(), "_event_listener_handle"); - chai->add(chaiscript::constructor(), - "_event_listener_handle"); + void event_handler::dispatch(event* event) + { + try + { + std::vector arguments; - chai->add(chaiscript::fun( - [](event_listener_handle& lhs, const event_listener_handle& rhs) -> event_listener_handle& - { - return lhs = rhs; - }), "="); - - chai->add(chaiscript::fun([this](const event_listener_handle& handle) + for (auto argument : event->arguments) { - this->remove(handle); - }), "clear"); + arguments.push_back(this->context_->get_parameters()->load(argument)); + } + + this->dispatch_to_specific_listeners(event, arguments); + this->dispatch_to_generic_listeners(event, arguments); } - - void event_handler::dispatch(event* event) + catch (chaiscript::exception::eval_error& e) { - try - { - std::vector arguments; + throw std::runtime_error(e.pretty_print()); + } + } - for (auto argument : event->arguments) + void event_handler::dispatch_to_specific_listeners(event* event, + const std::vector& arguments) + { + for (auto listener : this->event_listeners_) + { + if (listener->event == event->name && listener->entity_id == event->entity_id) + { + if (listener->is_volatile) { - arguments.push_back(this->context_->get_parameters()->load(argument)); + this->event_listeners_.remove(listener); } - this->dispatch_to_specific_listeners(event, arguments); - this->dispatch_to_generic_listeners(event, arguments); + listener->callback(arguments); } - catch (chaiscript::exception::eval_error& e) + } + } + + void event_handler::dispatch_to_generic_listeners(event* event, + const std::vector& arguments) + { + for (auto listener : this->generic_event_listeners_) + { + if (listener->event == event->name) { - throw std::runtime_error(e.pretty_print()); + if (listener->is_volatile) + { + this->generic_event_listeners_.remove(listener); + } + + listener->callback(entity(this->context_, event->entity_id), arguments); + } + } + } + + event_listener_handle event_handler::add_event_listener(event_listener listener) + { + listener.id = ++this->current_listener_id_; + this->event_listeners_.add(listener); + return {listener.id}; + } + + event_listener_handle event_handler::add_event_listener(generic_event_listener listener) + { + listener.id = ++this->current_listener_id_; + this->generic_event_listeners_.add(listener); + return {listener.id}; + } + + void event_handler::clear() + { + this->event_listeners_.clear(); + this->generic_event_listeners_.clear(); + } + + void event_handler::remove(const event_listener_handle& handle) + { + for (const auto task : this->event_listeners_) + { + if (task->id == handle.id) + { + this->event_listeners_.remove(task); + return; } } - void event_handler::dispatch_to_specific_listeners(event* event, - const std::vector& arguments) + for (const auto task : this->generic_event_listeners_) { - for (auto listener : this->event_listeners_) + if (task->id == handle.id) { - if (listener->event == event->name && listener->entity_id == event->entity_id) - { - if (listener->is_volatile) - { - this->event_listeners_.remove(listener); - } - - listener->callback(arguments); - } - } - } - - void event_handler::dispatch_to_generic_listeners(event* event, - const std::vector& arguments) - { - for (auto listener : this->generic_event_listeners_) - { - if (listener->event == event->name) - { - if (listener->is_volatile) - { - this->generic_event_listeners_.remove(listener); - } - - listener->callback(entity(this->context_, event->entity_id), arguments); - } - } - } - - event_listener_handle event_handler::add_event_listener(event_listener listener) - { - listener.id = ++this->current_listener_id_; - this->event_listeners_.add(listener); - return {listener.id}; - } - - event_listener_handle event_handler::add_event_listener(generic_event_listener listener) - { - listener.id = ++this->current_listener_id_; - this->generic_event_listeners_.add(listener); - return {listener.id}; - } - - void event_handler::clear() - { - this->event_listeners_.clear(); - this->generic_event_listeners_.clear(); - } - - void event_handler::remove(const event_listener_handle& handle) - { - for (const auto task : this->event_listeners_) - { - if (task->id == handle.id) - { - this->event_listeners_.remove(task); - return; - } - } - - for (const auto task : this->generic_event_listeners_) - { - if (task->id == handle.id) - { - this->generic_event_listeners_.remove(task); - return; - } + this->generic_event_listeners_.remove(task); + return; } } } diff --git a/src/game/scripting/event_handler.hpp b/src/game/scripting/event_handler.hpp index 603a1d5..63d3c6f 100644 --- a/src/game/scripting/event_handler.hpp +++ b/src/game/scripting/event_handler.hpp @@ -1,60 +1,57 @@ -#pragma once -#include "utils/concurrent_list.hpp" -#include "entity.hpp" -#include "event.hpp" - -namespace game -{ - namespace scripting - { - class context; - - class event_listener_handle - { - public: - unsigned long long id = 0; - }; - - class event_listener final : public event_listener_handle - { - public: - std::string event = {}; - unsigned int entity_id = 0; - std::function)> callback = {}; - bool is_volatile = false; - }; - - class generic_event_listener final : public event_listener_handle - { - public: - std::string event = {}; - std::function)> callback = {}; - bool is_volatile = false; - }; - - class event_handler final - { - public: - explicit event_handler(context* context); - - void dispatch(event* event); - - event_listener_handle add_event_listener(event_listener listener); - event_listener_handle add_event_listener(generic_event_listener listener); - - void clear(); - - private: - context* context_; - std::atomic_int64_t current_listener_id_ = 0; - - utils::concurrent_list event_listeners_; - utils::concurrent_list generic_event_listeners_; - - void dispatch_to_specific_listeners(event* event, const std::vector& arguments); - void dispatch_to_generic_listeners(event* event, const std::vector& arguments); - - void remove(const event_listener_handle& handle); - }; - } -} +#pragma once +#include "utils/concurrent_list.hpp" +#include "entity.hpp" +#include "event.hpp" + +namespace game::scripting +{ + class context; + + class event_listener_handle + { + public: + unsigned long long id = 0; + }; + + class event_listener final : public event_listener_handle + { + public: + std::string event = {}; + unsigned int entity_id = 0; + std::function)> callback = {}; + bool is_volatile = false; + }; + + class generic_event_listener final : public event_listener_handle + { + public: + std::string event = {}; + std::function)> callback = {}; + bool is_volatile = false; + }; + + class event_handler final + { + public: + explicit event_handler(context* context); + + void dispatch(event* event); + + event_listener_handle add_event_listener(event_listener listener); + event_listener_handle add_event_listener(generic_event_listener listener); + + void clear(); + + private: + context* context_; + std::atomic_int64_t current_listener_id_ = 0; + + utils::concurrent_list event_listeners_; + utils::concurrent_list generic_event_listeners_; + + void dispatch_to_specific_listeners(event* event, const std::vector& arguments); + void dispatch_to_generic_listeners(event* event, const std::vector& arguments); + + void remove(const event_listener_handle& handle); + }; +} diff --git a/src/game/scripting/executer.cpp b/src/game/scripting/executer.cpp index c57a22e..948632d 100644 --- a/src/game/scripting/executer.cpp +++ b/src/game/scripting/executer.cpp @@ -6,167 +6,164 @@ #include "safe_executer.hpp" #include "context.hpp" -namespace game +namespace game::scripting { - namespace scripting + executer::executer(context* context) : context_(context) { - executer::executer(context* context) : context_(context) + } + + int executer::get_field_id(const int classnum, const std::string& field) const + { + const auto field_name = utils::string::to_lower(field); + const auto class_id = native::g_classMap[classnum].id; + const auto field_str = native::SL_GetString(field_name.data(), 1); + const auto _ = gsl::finally([field_str]() { + native::RemoveRefToValue(native::SCRIPT_STRING, {int(field_str)}); + }); + + const auto offset = native::FindVariable(class_id, field_str); + if (offset) + { + const auto index = 4 * (offset + 0xC800 * (class_id & 1)); + return PINT(SELECT_VALUE(0x1A3BC80, 0x1EFE180, 0x1DC8800))[index]; } - int executer::get_field_id(const int classnum, const std::string& field) const - { - const auto field_name = utils::string::to_lower(field); - const auto class_id = native::g_classMap[classnum].id; - const auto field_str = native::SL_GetString(field_name.data(), 1); - const auto _ = gsl::finally([field_str]() - { - native::RemoveRefToValue(native::SCRIPT_STRING, {int(field_str)}); - }); + return -1; + } - const auto offset = native::FindVariable(class_id, field_str); - if (offset) - { - const auto index = 4 * (offset + 0xC800 * (class_id & 1)); - return PINT(SELECT_VALUE(0x1A3BC80, 0x1EFE180, 0x1DC8800))[index]; - } + void executer::set_entity_field(const std::string& field, const unsigned int entity_id, + const chaiscript::Boxed_Value& value) + { + const auto entref = native::Scr_GetEntityIdRef(entity_id); + const int id = get_field_id(entref.raw.classnum, field); - return -1; - } - - void executer::set_entity_field(const std::string& field, const unsigned int entity_id, - const chaiscript::Boxed_Value& value) - { - const auto entref = native::Scr_GetEntityIdRef(entity_id); - const int id = get_field_id(entref.raw.classnum, field); - - if (id != -1) - { - stack_isolation _; - this->context_->get_parameters()->push(value); - - native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; - native::scr_VmPub->inparamcount = 0; - - if (!safe_executer::set_entity_field(entref, id)) - { - throw std::runtime_error("Failed to set value for field '" + field + "'"); - } - } - else - { - this->entity_fields_[entity_id][field] = value; - } - } - - chaiscript::Boxed_Value executer::get_entity_field(const std::string& field, const unsigned int entity_id) - { - const auto entref = native::Scr_GetEntityIdRef(entity_id); - const auto id = this->get_field_id(entref.raw.classnum, field); - - if (id != -1) - { - stack_isolation _; - - native::VariableValue value{}; - if (!safe_executer::get_entity_field(entref, id, &value)) - { - throw std::runtime_error("Failed to get value for field '" + field + "'"); - } - - const auto $ = gsl::finally([value]() - { - native::RemoveRefToValue(value.type, value.u); - }); - - return this->context_->get_parameters()->load(value); - } - else - { - const auto& map = this->entity_fields_[entity_id]; - const auto value = map.find(field); - if (value != map.end()) - { - return value->second; - } - } - - return {}; - } - - void executer::notify(const std::string& event, const unsigned int entity_id, - std::vector arguments) const + if (id != -1) { stack_isolation _; - - std::reverse(arguments.begin(), arguments.end()); - for (auto argument : arguments) - { - this->context_->get_parameters()->push(argument); - } - - const auto event_id = native::SL_GetString(event.data(), 0); - native::Scr_NotifyId(entity_id, event_id, native::scr_VmPub->inparamcount); - } - - chaiscript::Boxed_Value executer::call(const std::string& function, const unsigned int entity_id, - std::vector arguments) const - { - const auto function_index = find_function_index(function, entity_id == 0); - if (function_index < 0) - { - throw std::runtime_error("No function found for name '" + function + "'"); - } - - const auto entity = function_index > 0x1C7 - ? native::Scr_GetEntityIdRef(entity_id) - : native::scr_entref_t{~0u}; - - const auto function_ptr = native::Scr_GetFunc(function_index); - - stack_isolation _; - - std::reverse(arguments.begin(), arguments.end()); - for (const auto& argument : arguments) - { - this->context_->get_parameters()->push(argument); - } + this->context_->get_parameters()->push(value); native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; native::scr_VmPub->inparamcount = 0; - if (!safe_executer::call(function_ptr, entity)) + if (!safe_executer::set_entity_field(entref, id)) { - throw std::runtime_error("Error executing function '" + function + "'"); + throw std::runtime_error("Failed to set value for field '" + field + "'"); } - - return this->context_->get_parameters()->get_return_value(); } - - int executer::find_function_index(const std::string& function, const bool prefer_global) + else { - const auto target = utils::string::to_lower(function); - - const auto primary_map = prefer_global - ? &global_function_map - : &instance_function_map; - const auto secondary_map = !prefer_global - ? &global_function_map - : &instance_function_map; - - auto function_entry = primary_map->find(target); - if (function_entry != primary_map->end()) - { - return function_entry->second; - } - - function_entry = secondary_map->find(target); - if (function_entry != secondary_map->end()) - { - return function_entry->second; - } - - return -1; + this->entity_fields_[entity_id][field] = value; } } + + chaiscript::Boxed_Value executer::get_entity_field(const std::string& field, const unsigned int entity_id) + { + const auto entref = native::Scr_GetEntityIdRef(entity_id); + const auto id = this->get_field_id(entref.raw.classnum, field); + + if (id != -1) + { + stack_isolation _; + + native::VariableValue value{}; + if (!safe_executer::get_entity_field(entref, id, &value)) + { + throw std::runtime_error("Failed to get value for field '" + field + "'"); + } + + const auto $ = gsl::finally([value]() + { + native::RemoveRefToValue(value.type, value.u); + }); + + return this->context_->get_parameters()->load(value); + } + else + { + const auto& map = this->entity_fields_[entity_id]; + const auto value = map.find(field); + if (value != map.end()) + { + return value->second; + } + } + + return {}; + } + + void executer::notify(const std::string& event, const unsigned int entity_id, + std::vector arguments) const + { + stack_isolation _; + + std::reverse(arguments.begin(), arguments.end()); + for (auto argument : arguments) + { + this->context_->get_parameters()->push(argument); + } + + const auto event_id = native::SL_GetString(event.data(), 0); + native::Scr_NotifyId(entity_id, event_id, native::scr_VmPub->inparamcount); + } + + chaiscript::Boxed_Value executer::call(const std::string& function, const unsigned int entity_id, + std::vector arguments) const + { + const auto function_index = find_function_index(function, entity_id == 0); + if (function_index < 0) + { + throw std::runtime_error("No function found for name '" + function + "'"); + } + + const auto entity = function_index > 0x1C7 + ? native::Scr_GetEntityIdRef(entity_id) + : native::scr_entref_t{~0u}; + + const auto function_ptr = native::Scr_GetFunc(function_index); + + stack_isolation _; + + std::reverse(arguments.begin(), arguments.end()); + for (const auto& argument : arguments) + { + this->context_->get_parameters()->push(argument); + } + + native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; + native::scr_VmPub->inparamcount = 0; + + if (!safe_executer::call(function_ptr, entity)) + { + throw std::runtime_error("Error executing function '" + function + "'"); + } + + return this->context_->get_parameters()->get_return_value(); + } + + int executer::find_function_index(const std::string& function, const bool prefer_global) + { + const auto target = utils::string::to_lower(function); + + const auto primary_map = prefer_global + ? &global_function_map + : &instance_function_map; + const auto secondary_map = !prefer_global + ? &global_function_map + : &instance_function_map; + + auto function_entry = primary_map->find(target); + if (function_entry != primary_map->end()) + { + return function_entry->second; + } + + function_entry = secondary_map->find(target); + if (function_entry != secondary_map->end()) + { + return function_entry->second; + } + + return -1; + } } diff --git a/src/game/scripting/executer.hpp b/src/game/scripting/executer.hpp index 32e1536..01305f0 100644 --- a/src/game/scripting/executer.hpp +++ b/src/game/scripting/executer.hpp @@ -1,34 +1,31 @@ -#pragma once - -namespace game -{ - namespace scripting - { - class context; - - class executer final - { - public: - explicit executer(context* context); - - void set_entity_field(const std::string& field, unsigned int entity_id, - const chaiscript::Boxed_Value& value); - chaiscript::Boxed_Value get_entity_field(const std::string& field, unsigned int entity_id); - - void notify(const std::string& event, unsigned int entity_id, - std::vector arguments) const; - - chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id, - std::vector arguments) const; - - private: - context* context_; - - std::unordered_map> entity_fields_; - - int get_field_id(int classnum, const std::string& field) const; - - static int find_function_index(const std::string& function, bool prefer_global); - }; - } -} +#pragma once + +namespace game::scripting +{ + class context; + + class executer final + { + public: + explicit executer(context* context); + + void set_entity_field(const std::string& field, unsigned int entity_id, + const chaiscript::Boxed_Value& value); + chaiscript::Boxed_Value get_entity_field(const std::string& field, unsigned int entity_id); + + void notify(const std::string& event, unsigned int entity_id, + std::vector arguments) const; + + chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id, + std::vector arguments) const; + + private: + context* context_; + + std::unordered_map> entity_fields_; + + int get_field_id(int classnum, const std::string& field) const; + + static int find_function_index(const std::string& function, bool prefer_global); + }; +} diff --git a/src/game/scripting/functions.cpp b/src/game/scripting/functions.cpp index a7e51ab..06c5867 100644 --- a/src/game/scripting/functions.cpp +++ b/src/game/scripting/functions.cpp @@ -1,751 +1,748 @@ -#include "std_include.hpp" -#include "functions.hpp" - -namespace game -{ - namespace scripting - { - std::map instance_function_map = - { - {"getviewmodel", 33457}, - {"fragbuttonpressed", 33458}, - {"secondaryoffhandbuttonpressed", 33459}, - {"getcurrentweaponclipammo", 33460}, - {"setvelocity", 33461}, - {"getplayerviewheight", 33462}, - {"enablemousesteer", 33545}, - {"getnormalizedmovement", 33463}, - {"getnormalizedcameramovement", 33486}, - {"giveweapon", 33487}, - {"takeweapon", 33488}, - {"takeallweapons", 33489}, - {"getcurrentweapon", 33490}, - {"getcurrentprimaryweapon", 33491}, - {"getcurrentoffhand", 33492}, - {"hasweapon", 33493}, - {"switchtoweapon", 33494}, - {"switchtoweaponimmediate", 33495}, - {"switchtooffhand", 33496}, - {"givestartammo", 33522}, - {"givemaxammo", 33523}, - {"getfractionstartammo", 33524}, - {"getfractionmaxammo", 33525}, - {"isdualwielding", 33526}, - {"isreloading", 33527}, - {"isswitchingweapon", 33528}, - {"setorigin", 33529}, - {"getvelocity", 33530}, - {"setplayerangles", 33531}, - {"getplayerangles", 33532}, - {"usebuttonpressed", 33533}, - {"attackbuttonpressed", 33534}, - {"adsbuttonpressed", 33535}, - {"meleebuttonpressed", 33536}, - {"playerads", 33537}, - {"isonground", 33538}, - {"isusingturret", 33539}, - {"setviewmodel", 33540}, - {"setoffhandprimaryclass", 33541}, - {"getoffhandprimaryclass", 33542}, - {"setoffhandsecondaryclass", 33497}, - {"getoffhandsecondaryclass", 33498}, - {"beginlocationselection", 33499}, - {"endlocationselection", 33500}, - {"disableweapons", 33501}, - {"enableweapons", 33502}, - {"disableoffhandweapons", 33503}, - {"enableoffhandweapons", 33504}, - {"disableweaponswitch", 33505}, - {"enableweaponswitch", 33506}, - {"openpopupmenu", 33507}, - {"openpopupmenunomouse", 33508}, - {"closepopupmenu", 33509}, - {"openmenu", 33510}, - {"closemenu", 33511}, - {"freezecontrols", 33513}, - {"disableusability", 33514}, - {"enableusability", 33515}, - {"setwhizbyspreads", 33516}, - {"setwhizbyradii", 33517}, - {"setreverb", 33518}, - {"deactivatereverb", 33519}, - {"setvolmod", 33520}, - {"setchannelvolume", 33521}, - {"setchannelvolumes", 33464}, - {"deactivatechannelvolumes", 33465}, - {"playlocalsound", 33466}, - {"stoplocalsound", 33467}, - {"setweaponammoclip", 33468}, - {"setweaponammostock", 33469}, - {"getweaponammoclip", 33470}, - {"getweaponammostock", 33471}, - {"anyammoforweaponmodes", 33472}, - {"setclientdvar", 33473}, - {"setclientdvars", 33474}, - {"allowads", 33475}, - {"allowjump", 33476}, - {"allowsprint", 33477}, - {"setspreadoverride", 33478}, - {"resetspreadoverride", 33479}, - {"setaimspreadmovementscale", 33480}, - {"setactionslot", 33481}, - {"setviewkickscale", 33482}, - {"getviewkickscale", 33483}, - {"getweaponslistall", 33484}, - {"getweaponslistprimaries", 33485}, - {"getweaponslistoffhands", 33430}, - {"getweaponslistitems", 33431}, - {"getweaponslistexclusives", 33432}, - {"getweaponslist", 33433}, - {"canplayerplacesentry", 33434}, - {"canplayerplacetank", 33435}, - {"visionsetnakedforplayer", 33436}, - {"visionsetnightforplayer", 33437}, - {"visionsetmissilecamforplayer", 33438}, - {"visionsetthermalforplayer", 33439}, - {"visionsetpainforplayer", 33440}, - {"setblurforplayer", 33441}, - {"getplayerweaponmodel", 33442}, - {"getplayerknifemodel", 33443}, - {"updateplayermodelwithweapons", 33444}, - {"notifyonplayercommand", 33445}, - {"canmantle", 33446}, - {"forcemantle", 33447}, - {"ismantling", 33448}, - {"playfx", 33449}, - {"recoilscaleon", 33450}, - {"recoilscaleoff", 33451}, - {"weaponlockstart", 33452}, - {"weaponlockfinalize", 33453}, - {"weaponlockfree", 33454}, - {"weaponlocktargettooclose", 33455}, - {"weaponlocknoclearance", 33390}, - {"visionsyncwithplayer", 33391}, - {"showhudsplash", 33392}, - {"setperk", 33393}, - {"hasperk", 33394}, - {"clearperks", 33395}, - {"unsetperk", 33396}, - {"noclip", 33397}, - {"ufo", 33398}, - - // playercmd #2 - {"pingplayer", 33308}, - {"buttonpressed", 33309}, - {"sayall", 33310}, - {"sayteam", 33311}, - {"showscoreboard", 33312}, - {"setspawnweapon", 33313}, - {"dropitem", 33314}, - {"dropscavengerbag", 33315}, - {"finishplayerdamage", 33340}, - {"suicide", 33341}, - {"closeingamemenu", 33342}, - {"iprintln", 33343}, - {"iprintlnbold", 33344}, - {"spawn", 33345}, - {"setentertime", 33346}, - {"cloneplayer", 33347}, - {"istalking", 33348}, - {"allowspectateteam", 33349}, - {"getguid", 33350}, - {"getxuid", 33382}, - {"ishost", 33383}, - {"getspectatingplayer", 33384}, - {"predictstreampos", 33385}, - {"updatescores", 33386}, - {"updatedmscores", 33387}, - {"setrank", 33388}, - {"setcardtitle", 33389}, - {"setcardicon", 33420}, - {"setcardnameplate", 33421}, - {"setcarddisplayslot", 33422}, - {"regweaponforfxremoval", 33423}, - {"laststandrevive", 33424}, - {"setspectatedefaults", 33425}, - {"getthirdpersoncrosshairoffset", 33426}, - {"disableweaponpickup", 33427}, - {"enableweaponpickup", 33428}, - - // HECmd - {"settext", 32950}, - {"clearalltextafterhudelem", 32951}, - {"setshader", 32952}, - {"settargetent", 32953}, - {"cleartargetent", 32954}, - {"settimer", 32955}, - {"settimerup", 32956}, - {"settimerstatic", 32957}, - {"settenthstimer", 32958}, - {"settenthstimerup", 32959}, - {"settenthstimerstatic", 32960}, - {"setclock", 32961}, - {"setclockup", 32962}, - {"setvalue", 32963}, - {"setwaypoint", 32964}, - {"rotatingicon", 32965}, - {"secondaryarrow", 32891}, - {"setwaypointiconoffscreenonly", 32892}, - {"fadeovertime", 32893}, - {"scaleovertime", 32894}, - {"moveovertime", 32895}, - {"reset", 32896}, - {"destroy", 32897}, - {"setpulsefx", 32898}, - {"setplayernamestring", 32899}, - {"fadeovertime2", 33547}, - {"scaleovertime2", 33548}, - {"changefontscaleovertime", 32900}, - - // ScrCmd - {"attach", 32791}, - {"attachshieldmodel", 32792}, - {"detach", 32804}, - {"detachshieldmodel", 32805}, - {"moveshieldmodel", 32806}, - {"detachall", 32807}, - {"getattachsize", 32808}, - {"getattachmodelname", 32809}, - {"getattachtagname", 32810}, - {"getattachignorecollision", 32835}, - {"hidepart", 32836}, - {"allinstances", 32837}, - {"hideallparts", 32838}, - {"showpart", 32839}, - {"showallparts", 32840}, - {"linkto", 32841}, - {"linktoblendtotag", 32842}, - {"unlink", 32843}, - {"islinked", 32867}, - {"enablelinkto", 32868}, - {"playerlinkto", 32885}, - {"playerlinktodelta", 32886}, - {"playerlinkweaponviewtodelta", 32887}, - {"playerlinktoabsolute", 32888}, - {"playerlinktoblend", 32889}, - {"playerlinkedoffsetenable", 32890}, - {"playerlinkedoffsetdisable", 32916}, - {"playerlinkedsetviewznear", 32917}, - {"playerlinkedsetusebaseangleforviewclamp", 32918}, - {"lerpviewangleclamp", 32919}, - {"setviewangleresistance", 32920}, - {"geteye", 32921}, - {"istouching", 32922}, - {"stoploopsound", 32923}, - {"stopsounds", 32924}, - {"playrumbleonentity", 32925}, - {"playrumblelooponentity", 32926}, - {"stoprumble", 32927}, - {"delete", 32928}, - {"setmodel", 32929}, - {"laseron", 32930}, - {"laseroff", 32931}, - {"laseraltviewon", 32932}, - {"laseraltviewoff", 32933}, - {"thermalvisionon", 32934}, - {"thermalvisionoff", 32935}, - {"thermaldrawenable", 32803}, - {"thermaldrawdisable", 32768}, - {"thermalvisionfofoverlayon", 32936}, - {"thermalvisionfofoverlayoff", 32937}, - {"autospotoverlayon", 32938}, - {"autospotoverlayoff", 32939}, - {"setcontents", 32940}, - {"makeusable", 32941}, - {"makeunusable", 32942}, - {"setcursorhint", 32966}, - {"sethintstring", 32967}, - {"forceusehinton", 32968}, - {"forceusehintoff", 32969}, - {"makesoft", 32970}, - {"makehard", 32971}, - {"willneverchange", 32972}, - {"startfiring", 32973}, - {"stopfiring", 32974}, - {"isfiringturret", 32975}, - {"startbarrelspin", 32976}, - {"stopbarrelspin", 32977}, - {"getbarrelspinrate", 32978}, - {"remotecontrolturret", 32979}, - {"remotecontrolturretoff", 32980}, - {"shootturret", 32981}, - {"getturretowner", 32982}, - {"setsentryowner", 33006}, - {"setsentrycarrier", 33007}, - {"setturretminimapvisible", 33008}, - {"settargetentity", 33009}, - {"snaptotargetentity", 33010}, - {"cleartargetentity", 33011}, - {"getturrettarget", 33012}, - {"setplayerspread", 33013}, - {"setaispread", 33014}, - {"setsuppressiontime", 33015}, - {"setconvergencetime", 33049}, - {"setconvergenceheightpercent", 33050}, - {"setturretteam", 33051}, - {"maketurretsolid", 33052}, - {"maketurretoperable", 33053}, - {"maketurretinoperable", 33054}, - {"setturretaccuracy", 33082}, - {"setrightarc", 33083}, - {"setleftarc", 33084}, - {"settoparc", 33085}, - {"setbottomarc", 33086}, - {"setautorotationdelay", 33087}, - {"setdefaultdroppitch", 33088}, - {"restoredefaultdroppitch", 33089}, - {"turretfiredisable", 33090}, - {"turretfireenable", 33121}, - {"setturretmodechangewait", 33122}, - {"usetriggerrequirelookat", 33123}, - {"getstance", 33124}, - {"setstance", 33125}, - {"itemweaponsetammo", 33126}, - {"getammocount", 33127}, - {"gettagorigin", 33128}, - {"gettagangles", 33129}, - {"shellshock", 33130}, - {"stunplayer", 33131}, - {"stopshellshock", 33132}, - {"fadeoutshellshock", 33133}, - {"setdepthoffield", 33134}, - {"setviewmodeldepthoffield", 33135}, - {"setmotionblurmovescale", 33136}, - {"setmotionblurturnscale", 33168}, - {"setmotionblurzoomscale", 33169}, - {"viewkick", 33170}, - {"localtoworldcoords", 33171}, - {"getentitynumber", 33172}, - {"getentityvelocity", 33173}, - {"enablegrenadetouchdamage", 33174}, - {"disablegrenadetouchdamage", 33175}, - {"enableaimassist", 33176}, - {"disableaimassist", 33207}, - {"radiusdamage", 33208}, - {"detonate", 33209}, - {"damageconetrace", 33210}, - {"sightconetrace", 33211}, - {"settargetent", 33212}, - {"settargetpos", 33213}, - {"cleartarget", 33214}, - {"setflightmodedirect", 33215}, - {"setflightmodetop", 33216}, - {"getlightintensity", 33217}, - {"setlightintensity", 33218}, - {"isragdoll", 33219}, - {"setmovespeedscale", 33220}, - {"cameralinkto", 33221}, - {"cameraunlink", 33222}, - {"controlslinkto", 33251}, - {"controlsunlink", 33252}, - {"makevehiclesolidcapsule", 33253}, - {"makevehiclesolidsphere", 33254}, - {"remotecontrolvehicle", 33256}, - {"remotecontrolvehicleoff", 33257}, - {"isfiringvehicleturret", 33258}, - {"drivevehicleandcontrolturret", 33259}, - {"drivevehicleandcontrolturretoff", 33260}, - {"getplayersetting", 33261}, - {"getlocalplayerprofiledata", 33262}, - {"setlocalplayerprofiledata", 33263}, - {"remotecamerasoundscapeon", 33264}, - {"remotecamerasoundscapeoff", 33265}, - {"radarjamon", 33266}, - {"radarjamoff", 33267}, - {"setmotiontrackervisible", 33268}, - {"getmotiontrackervisible", 33269}, - {"circle", 33270}, - {"getpointinbounds", 33271}, - {"transfermarkstonewscriptmodel", 33272}, - {"setwatersheeting", 33273}, - {"setweaponhudiconoverride", 33274}, - {"getweaponhudiconoverride", 33275}, - {"setempjammed", 33276}, - {"playersetexpfog", 33277}, - {"isitemunlocked", 33278}, - {"getplayerdata", 33279}, - {"setplayerdata", 33306}, - - // Vehicle stuff - {"teleport", 0x824C}, - {"attachpath", 0x824D}, - {"getattachpos", 0x824E}, - {"startpath", 0x824F}, - {"setswitchnode", 0x8250}, - {"setwaitspeed", 0x8251}, - {"finishdamage", 0x8252}, - {"setspeed", 0x8253}, - {"setspeedimmediate", 0x8254}, - {"setwaitspeed", 0x8251}, - - {"setlookatent", 0x8237}, - {"clearlookatent", 0x8238}, - - {"setvehgoalpos", 33325}, - {"setturningability", 33381}, - - // some entity (script_model) stuff - {"moveto", 33399}, - {"movex", 33400}, - {"movey", 33401}, - {"movez", 33402}, - {"movegravity", 33403}, - {"moveslide", 33404}, - {"stopmoveslide", 33405}, - {"rotateto", 33406}, - {"rotatepitch", 33407}, - {"rotateyaw", 33408}, - {"rotateroll", 33409}, - {"addpitch", 33410}, - {"addyaw", 33411}, - {"addroll", 33412}, - {"vibrate", 33413}, - {"rotatevelocity", 33414}, - {"solid", 33415}, - {"notsolid", 33416}, - {"setcandamage", 33417}, - {"setcanradiusdamage", 33418}, - {"physicslaunchclient", 33419}, - {"physicslaunchserver", 33351}, - {"physicslaunchserveritem", 33352}, - {"clonebrushmodeltoscriptmodel", 33353}, - {"scriptmodelplayanim", 33354}, - {"scriptmodelclearanim", 33355}, - - // varied ent/player script commands - {"getorigin", 32910}, - {"useby", 32914}, - {"playsound", 32915}, - {"playsoundasmaster", 32878}, - {"playsoundtoteam", 32771}, - {"playsoundtoplayer", 32772}, - {"playloopsound", 32879}, - {"getnormalhealth", 32884}, - {"setnormalhealth", 32844}, - {"show", 32847}, - {"hide", 32848}, - {"playerhide", 32773}, - {"showtoplayer", 32774}, - {"enableplayeruse", 32775}, - {"disableplayeruse", 32776}, - {"setscriptmoverkillcam", 33546}, - {"makescrambler", 32777}, - {"makeportableradar", 32778}, - {"maketrophysystem", 32779}, - {"setmode", 32864}, - {"getmode", 32865}, - {"placespawnpoint", 32780}, - {"setteamfortrigger", 32781}, - {"clientclaimtrigger", 32782}, - {"clientreleasetrigger", 32783}, - {"releaseclaimedtrigger", 32784}, - {"isusingonlinedataoffline", 32785}, - {"getrestedtime", 32786}, - {"sendleaderboards", 32787}, - {"logstring", 32800}, - {"isonladder", 32788}, - {"startragdoll", 32798}, - {"getcorpseanim", 32789}, - {"playerforcedeathanim", 32790}, - {"startac130", 33543}, - {"stopac130", 33544}, - }; - - std::map global_function_map = - { - // global stuff #1 - {"iprintln", 362}, - {"iprintlnbold", 363}, - {"logstring", 364}, - {"getent", 365}, - {"getentarray", 366}, - {"spawnplane", 367}, - {"spawnstruct", 368}, - {"spawnhelicopter", 369}, - {"isalive", 370}, - {"isspawner", 371}, - {"createattractorent", 372}, - {"createattractororigin", 373}, - {"createrepulsorent", 374}, - {"createrepulsororigin", 375}, - {"deleteattractor", 376}, - {"playsoundatpos", 377}, - {"newhudelem", 378}, - {"newclienthudelem", 379}, - {"newteamhudelem", 380}, - {"resettimeout", 381}, - {"precachefxteamthermal", 382}, - {"isplayer", 383}, - {"isplayernumber", 384}, - {"setsunlight", 57}, - {"resetsunlight", 58}, - {"setwinningplayer", 385}, - {"setwinningteam", 311}, - {"announcement", 312}, - {"clientannouncement", 313}, - {"getteamscore", 314}, - {"setteamscore", 315}, - {"setclientnamemode", 316}, - {"updateclientnames", 317}, - {"getteamplayersalive", 318}, - {"logprint", 319}, - {"worldentnumber", 320}, - {"obituary", 321}, - {"positionwouldtelefrag", 322}, - {"canspawn", 323}, - {"getstarttime", 324}, - {"precachestatusicon", 325}, - {"precacheminimapicon", 327}, - {"precachempanim", 328}, - {"restart", 329}, - {"exitlevel", 330}, - {"addtestclient", 331}, - {"makedvarserverinfo", 332}, - {"setarchive", 333}, - {"allclientsprint", 334}, - {"clientprint", 335}, - {"mapexists", 336}, - {"isvalidgametype", 337}, - {"matchend", 338}, - {"setplayerteamrank", 339}, - {"endparty", 340}, - {"setteamradar", 341}, - {"getteamradar", 342}, - {"setteamradarstrength", 343}, - {"getteamradarstrength", 344}, - {"getuavstrengthmin", 345}, - {"getuavstrengthmax", 262}, - {"getuavstrengthlevelneutral", 263}, - {"getuavstrengthlevelshowenemyfastsweep", 264}, - {"getuavstrengthlevelshowenemydirectional", 265}, - {"blockteamradar", 266}, - {"unblockteamradar", 267}, - {"isteamradarblocked", 268}, - {"getassignedteam", 269}, - {"setmatchdata", 270}, - {"getmatchdata", 271}, - {"sendmatchdata", 272}, - {"clearmatchdata", 273}, - {"setmatchdatadef", 274}, - {"setmatchclientip", 275}, - {"setmatchdataid", 276}, - {"setclientmatchdata", 277}, - {"getclientmatchdata", 278}, - {"setclientmatchdatadef", 279}, - {"sendclientmatchdata", 280}, - {"getbuildversion", 281}, - {"getbuildnumber", 282}, - {"getsystemtime", 283}, - {"getmatchrulesdata", 284}, - {"isusingmatchrulesdata", 285}, - {"kick", 286}, - {"issplitscreen", 287}, - {"setmapcenter", 288}, - {"setgameendtime", 289}, - {"visionsetnaked", 290}, - {"visionsetnight", 291}, - {"visionsetmissilecam", 292}, - {"visionsetthermal", 217}, - {"visionsetpain", 218}, - {"endlobby", 219}, - {"ambience", 220}, - {"getmapcustom", 221}, - {"updateskill", 222}, - {"spawnsighttrace", 223}, - - // global stuff #2 - {"setprintchannel", 14}, - {"print", 15}, - {"println", 16}, - {"print3d", 17}, - {"line", 18}, - {"spawnturret", 19}, - {"canspawnturret", 20}, - {"assert", 21}, - {"assertex", 38}, - {"assertmsg", 39}, - {"isdefined", 40}, - {"isstring", 41}, - {"setdvar", 42}, - {"setdynamicdvar", 43}, - {"setdvarifuninitialized", 44}, - {"setdevdvar", 45}, - {"setdevdvarifuninitialized", 46}, - {"getdvar", 47}, - {"getdvarint", 48}, - {"getdvarfloat", 49}, - {"getdvarvector", 50}, - {"gettime", 51}, - {"getentbynum", 52}, - {"getweaponmodel", 53}, - {"getweaponhidetags", 81}, - {"getanimlength", 82}, - {"animhasnotetrack", 83}, - {"getnotetracktimes", 84}, - {"spawn", 85}, - {"spawnloopsound", 86}, - {"bullettrace", 87}, - {"bullettracepassed", 88}, - {"sighttracepassed", 116}, - {"physicstrace", 117}, - {"physicstracenormal", 118}, - {"playerphysicstrace", 119}, - {"getgroundposition", 120}, - {"getmovedelta", 121}, - {"getangledelta", 122}, - {"getnorthyaw", 123}, - {"setnorthyaw", 150}, - {"setslowmotion", 151}, - {"randomint", 152}, - {"randomfloat", 153}, - {"randomintrange", 154}, - {"randomfloatrange", 155}, - {"sin", 156}, - {"cos", 157}, - {"tan", 158}, - {"asin", 159}, - {"acos", 160}, - {"atan", 161}, - {"int", 162}, - {"float", 163}, - {"abs", 164}, - {"min", 165}, - {"max", 198}, - {"floor", 199}, - {"ceil", 200}, - {"exp", 201}, - {"log", 202}, - {"sqrt", 203}, - {"squared", 204}, - {"clamp", 205}, - {"angleclamp", 206}, - {"angleclamp180", 207}, - {"vectorfromlinetopoint", 208}, - {"pointonsegmentnearesttopoint", 209}, - {"distance", 210}, - {"distance2d", 211}, - {"distancesquared", 212}, - {"length", 213}, - {"lengthsquared", 214}, - {"closer", 215}, - {"vectordot", 216}, - {"vectornormalize", 246}, - {"vectortoangles", 247}, - {"vectortoyaw", 248}, - {"vectorlerp", 249}, - {"anglestoup", 250}, - {"anglestoright", 251}, - {"anglestoforward", 252}, - {"combineangles", 253}, - {"transformmove", 254}, - {"issubstr", 255}, - {"isendstr", 256}, - {"getsubstr", 257}, - {"tolower", 258}, - {"strtok", 259}, - {"stricmp", 260}, - {"ambientplay", 261}, - {"ambientstop", 293}, - {"precachemodel", 294}, - {"precacheshellshock", 295}, - {"precacheitem", 296}, - {"precacheshader", 297}, - {"precachestring", 298}, - {"precachemenu", 299}, - {"precacherumble", 300}, - {"precachelocationselector", 301}, - {"precacheleaderboards", 302}, - {"precacheheadicon", 326}, - {"loadfx", 303}, - {"playfx", 304}, - {"playfxontag", 305}, - {"stopfxontag", 306}, - {"playloopedfx", 307}, - {"spawnfx", 308}, - {"triggerfx", 309}, - {"playfxontagforclients", 310}, - {"physicsexplosionsphere", 346}, - {"physicsexplosioncylinder", 347}, - {"physicsjolt", 348}, - {"physicsjitter", 349}, - {"setexpfog", 350}, - {"isexplosivedamagemod", 351}, - {"radiusdamage", 352}, - {"setplayerignoreradiusdamage", 353}, - {"glassradiusdamage", 354}, - {"earthquake", 355}, - {"getnumparts", 356}, - {"getpartname", 386}, - {"weaponfiretime", 387}, - {"weaponclipsize", 388}, - {"weaponisauto", 389}, - {"weaponissemiauto", 390}, - {"weaponisboltaction", 391}, - {"weaponinheritsperks", 392}, - {"weaponburstcount", 393}, - {"weapontype", 394}, - {"weaponclass", 395}, - {"weaponinventorytype", 437}, - {"weaponstartammo", 438}, - {"weaponmaxammo", 439}, - {"weaponaltweaponname", 440}, - {"isweaponcliponly", 441}, - {"isweapondetonationtimed", 442}, - {"weaponhasthermalscope", 443}, - {"getvehiclenode", 444}, - {"getvehiclenodearray", 445}, - {"getallvehiclenodes", 446}, - {"getnumvehicles", 447}, - {"precachevehicle", 448}, - {"spawnvehicle", 449}, - {"getarray", 450}, - {"getspawnerarray", 408}, - {"playrumbleonposition", 409}, - {"playrumblelooponposition", 410}, - {"stopallrumbles", 411}, - {"soundexists", 412}, - {"openfile", 413}, - {"closefile", 414}, - {"fprintln", 415}, - {"fprintfields", 416}, - {"freadln", 417}, - {"fgetarg", 418}, - {"setminimap", 419}, - {"setthermalbodymaterial", 420}, - {"getarraykeys", 421}, - {"getfirstarraykey", 422}, - {"getnextarraykey", 396}, - {"sortbydistance", 397}, - {"tablelookup", 398}, - {"tablelookupbyrow", 399}, - {"tablelookupistring", 400}, - {"tablelookupistringbyrow", 401}, - {"tablelookuprownum", 402}, - {"getmissileowner", 403}, - {"magicbullet", 404}, - {"getweaponflashtagname", 405}, - {"averagepoint", 406}, - {"averagenormal", 407}, - {"getglass", 423}, - {"getglassarray", 424}, - {"getglassorigin", 425}, - {"isglassdestroyed", 426}, - {"destroyglass", 427}, - {"deleteglass", 428}, - {"getentchannelscount", 429}, - - // objective - {"objective_add", 431}, - {"objective_delete", 432}, - {"objective_state", 433}, - {"objective_icon", 434}, - {"objective_position", 435}, - {"objective_current", 436}, - {"objective_onentity", 357}, - {"objective_team", 358}, - {"objective_player", 359}, - {"objective_playerteam", 360}, - {"objective_playerenemyteam", 361}, - }; - } -} +#include "std_include.hpp" +#include "functions.hpp" + +namespace game::scripting +{ + std::map instance_function_map = + { + {"getviewmodel", 33457}, + {"fragbuttonpressed", 33458}, + {"secondaryoffhandbuttonpressed", 33459}, + {"getcurrentweaponclipammo", 33460}, + {"setvelocity", 33461}, + {"getplayerviewheight", 33462}, + {"enablemousesteer", 33545}, + {"getnormalizedmovement", 33463}, + {"getnormalizedcameramovement", 33486}, + {"giveweapon", 33487}, + {"takeweapon", 33488}, + {"takeallweapons", 33489}, + {"getcurrentweapon", 33490}, + {"getcurrentprimaryweapon", 33491}, + {"getcurrentoffhand", 33492}, + {"hasweapon", 33493}, + {"switchtoweapon", 33494}, + {"switchtoweaponimmediate", 33495}, + {"switchtooffhand", 33496}, + {"givestartammo", 33522}, + {"givemaxammo", 33523}, + {"getfractionstartammo", 33524}, + {"getfractionmaxammo", 33525}, + {"isdualwielding", 33526}, + {"isreloading", 33527}, + {"isswitchingweapon", 33528}, + {"setorigin", 33529}, + {"getvelocity", 33530}, + {"setplayerangles", 33531}, + {"getplayerangles", 33532}, + {"usebuttonpressed", 33533}, + {"attackbuttonpressed", 33534}, + {"adsbuttonpressed", 33535}, + {"meleebuttonpressed", 33536}, + {"playerads", 33537}, + {"isonground", 33538}, + {"isusingturret", 33539}, + {"setviewmodel", 33540}, + {"setoffhandprimaryclass", 33541}, + {"getoffhandprimaryclass", 33542}, + {"setoffhandsecondaryclass", 33497}, + {"getoffhandsecondaryclass", 33498}, + {"beginlocationselection", 33499}, + {"endlocationselection", 33500}, + {"disableweapons", 33501}, + {"enableweapons", 33502}, + {"disableoffhandweapons", 33503}, + {"enableoffhandweapons", 33504}, + {"disableweaponswitch", 33505}, + {"enableweaponswitch", 33506}, + {"openpopupmenu", 33507}, + {"openpopupmenunomouse", 33508}, + {"closepopupmenu", 33509}, + {"openmenu", 33510}, + {"closemenu", 33511}, + {"freezecontrols", 33513}, + {"disableusability", 33514}, + {"enableusability", 33515}, + {"setwhizbyspreads", 33516}, + {"setwhizbyradii", 33517}, + {"setreverb", 33518}, + {"deactivatereverb", 33519}, + {"setvolmod", 33520}, + {"setchannelvolume", 33521}, + {"setchannelvolumes", 33464}, + {"deactivatechannelvolumes", 33465}, + {"playlocalsound", 33466}, + {"stoplocalsound", 33467}, + {"setweaponammoclip", 33468}, + {"setweaponammostock", 33469}, + {"getweaponammoclip", 33470}, + {"getweaponammostock", 33471}, + {"anyammoforweaponmodes", 33472}, + {"setclientdvar", 33473}, + {"setclientdvars", 33474}, + {"allowads", 33475}, + {"allowjump", 33476}, + {"allowsprint", 33477}, + {"setspreadoverride", 33478}, + {"resetspreadoverride", 33479}, + {"setaimspreadmovementscale", 33480}, + {"setactionslot", 33481}, + {"setviewkickscale", 33482}, + {"getviewkickscale", 33483}, + {"getweaponslistall", 33484}, + {"getweaponslistprimaries", 33485}, + {"getweaponslistoffhands", 33430}, + {"getweaponslistitems", 33431}, + {"getweaponslistexclusives", 33432}, + {"getweaponslist", 33433}, + {"canplayerplacesentry", 33434}, + {"canplayerplacetank", 33435}, + {"visionsetnakedforplayer", 33436}, + {"visionsetnightforplayer", 33437}, + {"visionsetmissilecamforplayer", 33438}, + {"visionsetthermalforplayer", 33439}, + {"visionsetpainforplayer", 33440}, + {"setblurforplayer", 33441}, + {"getplayerweaponmodel", 33442}, + {"getplayerknifemodel", 33443}, + {"updateplayermodelwithweapons", 33444}, + {"notifyonplayercommand", 33445}, + {"canmantle", 33446}, + {"forcemantle", 33447}, + {"ismantling", 33448}, + {"playfx", 33449}, + {"recoilscaleon", 33450}, + {"recoilscaleoff", 33451}, + {"weaponlockstart", 33452}, + {"weaponlockfinalize", 33453}, + {"weaponlockfree", 33454}, + {"weaponlocktargettooclose", 33455}, + {"weaponlocknoclearance", 33390}, + {"visionsyncwithplayer", 33391}, + {"showhudsplash", 33392}, + {"setperk", 33393}, + {"hasperk", 33394}, + {"clearperks", 33395}, + {"unsetperk", 33396}, + {"noclip", 33397}, + {"ufo", 33398}, + + // playercmd #2 + {"pingplayer", 33308}, + {"buttonpressed", 33309}, + {"sayall", 33310}, + {"sayteam", 33311}, + {"showscoreboard", 33312}, + {"setspawnweapon", 33313}, + {"dropitem", 33314}, + {"dropscavengerbag", 33315}, + {"finishplayerdamage", 33340}, + {"suicide", 33341}, + {"closeingamemenu", 33342}, + {"iprintln", 33343}, + {"iprintlnbold", 33344}, + {"spawn", 33345}, + {"setentertime", 33346}, + {"cloneplayer", 33347}, + {"istalking", 33348}, + {"allowspectateteam", 33349}, + {"getguid", 33350}, + {"getxuid", 33382}, + {"ishost", 33383}, + {"getspectatingplayer", 33384}, + {"predictstreampos", 33385}, + {"updatescores", 33386}, + {"updatedmscores", 33387}, + {"setrank", 33388}, + {"setcardtitle", 33389}, + {"setcardicon", 33420}, + {"setcardnameplate", 33421}, + {"setcarddisplayslot", 33422}, + {"regweaponforfxremoval", 33423}, + {"laststandrevive", 33424}, + {"setspectatedefaults", 33425}, + {"getthirdpersoncrosshairoffset", 33426}, + {"disableweaponpickup", 33427}, + {"enableweaponpickup", 33428}, + + // HECmd + {"settext", 32950}, + {"clearalltextafterhudelem", 32951}, + {"setshader", 32952}, + {"settargetent", 32953}, + {"cleartargetent", 32954}, + {"settimer", 32955}, + {"settimerup", 32956}, + {"settimerstatic", 32957}, + {"settenthstimer", 32958}, + {"settenthstimerup", 32959}, + {"settenthstimerstatic", 32960}, + {"setclock", 32961}, + {"setclockup", 32962}, + {"setvalue", 32963}, + {"setwaypoint", 32964}, + {"rotatingicon", 32965}, + {"secondaryarrow", 32891}, + {"setwaypointiconoffscreenonly", 32892}, + {"fadeovertime", 32893}, + {"scaleovertime", 32894}, + {"moveovertime", 32895}, + {"reset", 32896}, + {"destroy", 32897}, + {"setpulsefx", 32898}, + {"setplayernamestring", 32899}, + {"fadeovertime2", 33547}, + {"scaleovertime2", 33548}, + {"changefontscaleovertime", 32900}, + + // ScrCmd + {"attach", 32791}, + {"attachshieldmodel", 32792}, + {"detach", 32804}, + {"detachshieldmodel", 32805}, + {"moveshieldmodel", 32806}, + {"detachall", 32807}, + {"getattachsize", 32808}, + {"getattachmodelname", 32809}, + {"getattachtagname", 32810}, + {"getattachignorecollision", 32835}, + {"hidepart", 32836}, + {"allinstances", 32837}, + {"hideallparts", 32838}, + {"showpart", 32839}, + {"showallparts", 32840}, + {"linkto", 32841}, + {"linktoblendtotag", 32842}, + {"unlink", 32843}, + {"islinked", 32867}, + {"enablelinkto", 32868}, + {"playerlinkto", 32885}, + {"playerlinktodelta", 32886}, + {"playerlinkweaponviewtodelta", 32887}, + {"playerlinktoabsolute", 32888}, + {"playerlinktoblend", 32889}, + {"playerlinkedoffsetenable", 32890}, + {"playerlinkedoffsetdisable", 32916}, + {"playerlinkedsetviewznear", 32917}, + {"playerlinkedsetusebaseangleforviewclamp", 32918}, + {"lerpviewangleclamp", 32919}, + {"setviewangleresistance", 32920}, + {"geteye", 32921}, + {"istouching", 32922}, + {"stoploopsound", 32923}, + {"stopsounds", 32924}, + {"playrumbleonentity", 32925}, + {"playrumblelooponentity", 32926}, + {"stoprumble", 32927}, + {"delete", 32928}, + {"setmodel", 32929}, + {"laseron", 32930}, + {"laseroff", 32931}, + {"laseraltviewon", 32932}, + {"laseraltviewoff", 32933}, + {"thermalvisionon", 32934}, + {"thermalvisionoff", 32935}, + {"thermaldrawenable", 32803}, + {"thermaldrawdisable", 32768}, + {"thermalvisionfofoverlayon", 32936}, + {"thermalvisionfofoverlayoff", 32937}, + {"autospotoverlayon", 32938}, + {"autospotoverlayoff", 32939}, + {"setcontents", 32940}, + {"makeusable", 32941}, + {"makeunusable", 32942}, + {"setcursorhint", 32966}, + {"sethintstring", 32967}, + {"forceusehinton", 32968}, + {"forceusehintoff", 32969}, + {"makesoft", 32970}, + {"makehard", 32971}, + {"willneverchange", 32972}, + {"startfiring", 32973}, + {"stopfiring", 32974}, + {"isfiringturret", 32975}, + {"startbarrelspin", 32976}, + {"stopbarrelspin", 32977}, + {"getbarrelspinrate", 32978}, + {"remotecontrolturret", 32979}, + {"remotecontrolturretoff", 32980}, + {"shootturret", 32981}, + {"getturretowner", 32982}, + {"setsentryowner", 33006}, + {"setsentrycarrier", 33007}, + {"setturretminimapvisible", 33008}, + {"settargetentity", 33009}, + {"snaptotargetentity", 33010}, + {"cleartargetentity", 33011}, + {"getturrettarget", 33012}, + {"setplayerspread", 33013}, + {"setaispread", 33014}, + {"setsuppressiontime", 33015}, + {"setconvergencetime", 33049}, + {"setconvergenceheightpercent", 33050}, + {"setturretteam", 33051}, + {"maketurretsolid", 33052}, + {"maketurretoperable", 33053}, + {"maketurretinoperable", 33054}, + {"setturretaccuracy", 33082}, + {"setrightarc", 33083}, + {"setleftarc", 33084}, + {"settoparc", 33085}, + {"setbottomarc", 33086}, + {"setautorotationdelay", 33087}, + {"setdefaultdroppitch", 33088}, + {"restoredefaultdroppitch", 33089}, + {"turretfiredisable", 33090}, + {"turretfireenable", 33121}, + {"setturretmodechangewait", 33122}, + {"usetriggerrequirelookat", 33123}, + {"getstance", 33124}, + {"setstance", 33125}, + {"itemweaponsetammo", 33126}, + {"getammocount", 33127}, + {"gettagorigin", 33128}, + {"gettagangles", 33129}, + {"shellshock", 33130}, + {"stunplayer", 33131}, + {"stopshellshock", 33132}, + {"fadeoutshellshock", 33133}, + {"setdepthoffield", 33134}, + {"setviewmodeldepthoffield", 33135}, + {"setmotionblurmovescale", 33136}, + {"setmotionblurturnscale", 33168}, + {"setmotionblurzoomscale", 33169}, + {"viewkick", 33170}, + {"localtoworldcoords", 33171}, + {"getentitynumber", 33172}, + {"getentityvelocity", 33173}, + {"enablegrenadetouchdamage", 33174}, + {"disablegrenadetouchdamage", 33175}, + {"enableaimassist", 33176}, + {"disableaimassist", 33207}, + {"radiusdamage", 33208}, + {"detonate", 33209}, + {"damageconetrace", 33210}, + {"sightconetrace", 33211}, + {"settargetent", 33212}, + {"settargetpos", 33213}, + {"cleartarget", 33214}, + {"setflightmodedirect", 33215}, + {"setflightmodetop", 33216}, + {"getlightintensity", 33217}, + {"setlightintensity", 33218}, + {"isragdoll", 33219}, + {"setmovespeedscale", 33220}, + {"cameralinkto", 33221}, + {"cameraunlink", 33222}, + {"controlslinkto", 33251}, + {"controlsunlink", 33252}, + {"makevehiclesolidcapsule", 33253}, + {"makevehiclesolidsphere", 33254}, + {"remotecontrolvehicle", 33256}, + {"remotecontrolvehicleoff", 33257}, + {"isfiringvehicleturret", 33258}, + {"drivevehicleandcontrolturret", 33259}, + {"drivevehicleandcontrolturretoff", 33260}, + {"getplayersetting", 33261}, + {"getlocalplayerprofiledata", 33262}, + {"setlocalplayerprofiledata", 33263}, + {"remotecamerasoundscapeon", 33264}, + {"remotecamerasoundscapeoff", 33265}, + {"radarjamon", 33266}, + {"radarjamoff", 33267}, + {"setmotiontrackervisible", 33268}, + {"getmotiontrackervisible", 33269}, + {"circle", 33270}, + {"getpointinbounds", 33271}, + {"transfermarkstonewscriptmodel", 33272}, + {"setwatersheeting", 33273}, + {"setweaponhudiconoverride", 33274}, + {"getweaponhudiconoverride", 33275}, + {"setempjammed", 33276}, + {"playersetexpfog", 33277}, + {"isitemunlocked", 33278}, + {"getplayerdata", 33279}, + {"setplayerdata", 33306}, + + // Vehicle stuff + {"teleport", 0x824C}, + {"attachpath", 0x824D}, + {"getattachpos", 0x824E}, + {"startpath", 0x824F}, + {"setswitchnode", 0x8250}, + {"setwaitspeed", 0x8251}, + {"finishdamage", 0x8252}, + {"setspeed", 0x8253}, + {"setspeedimmediate", 0x8254}, + {"setwaitspeed", 0x8251}, + + {"setlookatent", 0x8237}, + {"clearlookatent", 0x8238}, + + {"setvehgoalpos", 33325}, + {"setturningability", 33381}, + + // some entity (script_model) stuff + {"moveto", 33399}, + {"movex", 33400}, + {"movey", 33401}, + {"movez", 33402}, + {"movegravity", 33403}, + {"moveslide", 33404}, + {"stopmoveslide", 33405}, + {"rotateto", 33406}, + {"rotatepitch", 33407}, + {"rotateyaw", 33408}, + {"rotateroll", 33409}, + {"addpitch", 33410}, + {"addyaw", 33411}, + {"addroll", 33412}, + {"vibrate", 33413}, + {"rotatevelocity", 33414}, + {"solid", 33415}, + {"notsolid", 33416}, + {"setcandamage", 33417}, + {"setcanradiusdamage", 33418}, + {"physicslaunchclient", 33419}, + {"physicslaunchserver", 33351}, + {"physicslaunchserveritem", 33352}, + {"clonebrushmodeltoscriptmodel", 33353}, + {"scriptmodelplayanim", 33354}, + {"scriptmodelclearanim", 33355}, + + // varied ent/player script commands + {"getorigin", 32910}, + {"useby", 32914}, + {"playsound", 32915}, + {"playsoundasmaster", 32878}, + {"playsoundtoteam", 32771}, + {"playsoundtoplayer", 32772}, + {"playloopsound", 32879}, + {"getnormalhealth", 32884}, + {"setnormalhealth", 32844}, + {"show", 32847}, + {"hide", 32848}, + {"playerhide", 32773}, + {"showtoplayer", 32774}, + {"enableplayeruse", 32775}, + {"disableplayeruse", 32776}, + {"setscriptmoverkillcam", 33546}, + {"makescrambler", 32777}, + {"makeportableradar", 32778}, + {"maketrophysystem", 32779}, + {"setmode", 32864}, + {"getmode", 32865}, + {"placespawnpoint", 32780}, + {"setteamfortrigger", 32781}, + {"clientclaimtrigger", 32782}, + {"clientreleasetrigger", 32783}, + {"releaseclaimedtrigger", 32784}, + {"isusingonlinedataoffline", 32785}, + {"getrestedtime", 32786}, + {"sendleaderboards", 32787}, + {"logstring", 32800}, + {"isonladder", 32788}, + {"startragdoll", 32798}, + {"getcorpseanim", 32789}, + {"playerforcedeathanim", 32790}, + {"startac130", 33543}, + {"stopac130", 33544}, + }; + + std::map global_function_map = + { + // global stuff #1 + {"iprintln", 362}, + {"iprintlnbold", 363}, + {"logstring", 364}, + {"getent", 365}, + {"getentarray", 366}, + {"spawnplane", 367}, + {"spawnstruct", 368}, + {"spawnhelicopter", 369}, + {"isalive", 370}, + {"isspawner", 371}, + {"createattractorent", 372}, + {"createattractororigin", 373}, + {"createrepulsorent", 374}, + {"createrepulsororigin", 375}, + {"deleteattractor", 376}, + {"playsoundatpos", 377}, + {"newhudelem", 378}, + {"newclienthudelem", 379}, + {"newteamhudelem", 380}, + {"resettimeout", 381}, + {"precachefxteamthermal", 382}, + {"isplayer", 383}, + {"isplayernumber", 384}, + {"setsunlight", 57}, + {"resetsunlight", 58}, + {"setwinningplayer", 385}, + {"setwinningteam", 311}, + {"announcement", 312}, + {"clientannouncement", 313}, + {"getteamscore", 314}, + {"setteamscore", 315}, + {"setclientnamemode", 316}, + {"updateclientnames", 317}, + {"getteamplayersalive", 318}, + {"logprint", 319}, + {"worldentnumber", 320}, + {"obituary", 321}, + {"positionwouldtelefrag", 322}, + {"canspawn", 323}, + {"getstarttime", 324}, + {"precachestatusicon", 325}, + {"precacheminimapicon", 327}, + {"precachempanim", 328}, + {"restart", 329}, + {"exitlevel", 330}, + {"addtestclient", 331}, + {"makedvarserverinfo", 332}, + {"setarchive", 333}, + {"allclientsprint", 334}, + {"clientprint", 335}, + {"mapexists", 336}, + {"isvalidgametype", 337}, + {"matchend", 338}, + {"setplayerteamrank", 339}, + {"endparty", 340}, + {"setteamradar", 341}, + {"getteamradar", 342}, + {"setteamradarstrength", 343}, + {"getteamradarstrength", 344}, + {"getuavstrengthmin", 345}, + {"getuavstrengthmax", 262}, + {"getuavstrengthlevelneutral", 263}, + {"getuavstrengthlevelshowenemyfastsweep", 264}, + {"getuavstrengthlevelshowenemydirectional", 265}, + {"blockteamradar", 266}, + {"unblockteamradar", 267}, + {"isteamradarblocked", 268}, + {"getassignedteam", 269}, + {"setmatchdata", 270}, + {"getmatchdata", 271}, + {"sendmatchdata", 272}, + {"clearmatchdata", 273}, + {"setmatchdatadef", 274}, + {"setmatchclientip", 275}, + {"setmatchdataid", 276}, + {"setclientmatchdata", 277}, + {"getclientmatchdata", 278}, + {"setclientmatchdatadef", 279}, + {"sendclientmatchdata", 280}, + {"getbuildversion", 281}, + {"getbuildnumber", 282}, + {"getsystemtime", 283}, + {"getmatchrulesdata", 284}, + {"isusingmatchrulesdata", 285}, + {"kick", 286}, + {"issplitscreen", 287}, + {"setmapcenter", 288}, + {"setgameendtime", 289}, + {"visionsetnaked", 290}, + {"visionsetnight", 291}, + {"visionsetmissilecam", 292}, + {"visionsetthermal", 217}, + {"visionsetpain", 218}, + {"endlobby", 219}, + {"ambience", 220}, + {"getmapcustom", 221}, + {"updateskill", 222}, + {"spawnsighttrace", 223}, + + // global stuff #2 + {"setprintchannel", 14}, + {"print", 15}, + {"println", 16}, + {"print3d", 17}, + {"line", 18}, + {"spawnturret", 19}, + {"canspawnturret", 20}, + {"assert", 21}, + {"assertex", 38}, + {"assertmsg", 39}, + {"isdefined", 40}, + {"isstring", 41}, + {"setdvar", 42}, + {"setdynamicdvar", 43}, + {"setdvarifuninitialized", 44}, + {"setdevdvar", 45}, + {"setdevdvarifuninitialized", 46}, + {"getdvar", 47}, + {"getdvarint", 48}, + {"getdvarfloat", 49}, + {"getdvarvector", 50}, + {"gettime", 51}, + {"getentbynum", 52}, + {"getweaponmodel", 53}, + {"getweaponhidetags", 81}, + {"getanimlength", 82}, + {"animhasnotetrack", 83}, + {"getnotetracktimes", 84}, + {"spawn", 85}, + {"spawnloopsound", 86}, + {"bullettrace", 87}, + {"bullettracepassed", 88}, + {"sighttracepassed", 116}, + {"physicstrace", 117}, + {"physicstracenormal", 118}, + {"playerphysicstrace", 119}, + {"getgroundposition", 120}, + {"getmovedelta", 121}, + {"getangledelta", 122}, + {"getnorthyaw", 123}, + {"setnorthyaw", 150}, + {"setslowmotion", 151}, + {"randomint", 152}, + {"randomfloat", 153}, + {"randomintrange", 154}, + {"randomfloatrange", 155}, + {"sin", 156}, + {"cos", 157}, + {"tan", 158}, + {"asin", 159}, + {"acos", 160}, + {"atan", 161}, + {"int", 162}, + {"float", 163}, + {"abs", 164}, + {"min", 165}, + {"max", 198}, + {"floor", 199}, + {"ceil", 200}, + {"exp", 201}, + {"log", 202}, + {"sqrt", 203}, + {"squared", 204}, + {"clamp", 205}, + {"angleclamp", 206}, + {"angleclamp180", 207}, + {"vectorfromlinetopoint", 208}, + {"pointonsegmentnearesttopoint", 209}, + {"distance", 210}, + {"distance2d", 211}, + {"distancesquared", 212}, + {"length", 213}, + {"lengthsquared", 214}, + {"closer", 215}, + {"vectordot", 216}, + {"vectornormalize", 246}, + {"vectortoangles", 247}, + {"vectortoyaw", 248}, + {"vectorlerp", 249}, + {"anglestoup", 250}, + {"anglestoright", 251}, + {"anglestoforward", 252}, + {"combineangles", 253}, + {"transformmove", 254}, + {"issubstr", 255}, + {"isendstr", 256}, + {"getsubstr", 257}, + {"tolower", 258}, + {"strtok", 259}, + {"stricmp", 260}, + {"ambientplay", 261}, + {"ambientstop", 293}, + {"precachemodel", 294}, + {"precacheshellshock", 295}, + {"precacheitem", 296}, + {"precacheshader", 297}, + {"precachestring", 298}, + {"precachemenu", 299}, + {"precacherumble", 300}, + {"precachelocationselector", 301}, + {"precacheleaderboards", 302}, + {"precacheheadicon", 326}, + {"loadfx", 303}, + {"playfx", 304}, + {"playfxontag", 305}, + {"stopfxontag", 306}, + {"playloopedfx", 307}, + {"spawnfx", 308}, + {"triggerfx", 309}, + {"playfxontagforclients", 310}, + {"physicsexplosionsphere", 346}, + {"physicsexplosioncylinder", 347}, + {"physicsjolt", 348}, + {"physicsjitter", 349}, + {"setexpfog", 350}, + {"isexplosivedamagemod", 351}, + {"radiusdamage", 352}, + {"setplayerignoreradiusdamage", 353}, + {"glassradiusdamage", 354}, + {"earthquake", 355}, + {"getnumparts", 356}, + {"getpartname", 386}, + {"weaponfiretime", 387}, + {"weaponclipsize", 388}, + {"weaponisauto", 389}, + {"weaponissemiauto", 390}, + {"weaponisboltaction", 391}, + {"weaponinheritsperks", 392}, + {"weaponburstcount", 393}, + {"weapontype", 394}, + {"weaponclass", 395}, + {"weaponinventorytype", 437}, + {"weaponstartammo", 438}, + {"weaponmaxammo", 439}, + {"weaponaltweaponname", 440}, + {"isweaponcliponly", 441}, + {"isweapondetonationtimed", 442}, + {"weaponhasthermalscope", 443}, + {"getvehiclenode", 444}, + {"getvehiclenodearray", 445}, + {"getallvehiclenodes", 446}, + {"getnumvehicles", 447}, + {"precachevehicle", 448}, + {"spawnvehicle", 449}, + {"getarray", 450}, + {"getspawnerarray", 408}, + {"playrumbleonposition", 409}, + {"playrumblelooponposition", 410}, + {"stopallrumbles", 411}, + {"soundexists", 412}, + {"openfile", 413}, + {"closefile", 414}, + {"fprintln", 415}, + {"fprintfields", 416}, + {"freadln", 417}, + {"fgetarg", 418}, + {"setminimap", 419}, + {"setthermalbodymaterial", 420}, + {"getarraykeys", 421}, + {"getfirstarraykey", 422}, + {"getnextarraykey", 396}, + {"sortbydistance", 397}, + {"tablelookup", 398}, + {"tablelookupbyrow", 399}, + {"tablelookupistring", 400}, + {"tablelookupistringbyrow", 401}, + {"tablelookuprownum", 402}, + {"getmissileowner", 403}, + {"magicbullet", 404}, + {"getweaponflashtagname", 405}, + {"averagepoint", 406}, + {"averagenormal", 407}, + {"getglass", 423}, + {"getglassarray", 424}, + {"getglassorigin", 425}, + {"isglassdestroyed", 426}, + {"destroyglass", 427}, + {"deleteglass", 428}, + {"getentchannelscount", 429}, + + // objective + {"objective_add", 431}, + {"objective_delete", 432}, + {"objective_state", 433}, + {"objective_icon", 434}, + {"objective_position", 435}, + {"objective_current", 436}, + {"objective_onentity", 357}, + {"objective_team", 358}, + {"objective_player", 359}, + {"objective_playerteam", 360}, + {"objective_playerenemyteam", 361}, + }; +} diff --git a/src/game/scripting/functions.hpp b/src/game/scripting/functions.hpp index 046fe78..d9e6174 100644 --- a/src/game/scripting/functions.hpp +++ b/src/game/scripting/functions.hpp @@ -1,10 +1,7 @@ #pragma once -namespace game +namespace game::scripting { - namespace scripting - { - extern std::map instance_function_map; - extern std::map global_function_map; - } + extern std::map instance_function_map; + extern std::map global_function_map; } diff --git a/src/game/scripting/parameters.cpp b/src/game/scripting/parameters.cpp index 5f55c92..f516083 100644 --- a/src/game/scripting/parameters.cpp +++ b/src/game/scripting/parameters.cpp @@ -1,153 +1,150 @@ #include "std_include.hpp" #include "context.hpp" -namespace game +namespace game::scripting { - namespace scripting + parameters::parameters(context* context) : context_(context) { - parameters::parameters(context* context) : context_(context) + } + + chaiscript::Boxed_Value parameters::load(const native::VariableValue value) const + { + if (value.type == native::SCRIPT_STRING) { + const std::string string = native::SL_ConvertToString(value.u.stringValue); + return chaiscript::var(string); + } + else if (value.type == native::SCRIPT_FLOAT) + { + return chaiscript::var(value.u.floatValue); + } + else if (value.type == native::SCRIPT_INTEGER) + { + return chaiscript::var(value.u.intValue); + } + else if (value.type == native::SCRIPT_OBJECT) + { + return chaiscript::var(entity(this->context_, value.u.entityId)); + } + else if (value.type == native::SCRIPT_VECTOR) + { + std::vector values; + values.push_back(chaiscript::var(value.u.vectorValue[0])); + values.push_back(chaiscript::var(value.u.vectorValue[1])); + values.push_back(chaiscript::var(value.u.vectorValue[2])); + + return chaiscript::var(values); } - chaiscript::Boxed_Value parameters::load(const native::VariableValue value) const + return {}; + } + + void parameters::push(const chaiscript::Boxed_Value& value) const + { + if (native::scr_VmPub->outparamcount) { - if (value.type == native::SCRIPT_STRING) - { - const std::string string = native::SL_ConvertToString(value.u.stringValue); - return chaiscript::var(string); - } - else if (value.type == native::SCRIPT_FLOAT) - { - return chaiscript::var(value.u.floatValue); - } - else if (value.type == native::SCRIPT_INTEGER) - { - return chaiscript::var(value.u.intValue); - } - else if (value.type == native::SCRIPT_OBJECT) - { - return chaiscript::var(entity(this->context_, value.u.entityId)); - } - else if (value.type == native::SCRIPT_VECTOR) - { - std::vector values; - values.push_back(chaiscript::var(value.u.vectorValue[0])); - values.push_back(chaiscript::var(value.u.vectorValue[1])); - values.push_back(chaiscript::var(value.u.vectorValue[2])); - - return chaiscript::var(values); - } - - return {}; + native::Scr_ClearOutParams(); } - void parameters::push(const chaiscript::Boxed_Value& value) const + if (native::scr_VmPub->top == native::scr_VmPub->maxstack) { - if (native::scr_VmPub->outparamcount) + throw std::runtime_error("Internal script stack overflow"); + } + + native::VariableValue* value_ptr = ++native::scr_VmPub->top; + ++native::scr_VmPub->inparamcount; + + value_ptr->type = native::SCRIPT_NONE; + value_ptr->u.intValue = 0; + + if (value.get_type_info() == typeid(float)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_FLOAT; + value_ptr->u.floatValue = real_value; + } + else if (value.get_type_info() == typeid(double)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_FLOAT; + value_ptr->u.floatValue = static_cast(real_value); + } + else if (value.get_type_info() == typeid(int)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_INTEGER; + value_ptr->u.intValue = real_value; + } + else if (value.get_type_info() == typeid(bool)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_INTEGER; + value_ptr->u.intValue = real_value; + } + else if (value.get_type_info() == typeid(entity)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_OBJECT; + value_ptr->u.entityId = real_value.get_entity_id(); + + game::native::AddRefToValue(value_ptr); + } + else if (value.get_type_info() == typeid(std::string)) + { + const auto real_value = this->context_->get_chai()->boxed_cast(value); + value_ptr->type = native::SCRIPT_STRING; + value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0); + } + else if (value.get_type_info() == typeid(std::vector)) + { + float values[3]; + const auto real_value = this->context_->get_chai()->boxed_cast + >(value); + if (real_value.size() != 3) { - native::Scr_ClearOutParams(); + throw std::runtime_error("Invalid vector length. Size must be exactly 3"); } - if (native::scr_VmPub->top == native::scr_VmPub->maxstack) + const auto unbox_float = [&real_value, this](const size_t index) -> float { - throw std::runtime_error("Internal script stack overflow"); - } - - native::VariableValue* value_ptr = ++native::scr_VmPub->top; - ++native::scr_VmPub->inparamcount; - - value_ptr->type = native::SCRIPT_NONE; - value_ptr->u.intValue = 0; - - if (value.get_type_info() == typeid(float)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_FLOAT; - value_ptr->u.floatValue = real_value; - } - else if (value.get_type_info() == typeid(double)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_FLOAT; - value_ptr->u.floatValue = static_cast(real_value); - } - else if (value.get_type_info() == typeid(int)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_INTEGER; - value_ptr->u.intValue = real_value; - } - else if (value.get_type_info() == typeid(bool)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_INTEGER; - value_ptr->u.intValue = real_value; - } - else if (value.get_type_info() == typeid(entity)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_OBJECT; - value_ptr->u.entityId = real_value.get_entity_id(); - - game::native::AddRefToValue(value_ptr); - } - else if (value.get_type_info() == typeid(std::string)) - { - const auto real_value = this->context_->get_chai()->boxed_cast(value); - value_ptr->type = native::SCRIPT_STRING; - value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0); - } - else if (value.get_type_info() == typeid(std::vector)) - { - float values[3]; - const auto real_value = this->context_->get_chai()->boxed_cast - >(value); - if (real_value.size() != 3) + const auto value = real_value[index]; + if (value.get_type_info() == typeid(float)) { - throw std::runtime_error("Invalid vector length. Size must be exactly 3"); + return this->context_->get_chai()->boxed_cast(value); + } + if (value.get_type_info() == typeid(double)) + { + return float(this->context_->get_chai()->boxed_cast(value)); + } + if (value.get_type_info() == typeid(int)) + { + return float(this->context_->get_chai()->boxed_cast(value)); } - const auto unbox_float = [&real_value, this](const size_t index) -> float - { - const auto value = real_value[index]; - if (value.get_type_info() == typeid(float)) - { - return this->context_->get_chai()->boxed_cast(value); - } - if (value.get_type_info() == typeid(double)) - { - return float(this->context_->get_chai()->boxed_cast(value)); - } - if (value.get_type_info() == typeid(int)) - { - return float(this->context_->get_chai()->boxed_cast(value)); - } + throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number"); + }; - throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number"); - }; + values[0] = unbox_float(0); + values[1] = unbox_float(1); + values[2] = unbox_float(2); - values[0] = unbox_float(0); - values[1] = unbox_float(1); - values[2] = unbox_float(2); - - value_ptr->type = native::SCRIPT_VECTOR; - value_ptr->u.vectorValue = native::Scr_AllocVector(values); - } - else - { - throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'"); - } + value_ptr->type = native::SCRIPT_VECTOR; + value_ptr->u.vectorValue = native::Scr_AllocVector(values); } - - chaiscript::Boxed_Value parameters::get_return_value() const + else { - if (native::scr_VmPub->inparamcount == 0) return {}; - - native::Scr_ClearOutParams(); - native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; - native::scr_VmPub->inparamcount = 0; - - return this->load(native::scr_VmPub->top[1 - native::scr_VmPub->outparamcount]); + throw std::runtime_error("Unable to unbox value of type '" + value.get_type_info().bare_name() + "'"); } } + + chaiscript::Boxed_Value parameters::get_return_value() const + { + if (native::scr_VmPub->inparamcount == 0) return {}; + + native::Scr_ClearOutParams(); + native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount; + native::scr_VmPub->inparamcount = 0; + + return this->load(native::scr_VmPub->top[1 - native::scr_VmPub->outparamcount]); + } } diff --git a/src/game/scripting/parameters.hpp b/src/game/scripting/parameters.hpp index efcfd8c..244e368 100644 --- a/src/game/scripting/parameters.hpp +++ b/src/game/scripting/parameters.hpp @@ -1,23 +1,20 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - class context; - - class parameters final - { - public: - explicit parameters(context* context); - - void push(const chaiscript::Boxed_Value& value) const; - chaiscript::Boxed_Value load(native::VariableValue value) const; - - chaiscript::Boxed_Value get_return_value() const; - private: - context* context_; - }; - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting +{ + class context; + + class parameters final + { + public: + explicit parameters(context* context); + + void push(const chaiscript::Boxed_Value& value) const; + chaiscript::Boxed_Value load(native::VariableValue value) const; + + chaiscript::Boxed_Value get_return_value() const; + private: + context* context_; + }; +} diff --git a/src/game/scripting/safe_executer.cpp b/src/game/scripting/safe_executer.cpp index 18c4567..ed71913 100644 --- a/src/game/scripting/safe_executer.cpp +++ b/src/game/scripting/safe_executer.cpp @@ -1,63 +1,59 @@ -#include "std_include.hpp" -#include "safe_executer.hpp" - -#pragma warning(push) -#pragma warning(disable: 4611) -namespace game -{ - namespace scripting - { - namespace safe_executer - { - static_assert(sizeof(jmp_buf) == 64); - - bool call(const native::scr_call_t function, const native::scr_entref_t entref) - { - *native::g_script_error_level += 1; - if (setjmp(native::g_script_error[*native::g_script_error_level])) - { - *native::g_script_error_level -= 1; - return false; - } - - function(entref.val); - - *native::g_script_error_level -= 1; - return true; - } - - bool set_entity_field(const native::scr_entref_t entref, const int offset) - { - *native::g_script_error_level += 1; - if (setjmp(native::g_script_error[*native::g_script_error_level])) - { - *native::g_script_error_level -= 1; - return false; - } - - native::Scr_SetObjectField(entref.raw.classnum, entref.raw.entnum, offset); - - *native::g_script_error_level -= 1; - return true; - } - - bool get_entity_field(const native::scr_entref_t entref, const int offset, native::VariableValue* value) - { - *native::g_script_error_level += 1; - if (setjmp(native::g_script_error[*native::g_script_error_level])) - { - value->type = native::SCRIPT_NONE; - value->u.intValue = 0; - *native::g_script_error_level -= 1; - return false; - } - - *value = native::GetEntityFieldValue(entref.raw.classnum, entref.raw.entnum, offset); - - *native::g_script_error_level -= 1; - return true; - } - } - } -} -#pragma warning(pop) +#include "std_include.hpp" +#include "safe_executer.hpp" + +#pragma warning(push) +#pragma warning(disable: 4611) + +namespace game::scripting::safe_executer +{ + static_assert(sizeof(jmp_buf) == 64); + + bool call(const native::scr_call_t function, const native::scr_entref_t entref) + { + *native::g_script_error_level += 1; + if (setjmp(native::g_script_error[*native::g_script_error_level])) + { + *native::g_script_error_level -= 1; + return false; + } + + function(entref.val); + + *native::g_script_error_level -= 1; + return true; + } + + bool set_entity_field(const native::scr_entref_t entref, const int offset) + { + *native::g_script_error_level += 1; + if (setjmp(native::g_script_error[*native::g_script_error_level])) + { + *native::g_script_error_level -= 1; + return false; + } + + native::Scr_SetObjectField(entref.raw.classnum, entref.raw.entnum, offset); + + *native::g_script_error_level -= 1; + return true; + } + + bool get_entity_field(const native::scr_entref_t entref, const int offset, native::VariableValue* value) + { + *native::g_script_error_level += 1; + if (setjmp(native::g_script_error[*native::g_script_error_level])) + { + value->type = native::SCRIPT_NONE; + value->u.intValue = 0; + *native::g_script_error_level -= 1; + return false; + } + + *value = native::GetEntityFieldValue(entref.raw.classnum, entref.raw.entnum, offset); + + *native::g_script_error_level -= 1; + return true; + } +} + +#pragma warning(pop) diff --git a/src/game/scripting/safe_executer.hpp b/src/game/scripting/safe_executer.hpp index 89ae335..0579f66 100644 --- a/src/game/scripting/safe_executer.hpp +++ b/src/game/scripting/safe_executer.hpp @@ -1,15 +1,9 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - namespace safe_executer - { - bool call(const native::scr_call_t function, const native::scr_entref_t entref); - bool set_entity_field(const native::scr_entref_t entref, const int offset); - bool get_entity_field(const native::scr_entref_t entref, const int offset, native::VariableValue* value); - } - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting::safe_executer +{ + bool call(const native::scr_call_t function, const native::scr_entref_t entref); + bool set_entity_field(const native::scr_entref_t entref, const int offset); + bool get_entity_field(const native::scr_entref_t entref, const int offset, native::VariableValue* value); +} diff --git a/src/game/scripting/scheduler.cpp b/src/game/scripting/scheduler.cpp index c4aea8f..cd22b36 100644 --- a/src/game/scripting/scheduler.cpp +++ b/src/game/scripting/scheduler.cpp @@ -1,98 +1,95 @@ #include "std_include.hpp" #include "context.hpp" -namespace game +namespace game::scripting { - namespace scripting + scheduler::scheduler(context* context) : context_(context) { - scheduler::scheduler(context* context) : context_(context) + const auto chai = this->context_->get_chai(); + + chai->add(chaiscript::user_type(), "_task_handle"); + chai->add(chaiscript::constructor(), "_task_handle"); + chai->add(chaiscript::constructor(), "_task_handle"); + + chai->add(chaiscript::fun([](task_handle& lhs, const task_handle& rhs) -> task_handle& { - const auto chai = this->context_->get_chai(); + return lhs = rhs; + }), "="); - chai->add(chaiscript::user_type(), "_task_handle"); - chai->add(chaiscript::constructor(), "_task_handle"); - chai->add(chaiscript::constructor(), "_task_handle"); + chai->add(chaiscript::fun( + [this](const std::function& callback, const long long milliseconds) -> task_handle + { + return this->add(callback, milliseconds, true); + }), "setTimeout"); - chai->add(chaiscript::fun([](task_handle& lhs, const task_handle& rhs) -> task_handle& + chai->add(chaiscript::fun( + [this](const std::function& callback, const long long milliseconds) -> task_handle + { + return this->add(callback, milliseconds, false); + }), "setInterval"); + + const auto clear = [this](const task_handle& handle) + { + this->remove(handle); + }; + + chai->add(chaiscript::fun(clear), "clear"); + chai->add(chaiscript::fun(clear), "clearTimeout"); + chai->add(chaiscript::fun(clear), "clearInterval"); + } + + void scheduler::run_frame() + { + for (auto task : this->tasks_) + { + const auto now = std::chrono::steady_clock::now(); + if ((now - task->last_execution) > task->delay) { - return lhs = rhs; - }), "="); - - chai->add(chaiscript::fun( - [this](const std::function& callback, const long long milliseconds) -> task_handle - { - return this->add(callback, milliseconds, true); - }), "setTimeout"); - - chai->add(chaiscript::fun( - [this](const std::function& callback, const long long milliseconds) -> task_handle - { - return this->add(callback, milliseconds, false); - }), "setInterval"); - - const auto clear = [this](const task_handle& handle) - { - this->remove(handle); - }; - - chai->add(chaiscript::fun(clear), "clear"); - chai->add(chaiscript::fun(clear), "clearTimeout"); - chai->add(chaiscript::fun(clear), "clearInterval"); - } - - void scheduler::run_frame() - { - for (auto task : this->tasks_) - { - const auto now = std::chrono::steady_clock::now(); - if ((now - task->last_execution) > task->delay) - { - task->last_execution = now; - if (task->is_volatile) - { - this->tasks_.remove(task); - } - - task->callback(); - } - } - } - - void scheduler::clear() - { - this->tasks_.clear(); - } - - task_handle scheduler::add(const std::function& callback, const long long milliseconds, - const bool is_volatile) - { - return this->add(callback, std::chrono::milliseconds(milliseconds), is_volatile); - } - - task_handle scheduler::add(const std::function& callback, const std::chrono::milliseconds delay, - const bool is_volatile) - { - task task; - task.is_volatile = is_volatile; - task.callback = callback; - task.delay = delay; - task.last_execution = std::chrono::steady_clock::now(); - task.id = ++this->current_task_id_; - - this->tasks_.add(task); - - return {task.id}; - } - - void scheduler::remove(const task_handle& handle) - { - for (auto task : this->tasks_) - { - if (task->id == handle.id) + task->last_execution = now; + if (task->is_volatile) { this->tasks_.remove(task); - break; } + + task->callback(); + } + } + } + + void scheduler::clear() + { + this->tasks_.clear(); + } + + task_handle scheduler::add(const std::function& callback, const long long milliseconds, + const bool is_volatile) + { + return this->add(callback, std::chrono::milliseconds(milliseconds), is_volatile); + } + + task_handle scheduler::add(const std::function& callback, const std::chrono::milliseconds delay, + const bool is_volatile) + { + task task; + task.is_volatile = is_volatile; + task.callback = callback; + task.delay = delay; + task.last_execution = std::chrono::steady_clock::now(); + task.id = ++this->current_task_id_; + + this->tasks_.add(task); + + return {task.id}; + } + + void scheduler::remove(const task_handle& handle) + { + for (auto task : this->tasks_) + { + if (task->id == handle.id) + { + this->tasks_.remove(task); + break; } } } diff --git a/src/game/scripting/scheduler.hpp b/src/game/scripting/scheduler.hpp index 7370d6d..e92348e 100644 --- a/src/game/scripting/scheduler.hpp +++ b/src/game/scripting/scheduler.hpp @@ -1,45 +1,42 @@ -#pragma once -#include "utils/concurrent_list.hpp" - -namespace game -{ - namespace scripting - { - class context; - - class task_handle - { - public: - unsigned long long id = 0; - }; - - class task final : public task_handle - { - public: - std::chrono::steady_clock::time_point last_execution{}; - std::function callback{}; - std::chrono::milliseconds delay{}; - bool is_volatile = false; - }; - - class scheduler final - { - public: - explicit scheduler(context* context); - - void run_frame(); - void clear(); - - private: - context* context_; - - utils::concurrent_list tasks_; - std::atomic_int64_t current_task_id_ = 0; - - task_handle add(const std::function& callback, long long milliseconds, bool is_volatile); - task_handle add(const std::function& callback, std::chrono::milliseconds delay, bool is_volatile); - - void remove(const task_handle& handle); - }; - } -} +#pragma once +#include "utils/concurrent_list.hpp" + +namespace game::scripting +{ + class context; + + class task_handle + { + public: + unsigned long long id = 0; + }; + + class task final : public task_handle + { + public: + std::chrono::steady_clock::time_point last_execution{}; + std::function callback{}; + std::chrono::milliseconds delay{}; + bool is_volatile = false; + }; + + class scheduler final + { + public: + explicit scheduler(context* context); + + void run_frame(); + void clear(); + + private: + context* context_; + + utils::concurrent_list tasks_; + std::atomic_int64_t current_task_id_ = 0; + + task_handle add(const std::function& callback, long long milliseconds, bool is_volatile); + task_handle add(const std::function& callback, std::chrono::milliseconds delay, bool is_volatile); + + void remove(const task_handle& handle); + }; +} diff --git a/src/game/scripting/stack_isolation.cpp b/src/game/scripting/stack_isolation.cpp index 117c79d..0fc3d05 100644 --- a/src/game/scripting/stack_isolation.cpp +++ b/src/game/scripting/stack_isolation.cpp @@ -1,30 +1,27 @@ -#include "std_include.hpp" -#include "stack_isolation.hpp" - -namespace game -{ - namespace scripting - { - stack_isolation::stack_isolation() - { - this->in_param_count_ = native::scr_VmPub->inparamcount; - this->out_param_count_ = native::scr_VmPub->outparamcount; - this->top_ = native::scr_VmPub->top; - this->max_stack_ = native::scr_VmPub->maxstack; - - native::scr_VmPub->top = this->stack_; - native::scr_VmPub->maxstack = &this->stack_[ARRAYSIZE(this->stack_) - 1]; - native::scr_VmPub->inparamcount = 0; - native::scr_VmPub->outparamcount = 0; - } - - stack_isolation::~stack_isolation() - { - native::Scr_ClearOutParams(); - native::scr_VmPub->inparamcount = this->in_param_count_; - native::scr_VmPub->outparamcount = this->out_param_count_; - native::scr_VmPub->top = this->top_; - native::scr_VmPub->maxstack = this->max_stack_; - } - } -} +#include "std_include.hpp" +#include "stack_isolation.hpp" + +namespace game::scripting +{ + stack_isolation::stack_isolation() + { + this->in_param_count_ = native::scr_VmPub->inparamcount; + this->out_param_count_ = native::scr_VmPub->outparamcount; + this->top_ = native::scr_VmPub->top; + this->max_stack_ = native::scr_VmPub->maxstack; + + native::scr_VmPub->top = this->stack_; + native::scr_VmPub->maxstack = &this->stack_[ARRAYSIZE(this->stack_) - 1]; + native::scr_VmPub->inparamcount = 0; + native::scr_VmPub->outparamcount = 0; + } + + stack_isolation::~stack_isolation() + { + native::Scr_ClearOutParams(); + native::scr_VmPub->inparamcount = this->in_param_count_; + native::scr_VmPub->outparamcount = this->out_param_count_; + native::scr_VmPub->top = this->top_; + native::scr_VmPub->maxstack = this->max_stack_; + } +} diff --git a/src/game/scripting/stack_isolation.hpp b/src/game/scripting/stack_isolation.hpp index 35777f5..0241599 100644 --- a/src/game/scripting/stack_isolation.hpp +++ b/src/game/scripting/stack_isolation.hpp @@ -1,23 +1,20 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - class stack_isolation final - { - public: - stack_isolation(); - ~stack_isolation(); - - private: - native::VariableValue stack_[512]{}; - - native::VariableValue* max_stack_; - native::VariableValue* top_; - unsigned int in_param_count_; - unsigned int out_param_count_; - }; - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting +{ + class stack_isolation final + { + public: + stack_isolation(); + ~stack_isolation(); + + private: + native::VariableValue stack_[512]{}; + + native::VariableValue* max_stack_; + native::VariableValue* top_; + unsigned int in_param_count_; + unsigned int out_param_count_; + }; +} diff --git a/src/game/scripting/variable_value.cpp b/src/game/scripting/variable_value.cpp index 77eaf8d..8b798c7 100644 --- a/src/game/scripting/variable_value.cpp +++ b/src/game/scripting/variable_value.cpp @@ -1,23 +1,20 @@ -#include "std_include.hpp" -#include "variable_value.hpp" - -namespace game -{ - namespace scripting - { - variable_value::variable_value(native::VariableValue value) : value_(value) - { - native::AddRefToValue(&value); - } - - variable_value::~variable_value() - { - native::RemoveRefToValue(this->value_.type, this->value_.u); - } - - variable_value::operator native::VariableValue() const - { - return this->value_; - } - } -} +#include "std_include.hpp" +#include "variable_value.hpp" + +namespace game::scripting +{ + variable_value::variable_value(native::VariableValue value) : value_(value) + { + native::AddRefToValue(&value); + } + + variable_value::~variable_value() + { + native::RemoveRefToValue(this->value_.type, this->value_.u); + } + + variable_value::operator native::VariableValue() const + { + return this->value_; + } +} diff --git a/src/game/scripting/variable_value.hpp b/src/game/scripting/variable_value.hpp index 2a906bd..fb2a8c6 100644 --- a/src/game/scripting/variable_value.hpp +++ b/src/game/scripting/variable_value.hpp @@ -1,20 +1,17 @@ -#pragma once -#include "game/game.hpp" - -namespace game -{ - namespace scripting - { - class variable_value final - { - public: - explicit variable_value(native::VariableValue value); - ~variable_value(); - - explicit operator native::VariableValue() const; - - private: - native::VariableValue value_; - }; - } -} +#pragma once +#include "game/game.hpp" + +namespace game::scripting +{ + class variable_value final + { + public: + explicit variable_value(native::VariableValue value); + ~variable_value(); + + explicit operator native::VariableValue() const; + + private: + native::VariableValue value_; + }; +} diff --git a/src/module/dw.cpp b/src/module/dw.cpp index ba45e74..7985f58 100644 --- a/src/module/dw.cpp +++ b/src/module/dw.cpp @@ -254,7 +254,7 @@ namespace demonware auto queue = datagram_packets_.find(s); if (queue != datagram_packets_.end()) { - const bool blocking = is_blocking_socket(s, UDP_BLOCKING); + const auto blocking = is_blocking_socket(s, UDP_BLOCKING); lock.unlock(); while (blocking && queue->second.empty()) diff --git a/src/resources/settings.html b/src/resources/settings.html index cca18eb..1573442 100644 --- a/src/resources/settings.html +++ b/src/resources/settings.html @@ -37,7 +37,7 @@
-

No settings, yet!

+

No settings, yet!

diff --git a/src/utils/compression.cpp b/src/utils/compression.cpp index ce507bf..e04add9 100644 --- a/src/utils/compression.cpp +++ b/src/utils/compression.cpp @@ -1,73 +1,70 @@ -#include -#include "memory.hpp" -#include "compression.hpp" - -namespace utils -{ - namespace compression - { - std::string zlib::compress(const std::string& data) - { - memory::allocator allocator; - unsigned long length = (data.size() * 2); - if (!length) length = 2; - - if (length < 100) length *= 10; - - const auto buffer = allocator.allocate_array(length); - if (compress2(reinterpret_cast(buffer), &length, - reinterpret_cast(const_cast(data.data())), data.size(), - Z_BEST_COMPRESSION) != Z_OK) - { - return {}; - } - - return std::string(buffer, length); - } - - std::string zlib::decompress(const std::string& data) - { - z_stream stream; - ZeroMemory(&stream, sizeof(stream)); - std::string buffer; - - if (inflateInit(&stream) != Z_OK) - { - return {}; - } - - int ret; - memory::allocator allocator; - - const auto dest = allocator.allocate_array(CHUNK); - auto data_ptr = data.data(); - - do - { - stream.avail_in = std::min(static_cast(CHUNK), data.size() - (data_ptr - data.data())); - stream.next_in = reinterpret_cast(data_ptr); - data_ptr += stream.avail_in; - - do - { - stream.avail_out = CHUNK; - stream.next_out = dest; - - ret = inflate(&stream, Z_NO_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateEnd(&stream); - return {}; - } - - buffer.append(reinterpret_cast(dest), CHUNK - stream.avail_out); - } - while (stream.avail_out == 0); - } - while (ret != Z_STREAM_END); - - inflateEnd(&stream); - return buffer; - } - } -} +#include +#include "memory.hpp" +#include "compression.hpp" + +namespace utils::compression +{ + std::string zlib::compress(const std::string& data) + { + memory::allocator allocator; + unsigned long length = (data.size() * 2); + if (!length) length = 2; + + if (length < 100) length *= 10; + + const auto buffer = allocator.allocate_array(length); + if (compress2(reinterpret_cast(buffer), &length, + reinterpret_cast(const_cast(data.data())), data.size(), + Z_BEST_COMPRESSION) != Z_OK) + { + return {}; + } + + return std::string(buffer, length); + } + + std::string zlib::decompress(const std::string& data) + { + z_stream stream; + ZeroMemory(&stream, sizeof(stream)); + std::string buffer; + + if (inflateInit(&stream) != Z_OK) + { + return {}; + } + + int ret; + memory::allocator allocator; + + const auto dest = allocator.allocate_array(CHUNK); + auto data_ptr = data.data(); + + do + { + stream.avail_in = std::min(static_cast(CHUNK), data.size() - (data_ptr - data.data())); + stream.next_in = reinterpret_cast(data_ptr); + data_ptr += stream.avail_in; + + do + { + stream.avail_out = CHUNK; + stream.next_out = dest; + + ret = inflate(&stream, Z_NO_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateEnd(&stream); + return {}; + } + + buffer.append(reinterpret_cast(dest), CHUNK - stream.avail_out); + } + while (stream.avail_out == 0); + } + while (ret != Z_STREAM_END); + + inflateEnd(&stream); + return buffer; + } +} diff --git a/src/utils/compression.hpp b/src/utils/compression.hpp index 834c8ba..d09ff9e 100644 --- a/src/utils/compression.hpp +++ b/src/utils/compression.hpp @@ -1,16 +1,13 @@ -#pragma once - -#define CHUNK 16384 - -namespace utils -{ - namespace compression - { - class zlib final - { - public: - static std::string compress(const std::string& data); - static std::string decompress(const std::string& data); - }; - }; -} +#pragma once + +#define CHUNK 16384 + +namespace utils::compression +{ + class zlib final + { + public: + static std::string compress(const std::string& data); + static std::string decompress(const std::string& data); + }; +}; diff --git a/src/utils/cryptography.cpp b/src/utils/cryptography.cpp index 180f8a3..79ed280 100644 --- a/src/utils/cryptography.cpp +++ b/src/utils/cryptography.cpp @@ -4,323 +4,320 @@ /// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf -namespace utils +namespace utils::cryptography { - namespace cryptography + ecc::key::key() { - ecc::key::key() + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + + ecc::key::~key() + { + this->free(); + } + + bool ecc::key::is_valid() const + { + return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_))); + } + + ecc_key* ecc::key::get() + { + return &this->key_storage_; + } + + std::string ecc::key::get_public_key() const + { + uint8_t buffer[512] = {0}; + DWORD length = sizeof(buffer); + + if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK) { - ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); - } - - ecc::key::~key() - { - this->free(); - } - - bool ecc::key::is_valid() const - { - return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_))); - } - - ecc_key* ecc::key::get() - { - return &this->key_storage_; - } - - std::string ecc::key::get_public_key() const - { - uint8_t buffer[512] = {0}; - DWORD length = sizeof(buffer); - - if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK) - { - return std::string(reinterpret_cast(buffer), length); - } - - return {}; - } - - void ecc::key::set(const std::string& pub_key_buffer) - { - this->free(); - - if (ecc_ansi_x963_import(reinterpret_cast(pub_key_buffer.data()), pub_key_buffer.size(), - &this->key_storage_) != CRYPT_OK) - { - ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); - } - } - - void ecc::key::deserialize(const std::string& key) - { - this->free(); - - if (ecc_import(reinterpret_cast(key.data()), key.size(), &this->key_storage_) != CRYPT_OK) - { - ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); - } - } - - std::string ecc::key::serialize(const int type) const - { - uint8_t buffer[4096] = {0}; - DWORD length = sizeof(buffer); - - if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK) - { - return std::string(reinterpret_cast(buffer), length); - } - - return ""; - } - - void ecc::key::free() - { - if (this->is_valid()) - { - ecc_free(&this->key_storage_); - } - - ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); - } - - bool ecc::key::operator==(key& key) const - { - return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC)); - } - - ecc::key ecc::generate_key(const int bits) - { - key key; - - ltc_mp = ltm_desc; - register_prng(&sprng_desc); - ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.get()); - - return key; - } - - std::string ecc::sign_message(key key, const std::string& message) - { - if (!key.is_valid()) return ""; - - uint8_t buffer[512]; - DWORD length = sizeof(buffer); - - ltc_mp = ltm_desc; - register_prng(&sprng_desc); - ecc_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, nullptr, - find_prng("sprng"), key.get()); - return std::string(reinterpret_cast(buffer), length); } - bool ecc::verify_message(key key, const std::string& message, const std::string& signature) + return {}; + } + + void ecc::key::set(const std::string& pub_key_buffer) + { + this->free(); + + if (ecc_ansi_x963_import(reinterpret_cast(pub_key_buffer.data()), pub_key_buffer.size(), + &this->key_storage_) != CRYPT_OK) { - if (!key.is_valid()) return false; - - ltc_mp = ltm_desc; - - auto result = 0; - return (ecc_verify_hash(reinterpret_cast(signature.data()), signature.size(), - reinterpret_cast(message.data()), message.size(), &result, - key.get()) == CRYPT_OK && result != 0); - } - - std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key) - { - initialize(); - - const auto prng_id = find_prng("yarrow"); - - rsa_key new_key; - rsa_import(PBYTE(key.data()), key.size(), &new_key); - - prng_state yarrow; - rng_make_prng(128, prng_id, &yarrow, nullptr); - - unsigned char buffer[0x80]; - unsigned long length = sizeof(buffer); - - const auto rsa_result = rsa_encrypt_key( // - PBYTE(data.data()), // - data.size(), // - buffer, // - &length, // - PBYTE(hash.data()), // - hash.size(), // - &yarrow, // - prng_id, // - find_hash("sha1"), // - &new_key); - - rsa_free(&new_key); - - if (rsa_result == CRYPT_OK) - { - return std::string(PCHAR(buffer), length); - } - - return {}; - } - - void rsa::initialize() - { - static auto initialized = false; - if (initialized) return; - initialized = true; - - ltc_mp = ltm_desc; - register_hash(&sha1_desc); - register_prng(&yarrow_desc); - } - - std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key) - { - initialize(); - - std::string enc_data; - enc_data.resize(data.size()); - - symmetric_CBC cbc; - const auto des3 = find_cipher("3des"); - - cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), - key.size(), 0, &cbc); - cbc_encrypt(reinterpret_cast(data.data()), - reinterpret_cast(const_cast(enc_data.data())), data.size(), &cbc); - cbc_done(&cbc); - - return enc_data; - } - - std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key) - { - initialize(); - - std::string dec_data; - dec_data.resize(data.size()); - - symmetric_CBC cbc; - const auto des3 = find_cipher("3des"); - - cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), - key.size(), 0, &cbc); - cbc_decrypt(reinterpret_cast(data.data()), - reinterpret_cast(const_cast(dec_data.data())), data.size(), &cbc); - cbc_done(&cbc); - - return dec_data; - } - - void des3::initialize() - { - static auto initialized = false; - if (initialized) return; - initialized = true; - - register_cipher(&des3_desc); - } - - std::string tiger::compute(const std::string& data, const bool hex) - { - return compute(reinterpret_cast(data.data()), data.size(), hex); - } - - std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex) - { - uint8_t buffer[24] = {0}; - - hash_state state; - tiger_init(&state); - tiger_process(&state, data, length); - tiger_done(&state, buffer); - - std::string hash(reinterpret_cast(buffer), sizeof(buffer)); - if (!hex) return hash; - - return string::dump_hex(hash, ""); - } - - std::string sha1::compute(const std::string& data, const bool hex) - { - return compute(reinterpret_cast(data.data()), data.size(), hex); - } - - std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex) - { - uint8_t buffer[20] = {0}; - - hash_state state; - sha1_init(&state); - sha1_process(&state, data, length); - sha1_done(&state, buffer); - - std::string hash(reinterpret_cast(buffer), sizeof(buffer)); - if (!hex) return hash; - - return string::dump_hex(hash, ""); - } - - std::string sha256::compute(const std::string& data, const bool hex) - { - return compute(reinterpret_cast(data.data()), data.size(), hex); - } - - std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex) - { - uint8_t buffer[32] = {0}; - - hash_state state; - sha256_init(&state); - sha256_process(&state, data, length); - sha256_done(&state, buffer); - - std::string hash(reinterpret_cast(buffer), sizeof(buffer)); - if (!hex) return hash; - - return string::dump_hex(hash, ""); - } - - std::string sha512::compute(const std::string& data, const bool hex) - { - return compute(reinterpret_cast(data.data()), data.size(), hex); - } - - std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex) - { - uint8_t buffer[64] = {0}; - - hash_state state; - sha512_init(&state); - sha512_process(&state, data, length); - sha512_done(&state, buffer); - - std::string hash(reinterpret_cast(buffer), sizeof(buffer)); - if (!hex) return hash; - - return string::dump_hex(hash, ""); - } - - unsigned int jenkins_one_at_a_time::compute(const std::string& data) - { - return compute(data.data(), data.size()); - } - - unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len) - { - unsigned int hash, i; - for (hash = i = 0; i < len; ++i) - { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - return hash; + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); } } + + void ecc::key::deserialize(const std::string& key) + { + this->free(); + + if (ecc_import(reinterpret_cast(key.data()), key.size(), &this->key_storage_) != CRYPT_OK) + { + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + } + + std::string ecc::key::serialize(const int type) const + { + uint8_t buffer[4096] = {0}; + DWORD length = sizeof(buffer); + + if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK) + { + return std::string(reinterpret_cast(buffer), length); + } + + return ""; + } + + void ecc::key::free() + { + if (this->is_valid()) + { + ecc_free(&this->key_storage_); + } + + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } + + bool ecc::key::operator==(key& key) const + { + return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC)); + } + + ecc::key ecc::generate_key(const int bits) + { + key key; + + ltc_mp = ltm_desc; + register_prng(&sprng_desc); + ecc_make_key(nullptr, find_prng("sprng"), bits / 8, key.get()); + + return key; + } + + std::string ecc::sign_message(key key, const std::string& message) + { + if (!key.is_valid()) return ""; + + uint8_t buffer[512]; + DWORD length = sizeof(buffer); + + ltc_mp = ltm_desc; + register_prng(&sprng_desc); + ecc_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, nullptr, + find_prng("sprng"), key.get()); + + return std::string(reinterpret_cast(buffer), length); + } + + bool ecc::verify_message(key key, const std::string& message, const std::string& signature) + { + if (!key.is_valid()) return false; + + ltc_mp = ltm_desc; + + auto result = 0; + return (ecc_verify_hash(reinterpret_cast(signature.data()), signature.size(), + reinterpret_cast(message.data()), message.size(), &result, + key.get()) == CRYPT_OK && result != 0); + } + + std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key) + { + initialize(); + + const auto prng_id = find_prng("yarrow"); + + rsa_key new_key; + rsa_import(PBYTE(key.data()), key.size(), &new_key); + + prng_state yarrow; + rng_make_prng(128, prng_id, &yarrow, nullptr); + + unsigned char buffer[0x80]; + unsigned long length = sizeof(buffer); + + const auto rsa_result = rsa_encrypt_key( // + PBYTE(data.data()), // + data.size(), // + buffer, // + &length, // + PBYTE(hash.data()), // + hash.size(), // + &yarrow, // + prng_id, // + find_hash("sha1"), // + &new_key); + + rsa_free(&new_key); + + if (rsa_result == CRYPT_OK) + { + return std::string(PCHAR(buffer), length); + } + + return {}; + } + + void rsa::initialize() + { + static auto initialized = false; + if (initialized) return; + initialized = true; + + ltc_mp = ltm_desc; + register_hash(&sha1_desc); + register_prng(&yarrow_desc); + } + + std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key) + { + initialize(); + + std::string enc_data; + enc_data.resize(data.size()); + + symmetric_CBC cbc; + const auto des3 = find_cipher("3des"); + + cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), + key.size(), 0, &cbc); + cbc_encrypt(reinterpret_cast(data.data()), + reinterpret_cast(const_cast(enc_data.data())), data.size(), &cbc); + cbc_done(&cbc); + + return enc_data; + } + + std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key) + { + initialize(); + + std::string dec_data; + dec_data.resize(data.size()); + + symmetric_CBC cbc; + const auto des3 = find_cipher("3des"); + + cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), + key.size(), 0, &cbc); + cbc_decrypt(reinterpret_cast(data.data()), + reinterpret_cast(const_cast(dec_data.data())), data.size(), &cbc); + cbc_done(&cbc); + + return dec_data; + } + + void des3::initialize() + { + static auto initialized = false; + if (initialized) return; + initialized = true; + + register_cipher(&des3_desc); + } + + std::string tiger::compute(const std::string& data, const bool hex) + { + return compute(reinterpret_cast(data.data()), data.size(), hex); + } + + std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[24] = {0}; + + hash_state state; + tiger_init(&state); + tiger_process(&state, data, length); + tiger_done(&state, buffer); + + std::string hash(reinterpret_cast(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string sha1::compute(const std::string& data, const bool hex) + { + return compute(reinterpret_cast(data.data()), data.size(), hex); + } + + std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[20] = {0}; + + hash_state state; + sha1_init(&state); + sha1_process(&state, data, length); + sha1_done(&state, buffer); + + std::string hash(reinterpret_cast(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string sha256::compute(const std::string& data, const bool hex) + { + return compute(reinterpret_cast(data.data()), data.size(), hex); + } + + std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[32] = {0}; + + hash_state state; + sha256_init(&state); + sha256_process(&state, data, length); + sha256_done(&state, buffer); + + std::string hash(reinterpret_cast(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + std::string sha512::compute(const std::string& data, const bool hex) + { + return compute(reinterpret_cast(data.data()), data.size(), hex); + } + + std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex) + { + uint8_t buffer[64] = {0}; + + hash_state state; + sha512_init(&state); + sha512_process(&state, data, length); + sha512_done(&state, buffer); + + std::string hash(reinterpret_cast(buffer), sizeof(buffer)); + if (!hex) return hash; + + return string::dump_hex(hash, ""); + } + + unsigned int jenkins_one_at_a_time::compute(const std::string& data) + { + return compute(data.data(), data.size()); + } + + unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len) + { + unsigned int hash, i; + for (hash = i = 0; i < len; ++i) + { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; + } } diff --git a/src/utils/cryptography.hpp b/src/utils/cryptography.hpp index 7269710..39792df 100644 --- a/src/utils/cryptography.hpp +++ b/src/utils/cryptography.hpp @@ -1,95 +1,92 @@ #pragma once -namespace utils +namespace utils::cryptography { - namespace cryptography + class ecc final { - class ecc final + public: + class key final { public: - class key final - { - public: - key(); - ~key(); + key(); + ~key(); - bool is_valid() const; + bool is_valid() const; - ecc_key* get(); + ecc_key* get(); - std::string get_public_key() const; + std::string get_public_key() const; - void set(const std::string& pub_key_buffer); + void set(const std::string& pub_key_buffer); - void deserialize(const std::string& key); + void deserialize(const std::string& key); - std::string serialize(int type = PK_PRIVATE) const; + std::string serialize(int type = PK_PRIVATE) const; - void free(); + void free(); - bool operator==(key& key) const; - - private: - ecc_key key_storage_{}; - }; - - static key generate_key(int bits); - static std::string sign_message(key key, const std::string& message); - static bool verify_message(key key, const std::string& message, const std::string& signature); - }; - - class rsa final - { - public: - static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key); + bool operator==(key& key) const; private: - static void initialize(); + ecc_key key_storage_{}; }; - class des3 final - { - public: - static std::string encrypt(const std::string& data, const std::string& iv, const std::string& key); - static std::string decrypt(const std::string& data, const std::string& iv, const std::string& key); + static key generate_key(int bits); + static std::string sign_message(key key, const std::string& message); + static bool verify_message(key key, const std::string& message, const std::string& signature); + }; - private: - static void initialize(); - }; + class rsa final + { + public: + static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key); - class tiger final - { - public: - static std::string compute(const std::string& data, bool hex = false); - static std::string compute(const uint8_t* data, size_t length, bool hex = false); - }; + private: + static void initialize(); + }; - class sha1 final - { - public: - static std::string compute(const std::string& data, bool hex = false); - static std::string compute(const uint8_t* data, size_t length, bool hex = false); - }; + class des3 final + { + public: + static std::string encrypt(const std::string& data, const std::string& iv, const std::string& key); + static std::string decrypt(const std::string& data, const std::string& iv, const std::string& key); - class sha256 final - { - public: - static std::string compute(const std::string& data, bool hex = false); - static std::string compute(const uint8_t* data, size_t length, bool hex = false); - }; + private: + static void initialize(); + }; - class sha512 final - { - public: - static std::string compute(const std::string& data, bool hex = false); - static std::string compute(const uint8_t* data, size_t length, bool hex = false); - }; + class tiger final + { + public: + static std::string compute(const std::string& data, bool hex = false); + static std::string compute(const uint8_t* data, size_t length, bool hex = false); + }; - class jenkins_one_at_a_time final - { - public: - static unsigned int compute(const std::string& data); - static unsigned int compute(const char* key, size_t len); - }; - } + class sha1 final + { + public: + static std::string compute(const std::string& data, bool hex = false); + static std::string compute(const uint8_t* data, size_t length, bool hex = false); + }; + + class sha256 final + { + public: + static std::string compute(const std::string& data, bool hex = false); + static std::string compute(const uint8_t* data, size_t length, bool hex = false); + }; + + class sha512 final + { + public: + static std::string compute(const std::string& data, bool hex = false); + static std::string compute(const uint8_t* data, size_t length, bool hex = false); + }; + + class jenkins_one_at_a_time final + { + public: + static unsigned int compute(const std::string& data); + static unsigned int compute(const char* key, size_t len); + }; } diff --git a/src/utils/flags.cpp b/src/utils/flags.cpp index 972aa21..b099639 100644 --- a/src/utils/flags.cpp +++ b/src/utils/flags.cpp @@ -2,51 +2,48 @@ #include "flags.hpp" #include "string.hpp" -namespace utils +namespace utils::flags { - namespace flags + void parse_flags(std::vector& flags) { - void parse_flags(std::vector& flags) + int num_args; + const auto argv = CommandLineToArgvW(GetCommandLineW(), &num_args); + + flags.clear(); + + if (argv) { - int num_args; - const auto argv = CommandLineToArgvW(GetCommandLineW(), &num_args); - - flags.clear(); - - if (argv) + for (auto i = 0; i < num_args; ++i) { - for (auto i = 0; i < num_args; ++i) + std::wstring wide_flag(argv[i]); + if (wide_flag[0] == L'-') { - std::wstring wide_flag(argv[i]); - if (wide_flag[0] == L'-') - { - flags.emplace_back(wide_flag.begin() + 1, wide_flag.end()); - } - } - - LocalFree(argv); - } - } - - bool has_flag(const std::string& flag) - { - static auto parsed = false; - static std::vector enabled_flags; - - if (!parsed) - { - parse_flags(enabled_flags); - } - - for (const auto& entry : enabled_flags) - { - if (string::to_lower(entry) == string::to_lower(flag)) - { - return true; + flags.emplace_back(wide_flag.begin() + 1, wide_flag.end()); } } - return false; + LocalFree(argv); } } + + bool has_flag(const std::string& flag) + { + static auto parsed = false; + static std::vector enabled_flags; + + if (!parsed) + { + parse_flags(enabled_flags); + } + + for (const auto& entry : enabled_flags) + { + if (string::to_lower(entry) == string::to_lower(flag)) + { + return true; + } + } + + return false; + } } diff --git a/src/utils/flags.hpp b/src/utils/flags.hpp index 994adc3..e15c75d 100644 --- a/src/utils/flags.hpp +++ b/src/utils/flags.hpp @@ -1,9 +1,6 @@ #pragma once -namespace utils +namespace utils::flags { - namespace flags - { - bool has_flag(const std::string& flag); - } + bool has_flag(const std::string& flag); } diff --git a/src/utils/io.cpp b/src/utils/io.cpp index 7c0f7d1..476a3c9 100644 --- a/src/utils/io.cpp +++ b/src/utils/io.cpp @@ -1,110 +1,107 @@ #include #include "io.hpp" -namespace utils +namespace utils::io { - namespace io + bool file_exists(const std::string& file) { - bool file_exists(const std::string& file) + return std::ifstream(file).good(); + } + + bool write_file(const std::string& file, const std::string& data, const bool append) + { + const auto pos = file.find_last_of("/\\"); + if (pos != std::string::npos) { - return std::ifstream(file).good(); + create_directory(file.substr(0, pos)); } - bool write_file(const std::string& file, const std::string& data, const bool append) + std::ofstream stream( + file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out)); + + if (stream.is_open()) { - const auto pos = file.find_last_of("/\\"); - if (pos != std::string::npos) - { - create_directory(file.substr(0, pos)); - } + stream.write(data.data(), data.size()); + stream.close(); + return true; + } - std::ofstream stream( - file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : std::ofstream::out)); + return false; + } - if (stream.is_open()) + std::string read_file(const std::string& file) + { + std::string data; + read_file(file, &data); + return data; + } + + bool read_file(const std::string& file, std::string* data) + { + if (!data) return false; + data->clear(); + + if (file_exists(file)) + { + std::ifstream stream(file, std::ios::binary); + if (!stream.is_open()) return false; + + stream.seekg(0, std::ios::end); + const std::streamsize size = stream.tellg(); + stream.seekg(0, std::ios::beg); + + if (size > -1) { - stream.write(data.data(), data.size()); + data->resize(static_cast(size)); + stream.read(const_cast(data->data()), size); stream.close(); return true; } - - return false; } - std::string read_file(const std::string& file) - { - std::string data; - read_file(file, &data); - return data; - } + return false; + } - bool read_file(const std::string& file, std::string* data) + size_t file_size(const std::string& file) + { + if (file_exists(file)) { - if (!data) return false; - data->clear(); + std::ifstream stream(file, std::ios::binary); - if (file_exists(file)) + if (stream.good()) { - std::ifstream stream(file, std::ios::binary); - if (!stream.is_open()) return false; - stream.seekg(0, std::ios::end); - const std::streamsize size = stream.tellg(); - stream.seekg(0, std::ios::beg); - - if (size > -1) - { - data->resize(static_cast(size)); - stream.read(const_cast(data->data()), size); - stream.close(); - return true; - } + return static_cast(stream.tellg()); } - - return false; } - size_t file_size(const std::string& file) + return 0; + } + + bool create_directory(const std::string& directory) + { + return std::experimental::filesystem::create_directories(directory); + } + + bool directory_exists(const std::string& directory) + { + return std::experimental::filesystem::is_directory(directory); + } + + bool directory_is_empty(const std::string& directory) + { + return std::experimental::filesystem::is_empty(directory); + } + + std::vector list_files(const std::string& directory) + { + std::vector files; + + for (auto& file : std::experimental::filesystem::directory_iterator(directory)) { - if (file_exists(file)) - { - std::ifstream stream(file, std::ios::binary); - - if (stream.good()) - { - stream.seekg(0, std::ios::end); - return static_cast(stream.tellg()); - } - } - - return 0; + files.push_back(file.path().generic_string()); } - bool create_directory(const std::string& directory) - { - return std::experimental::filesystem::create_directories(directory); - } - - bool directory_exists(const std::string& directory) - { - return std::experimental::filesystem::is_directory(directory); - } - - bool directory_is_empty(const std::string& directory) - { - return std::experimental::filesystem::is_empty(directory); - } - - std::vector list_files(const std::string& directory) - { - std::vector files; - - for (auto& file : std::experimental::filesystem::directory_iterator(directory)) - { - files.push_back(file.path().generic_string()); - } - - return files; - } + return files; } } diff --git a/src/utils/io.hpp b/src/utils/io.hpp index 0dc5a56..9ed4502 100644 --- a/src/utils/io.hpp +++ b/src/utils/io.hpp @@ -1,17 +1,14 @@ -#pragma once - -namespace utils -{ - namespace io - { - bool file_exists(const std::string& file); - bool write_file(const std::string& file, const std::string& data, bool append = false); - bool read_file(const std::string& file, std::string* data); - std::string read_file(const std::string& file); - size_t file_size(const std::string& file); - bool create_directory(const std::string& directory); - bool directory_exists(const std::string& directory); - bool directory_is_empty(const std::string& directory); - std::vector list_files(const std::string& directory); - } -} +#pragma once + +namespace utils::io +{ + bool file_exists(const std::string& file); + bool write_file(const std::string& file, const std::string& data, bool append = false); + bool read_file(const std::string& file, std::string* data); + std::string read_file(const std::string& file); + size_t file_size(const std::string& file); + bool create_directory(const std::string& directory); + bool directory_exists(const std::string& directory); + bool directory_is_empty(const std::string& directory); + std::vector list_files(const std::string& directory); +} diff --git a/src/utils/nt.cpp b/src/utils/nt.cpp index 5018af9..a3a148e 100644 --- a/src/utils/nt.cpp +++ b/src/utils/nt.cpp @@ -1,207 +1,204 @@ #include #include "nt.hpp" -namespace utils +namespace utils::nt { - namespace nt + module module::load(const std::string& name) { - module module::load(const std::string& name) + return module(LoadLibraryA(name.data())); + } + + module module::get_by_address(void* address) + { + HMODULE handle = nullptr; + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(address), &handle); + return module(handle); + } + + module::module() + { + this->module_ = GetModuleHandleA(nullptr); + } + + module::module(const std::string& name) + { + this->module_ = GetModuleHandleA(name.data()); + } + + module::module(const HMODULE handle) + { + this->module_ = handle; + } + + bool module::operator==(const module& obj) const + { + return this->module_ == obj.module_; + } + + module::operator bool() const + { + return this->is_valid(); + } + + module::operator HMODULE() const + { + return this->get_handle(); + } + + PIMAGE_NT_HEADERS module::get_nt_headers() const + { + if (!this->is_valid()) return nullptr; + return reinterpret_cast(this->get_ptr() + this->get_dos_header()->e_lfanew); + } + + PIMAGE_DOS_HEADER module::get_dos_header() const + { + return reinterpret_cast(this->get_ptr()); + } + + PIMAGE_OPTIONAL_HEADER module::get_optional_header() const + { + if (!this->is_valid()) return nullptr; + return &this->get_nt_headers()->OptionalHeader; + } + + std::vector module::get_section_headers() const + { + std::vector headers; + + auto nt_headers = this->get_nt_headers(); + auto section = IMAGE_FIRST_SECTION(nt_headers); + + for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section) { - return module(LoadLibraryA(name.data())); + if (section) headers.push_back(section); + else OutputDebugStringA("There was an invalid section :O"); } - module module::get_by_address(void* address) + return headers; + } + + std::uint8_t* module::get_ptr() const + { + return reinterpret_cast(this->module_); + } + + void module::unprotect() const + { + if (!this->is_valid()) return; + + DWORD protection; + VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE, + &protection); + } + + size_t module::get_relative_entry_point() const + { + if (!this->is_valid()) return 0; + return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; + } + + void* module::get_entry_point() const + { + if (!this->is_valid()) return nullptr; + return this->get_ptr() + this->get_relative_entry_point(); + } + + bool module::is_valid() const + { + return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; + } + + std::string module::get_name() const + { + if (!this->is_valid()) return ""; + + auto path = this->get_path(); + const auto pos = path.find_last_of("/\\"); + if (pos == std::string::npos) return path; + + return path.substr(pos + 1); + } + + std::string module::get_path() const + { + if (!this->is_valid()) return ""; + + char name[MAX_PATH] = {0}; + GetModuleFileNameA(this->module_, name, sizeof name); + + return name; + } + + void module::free() + { + if (this->is_valid()) { - HMODULE handle = nullptr; - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(address), &handle); - return module(handle); - } - - module::module() - { - this->module_ = GetModuleHandleA(nullptr); - } - - module::module(const std::string& name) - { - this->module_ = GetModuleHandleA(name.data()); - } - - module::module(const HMODULE handle) - { - this->module_ = handle; - } - - bool module::operator==(const module& obj) const - { - return this->module_ == obj.module_; - } - - module::operator bool() const - { - return this->is_valid(); - } - - module::operator HMODULE() const - { - return this->get_handle(); - } - - PIMAGE_NT_HEADERS module::get_nt_headers() const - { - if (!this->is_valid()) return nullptr; - return reinterpret_cast(this->get_ptr() + this->get_dos_header()->e_lfanew); - } - - PIMAGE_DOS_HEADER module::get_dos_header() const - { - return reinterpret_cast(this->get_ptr()); - } - - PIMAGE_OPTIONAL_HEADER module::get_optional_header() const - { - if (!this->is_valid()) return nullptr; - return &this->get_nt_headers()->OptionalHeader; - } - - std::vector module::get_section_headers() const - { - std::vector headers; - - auto nt_headers = this->get_nt_headers(); - auto section = IMAGE_FIRST_SECTION(nt_headers); - - for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section) - { - if (section) headers.push_back(section); - else OutputDebugStringA("There was an invalid section :O"); - } - - return headers; - } - - std::uint8_t* module::get_ptr() const - { - return reinterpret_cast(this->module_); - } - - void module::unprotect() const - { - if (!this->is_valid()) return; - - DWORD protection; - VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE, - &protection); - } - - size_t module::get_relative_entry_point() const - { - if (!this->is_valid()) return 0; - return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; - } - - void* module::get_entry_point() const - { - if (!this->is_valid()) return nullptr; - return this->get_ptr() + this->get_relative_entry_point(); - } - - bool module::is_valid() const - { - return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; - } - - std::string module::get_name() const - { - if (!this->is_valid()) return ""; - - auto path = this->get_path(); - const auto pos = path.find_last_of("/\\"); - if (pos == std::string::npos) return path; - - return path.substr(pos + 1); - } - - std::string module::get_path() const - { - if (!this->is_valid()) return ""; - - char name[MAX_PATH] = {0}; - GetModuleFileNameA(this->module_, name, sizeof name); - - return name; - } - - void module::free() - { - if (this->is_valid()) - { - FreeLibrary(this->module_); - this->module_ = nullptr; - } - } - - HMODULE module::get_handle() const - { - return this->module_; - } - - void** module::get_iat_entry(const std::string& module_name, const std::string& proc_name) const - { - if (!this->is_valid()) return nullptr; - - const module other_module(module_name); - if (!other_module.is_valid()) return nullptr; - - const auto target_function = other_module.get_proc(proc_name); - if (!target_function) return nullptr; - - auto* header = this->get_optional_header(); - if (!header) return nullptr; - - auto* import_descriptor = reinterpret_cast(this->get_ptr() + header->DataDirectory - [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); - - while (import_descriptor->Name) - { - if (!_stricmp(reinterpret_cast(this->get_ptr() + import_descriptor->Name), module_name.data())) - { - auto* original_thunk_data = reinterpret_cast(import_descriptor-> - OriginalFirstThunk + this->get_ptr()); - auto* thunk_data = reinterpret_cast(import_descriptor->FirstThunk + this-> - get_ptr()); - - while (original_thunk_data->u1.AddressOfData) - { - const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; - - if (ordinal_number > 0xFFFF) continue; - - if (GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)) == - target_function) - { - return reinterpret_cast(&thunk_data->u1.Function); - } - - ++original_thunk_data; - ++thunk_data; - } - - //break; - } - - ++import_descriptor; - } - - return nullptr; - } - - void raise_hard_exception() - { - int data = false; - const module ntdll("ntdll.dll"); - ntdll.invoke_pascal("RtlAdjustPrivilege", 19, true, false, &data); - ntdll.invoke_pascal("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data); + FreeLibrary(this->module_); + this->module_ = nullptr; } } + + HMODULE module::get_handle() const + { + return this->module_; + } + + void** module::get_iat_entry(const std::string& module_name, const std::string& proc_name) const + { + if (!this->is_valid()) return nullptr; + + const module other_module(module_name); + if (!other_module.is_valid()) return nullptr; + + const auto target_function = other_module.get_proc(proc_name); + if (!target_function) return nullptr; + + auto* header = this->get_optional_header(); + if (!header) return nullptr; + + auto* import_descriptor = reinterpret_cast(this->get_ptr() + header->DataDirectory + [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + while (import_descriptor->Name) + { + if (!_stricmp(reinterpret_cast(this->get_ptr() + import_descriptor->Name), module_name.data())) + { + auto* original_thunk_data = reinterpret_cast(import_descriptor-> + OriginalFirstThunk + this->get_ptr()); + auto* thunk_data = reinterpret_cast(import_descriptor->FirstThunk + this-> + get_ptr()); + + while (original_thunk_data->u1.AddressOfData) + { + const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; + + if (ordinal_number > 0xFFFF) continue; + + if (GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)) == + target_function) + { + return reinterpret_cast(&thunk_data->u1.Function); + } + + ++original_thunk_data; + ++thunk_data; + } + + //break; + } + + ++import_descriptor; + } + + return nullptr; + } + + void raise_hard_exception() + { + int data = false; + const module ntdll("ntdll.dll"); + ntdll.invoke_pascal("RtlAdjustPrivilege", 19, true, false, &data); + ntdll.invoke_pascal("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data); + } } diff --git a/src/utils/nt.hpp b/src/utils/nt.hpp index 2c8f423..4892a72 100644 --- a/src/utils/nt.hpp +++ b/src/utils/nt.hpp @@ -1,91 +1,88 @@ -#pragma once - -namespace utils -{ - namespace nt - { - class module final - { - public: - static module load(const std::string& name); - static module get_by_address(void* address); - - module(); - explicit module(const std::string& name); - explicit module(HMODULE handle); - - module(const module& a) : module_(a.module_) - { - } - - bool operator!=(const module& obj) const { return !(*this == obj); }; - bool operator==(const module& obj) const; - - operator bool() const; - operator HMODULE() const; - - void unprotect() const; - void* get_entry_point() const; - size_t get_relative_entry_point() const; - - bool is_valid() const; - std::string get_name() const; - std::string get_path() const; - std::uint8_t* get_ptr() const; - void free(); - - HMODULE get_handle() const; - - template - T get_proc(const std::string& process) const - { - if (!this->is_valid()) T{}; - return reinterpret_cast(GetProcAddress(this->module_, process.data())); - } - - template - std::function get(const std::string& process) const - { - if (!this->is_valid()) std::function(); - return reinterpret_cast(this->get_proc(process)); - } - - template - T invoke(const std::string& process, Args ... args) const - { - auto method = this->get(process); - if (method) return method(args...); - return T(); - } - - template - T invoke_pascal(const std::string& process, Args ... args) const - { - auto method = this->get(process); - if (method) return method(args...); - return T(); - } - - template - T invoke_this(const std::string& process, void* this_ptr, Args ... args) const - { - auto method = this->get(this_ptr, process); - if (method) return method(args...); - return T(); - } - - std::vector get_section_headers() const; - - PIMAGE_NT_HEADERS get_nt_headers() const; - PIMAGE_DOS_HEADER get_dos_header() const; - PIMAGE_OPTIONAL_HEADER get_optional_header() const; - - void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const; - - private: - HMODULE module_; - }; - - void raise_hard_exception(); - } -} +#pragma once + +namespace utils::nt +{ + class module final + { + public: + static module load(const std::string& name); + static module get_by_address(void* address); + + module(); + explicit module(const std::string& name); + explicit module(HMODULE handle); + + module(const module& a) : module_(a.module_) + { + } + + bool operator!=(const module& obj) const { return !(*this == obj); }; + bool operator==(const module& obj) const; + + operator bool() const; + operator HMODULE() const; + + void unprotect() const; + void* get_entry_point() const; + size_t get_relative_entry_point() const; + + bool is_valid() const; + std::string get_name() const; + std::string get_path() const; + std::uint8_t* get_ptr() const; + void free(); + + HMODULE get_handle() const; + + template + T get_proc(const std::string& process) const + { + if (!this->is_valid()) T{}; + return reinterpret_cast(GetProcAddress(this->module_, process.data())); + } + + template + std::function get(const std::string& process) const + { + if (!this->is_valid()) std::function(); + return reinterpret_cast(this->get_proc(process)); + } + + template + T invoke(const std::string& process, Args ... args) const + { + auto method = this->get(process); + if (method) return method(args...); + return T(); + } + + template + T invoke_pascal(const std::string& process, Args ... args) const + { + auto method = this->get(process); + if (method) return method(args...); + return T(); + } + + template + T invoke_this(const std::string& process, void* this_ptr, Args ... args) const + { + auto method = this->get(this_ptr, process); + if (method) return method(args...); + return T(); + } + + std::vector get_section_headers() const; + + PIMAGE_NT_HEADERS get_nt_headers() const; + PIMAGE_DOS_HEADER get_dos_header() const; + PIMAGE_OPTIONAL_HEADER get_optional_header() const; + + void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const; + + private: + HMODULE module_; + }; + + void raise_hard_exception(); +} diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 9a4da47..9180cf0 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -1,58 +1,55 @@ -#include -#include "string.hpp" - -namespace utils -{ - namespace string - { - const char* va(const char* fmt, ...) - { - static thread_local va_provider<8, 256> provider; - - va_list ap; - va_start(ap, fmt); - - const char* result = provider.get(fmt, ap); - - va_end(ap); - return result; - } - - std::string to_lower(std::string text) - { - std::transform(text.begin(), text.end(), text.begin(), [](const char input) - { - return CHAR(tolower(input)); - }); - - return text; - } - - std::string to_upper(std::string text) - { - std::transform(text.begin(), text.end(), text.begin(), [](const char input) - { - return CHAR(toupper(input)); - }); - - return text; - } - - std::string dump_hex(const std::string& data, const std::string& separator) - { - std::string result; - - for (unsigned int i = 0; i < data.size(); ++i) - { - if (i > 0) - { - result.append(separator); - } - - result.append(va("%02X", data[i] & 0xFF)); - } - - return result; - } - } -} +#include +#include "string.hpp" + +namespace utils::string +{ + const char* va(const char* fmt, ...) + { + static thread_local va_provider<8, 256> provider; + + va_list ap; + va_start(ap, fmt); + + const char* result = provider.get(fmt, ap); + + va_end(ap); + return result; + } + + std::string to_lower(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return CHAR(tolower(input)); + }); + + return text; + } + + std::string to_upper(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return CHAR(toupper(input)); + }); + + return text; + } + + std::string dump_hex(const std::string& data, const std::string& separator) + { + std::string result; + + for (unsigned int i = 0; i < data.size(); ++i) + { + if (i > 0) + { + result.append(separator); + } + + result.append(va("%02X", data[i] & 0xFF)); + } + + return result; + } +} diff --git a/src/utils/string.hpp b/src/utils/string.hpp index 9c6d829..c51f2b6 100644 --- a/src/utils/string.hpp +++ b/src/utils/string.hpp @@ -1,84 +1,81 @@ -#pragma once -#include "memory.hpp" - -namespace utils -{ - namespace string - { - template - class va_provider final - { - public: - static_assert(Buffers != 0 && MinBufferSize != 0, "Buffers and MinBufferSize mustn't be 0"); - - va_provider() : current_buffer_(0) - { - } - - char* get(const char* format, const va_list ap) - { - ++this->current_buffer_ %= ARRAYSIZE(this->string_pool_); - auto entry = &this->string_pool_[this->current_buffer_]; - - if (!entry->size || !entry->buffer) - { - throw std::runtime_error("String pool not initialized"); - } - - while (true) - { - const int res = vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap); - if (res > 0) break; // Success - if (res == 0) return nullptr; // Error - - entry->double_size(); - } - - return entry->buffer; - } - - private: - class entry final - { - public: - explicit entry(size_t _size = MinBufferSize) : size(_size), buffer(nullptr) - { - if (this->size < MinBufferSize) this->size = MinBufferSize; - this->allocate(); - } - - ~entry() - { - if (this->buffer) memory::get_allocator()->free(this->buffer); - this->size = 0; - this->buffer = nullptr; - } - - void allocate() - { - if (this->buffer) memory::get_allocator()->free(this->buffer); - this->buffer = memory::get_allocator()->allocate_array(this->size + 1); - } - - void double_size() - { - this->size *= 2; - this->allocate(); - } - - size_t size; - char* buffer; - }; - - size_t current_buffer_; - entry string_pool_[Buffers]; - }; - - const char* va(const char* fmt, ...); - - std::string to_lower(std::string text); - std::string to_upper(std::string text); - - std::string dump_hex(const std::string& data, const std::string& separator = " "); - } -} +#pragma once +#include "memory.hpp" + +namespace utils::string +{ + template + class va_provider final + { + public: + static_assert(Buffers != 0 && MinBufferSize != 0, "Buffers and MinBufferSize mustn't be 0"); + + va_provider() : current_buffer_(0) + { + } + + char* get(const char* format, const va_list ap) + { + ++this->current_buffer_ %= ARRAYSIZE(this->string_pool_); + auto entry = &this->string_pool_[this->current_buffer_]; + + if (!entry->size || !entry->buffer) + { + throw std::runtime_error("String pool not initialized"); + } + + while (true) + { + const int res = vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap); + if (res > 0) break; // Success + if (res == 0) return nullptr; // Error + + entry->double_size(); + } + + return entry->buffer; + } + + private: + class entry final + { + public: + explicit entry(size_t _size = MinBufferSize) : size(_size), buffer(nullptr) + { + if (this->size < MinBufferSize) this->size = MinBufferSize; + this->allocate(); + } + + ~entry() + { + if (this->buffer) memory::get_allocator()->free(this->buffer); + this->size = 0; + this->buffer = nullptr; + } + + void allocate() + { + if (this->buffer) memory::get_allocator()->free(this->buffer); + this->buffer = memory::get_allocator()->allocate_array(this->size + 1); + } + + void double_size() + { + this->size *= 2; + this->allocate(); + } + + size_t size; + char* buffer; + }; + + size_t current_buffer_; + entry string_pool_[Buffers]; + }; + + const char* va(const char* fmt, ...); + + std::string to_lower(std::string text); + std::string to_upper(std::string text); + + std::string dump_hex(const std::string& data, const std::string& separator = " "); +}