Random cleanup

This commit is contained in:
momo5502 2019-09-27 22:35:57 +02:00
parent 320d57599e
commit 9f98190944
37 changed files with 2965 additions and 3080 deletions

View File

@ -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_;
}
}

View File

@ -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_;
};
}

View File

@ -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>(), "_entity");
chai->add(chaiscript::constructor<entity()>(), "_entity");
chai->add(chaiscript::constructor<entity(const entity&)>(), "_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<void(
std::vector<chaiscript::Boxed_Value>)>&
callback)
{
return ent.on_notify(event, callback, false);
}), "onNotify");
chai->add(chaiscript::fun([context](const std::string& event,
const std::function<void(
entity, std::vector<chaiscript::Boxed_Value>)>&
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<void(
entity, std::vector<chaiscript::Boxed_Value>)>&
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<chaiscript::Boxed_Value>& 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>(), "_entity");
chai->add(chaiscript::constructor<entity()>(), "_entity");
chai->add(chaiscript::constructor<entity(const entity&)>(), "_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<void(
std::vector<chaiscript::Boxed_Value>)>&
callback)
{
return ent.on_notify(event, callback, false);
}), "onNotify");
chai->add(chaiscript::fun([context](const std::string& event,
const std::function<void(
entity, std::vector<chaiscript::Boxed_Value>)>&
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<void(
entity, std::vector<chaiscript::Boxed_Value>)>&
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<chaiscript::Boxed_Value>& 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");
}
}

View File

@ -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);
}

View File

@ -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<void(std::vector<chaiscript::Boxed_Value>)>&
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<chaiscript::Boxed_Value>& arguments) const
{
return this->context_->get_executer()->call(function, this->get_entity_id(), arguments);
}
void entity::notify(const std::string& event,
const std::vector<chaiscript::Boxed_Value>& 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<void(std::vector<chaiscript::Boxed_Value>)>&
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<chaiscript::Boxed_Value>& arguments) const
{
return this->context_->get_executer()->call(function, this->get_entity_id(), arguments);
}
void entity::notify(const std::string& event,
const std::vector<chaiscript::Boxed_Value>& 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<int>(this->entity_id_)});
}
native::RemoveRefToValue(native::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)});
}
}
}

View File

@ -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<void(std::vector<chaiscript::Boxed_Value>)>& 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<chaiscript::Boxed_Value>& arguments) const;
void notify(const std::string& event, const std::vector<chaiscript::Boxed_Value>& 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<void(std::vector<chaiscript::Boxed_Value>)>& 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<chaiscript::Boxed_Value>& arguments) const;
void notify(const std::string& event, const std::vector<chaiscript::Boxed_Value>& 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;
};
}

View File

@ -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<native::VariableValue> arguments;
};
}
}
#pragma once
#include "game/game.hpp"
namespace game::scripting
{
class event final
{
public:
std::string name;
unsigned int entity_id;
std::vector<native::VariableValue> arguments;
};
}

View File

@ -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>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle()>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle(const event_listener_handle&)>(),
"_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>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle()>(), "_event_listener_handle");
chai->add(chaiscript::constructor<event_listener_handle(const event_listener_handle&)>(),
"_event_listener_handle");
void event_handler::dispatch(event* event)
{
try
{
std::vector<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value>& 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<chaiscript::Boxed_Value>& 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<chaiscript::Boxed_Value>& 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<chaiscript::Boxed_Value>& 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;
}
}
}

View File

@ -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<void(std::vector<chaiscript::Boxed_Value>)> callback = {};
bool is_volatile = false;
};
class generic_event_listener final : public event_listener_handle
{
public:
std::string event = {};
std::function<void(entity, std::vector<chaiscript::Boxed_Value>)> 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_listener> event_listeners_;
utils::concurrent_list<generic_event_listener> generic_event_listeners_;
void dispatch_to_specific_listeners(event* event, const std::vector<chaiscript::Boxed_Value>& arguments);
void dispatch_to_generic_listeners(event* event, const std::vector<chaiscript::Boxed_Value>& 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<void(std::vector<chaiscript::Boxed_Value>)> callback = {};
bool is_volatile = false;
};
class generic_event_listener final : public event_listener_handle
{
public:
std::string event = {};
std::function<void(entity, std::vector<chaiscript::Boxed_Value>)> 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_listener> event_listeners_;
utils::concurrent_list<generic_event_listener> generic_event_listeners_;
void dispatch_to_specific_listeners(event* event, const std::vector<chaiscript::Boxed_Value>& arguments);
void dispatch_to_generic_listeners(event* event, const std::vector<chaiscript::Boxed_Value>& arguments);
void remove(const event_listener_handle& handle);
};
}

View File

@ -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<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value> 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;
}
}

View File

@ -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<chaiscript::Boxed_Value> arguments) const;
chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments) const;
private:
context* context_;
std::unordered_map<unsigned int, std::unordered_map<std::string, chaiscript::Boxed_Value>> 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<chaiscript::Boxed_Value> arguments) const;
chaiscript::Boxed_Value call(const std::string& function, unsigned int entity_id,
std::vector<chaiscript::Boxed_Value> arguments) const;
private:
context* context_;
std::unordered_map<unsigned int, std::unordered_map<std::string, chaiscript::Boxed_Value>> 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);
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,7 @@
#pragma once
namespace game
namespace game::scripting
{
namespace scripting
{
extern std::map<std::string, int> instance_function_map;
extern std::map<std::string, int> global_function_map;
}
extern std::map<std::string, int> instance_function_map;
extern std::map<std::string, int> global_function_map;
}

View File

@ -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<chaiscript::Boxed_Value> 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<chaiscript::Boxed_Value> 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<float>(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<double>(value);
value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = static_cast<float>(real_value);
}
else if (value.get_type_info() == typeid(int))
{
const auto real_value = this->context_->get_chai()->boxed_cast<int>(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<bool>(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<entity>(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<std::string>(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<chaiscript::Boxed_Value>))
{
float values[3];
const auto real_value = this->context_->get_chai()->boxed_cast<std::vector<chaiscript::Boxed_Value>
>(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<float>(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<double>(value);
value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = static_cast<float>(real_value);
}
else if (value.get_type_info() == typeid(int))
{
const auto real_value = this->context_->get_chai()->boxed_cast<int>(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<bool>(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<entity>(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<std::string>(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<chaiscript::Boxed_Value>))
{
float values[3];
const auto real_value = this->context_->get_chai()->boxed_cast<std::vector<chaiscript::Boxed_Value>
>(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<float>(value);
}
if (value.get_type_info() == typeid(double))
{
return float(this->context_->get_chai()->boxed_cast<double>(value));
}
if (value.get_type_info() == typeid(int))
{
return float(this->context_->get_chai()->boxed_cast<int>(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<float>(value);
}
if (value.get_type_info() == typeid(double))
{
return float(this->context_->get_chai()->boxed_cast<double>(value));
}
if (value.get_type_info() == typeid(int))
{
return float(this->context_->get_chai()->boxed_cast<int>(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]);
}
}

View File

@ -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_;
};
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle()>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle(const task_handle&)>(), "_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>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle()>(), "_task_handle");
chai->add(chaiscript::constructor<task_handle(const task_handle&)>(), "_task_handle");
chai->add(chaiscript::fun(
[this](const std::function<void()>& 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<void()>& 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<void()>& callback, const long long milliseconds) -> task_handle
{
return this->add(callback, milliseconds, true);
}), "setTimeout");
chai->add(chaiscript::fun(
[this](const std::function<void()>& 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<void()>& 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<void()>& 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<void()>& 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<void()>& 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;
}
}
}

View File

@ -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<void()> 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<task> tasks_;
std::atomic_int64_t current_task_id_ = 0;
task_handle add(const std::function<void()>& callback, long long milliseconds, bool is_volatile);
task_handle add(const std::function<void()>& 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<void()> 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<task> tasks_;
std::atomic_int64_t current_task_id_ = 0;
task_handle add(const std::function<void()>& callback, long long milliseconds, bool is_volatile);
task_handle add(const std::function<void()>& callback, std::chrono::milliseconds delay, bool is_volatile);
void remove(const task_handle& handle);
};
}

View File

@ -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_;
}
}

View File

@ -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_;
};
}

View File

@ -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_;
}
}

View File

@ -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_;
};
}

View File

@ -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())

View File

@ -37,7 +37,7 @@
<body>
<div class="content">
<h1>No settings, yet!</h1>
<h3>No settings, yet!</h3>
</div>
</body>

View File

@ -1,73 +1,70 @@
#include <std_include.hpp>
#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<char>(length);
if (compress2(reinterpret_cast<Bytef*>(buffer), &length,
reinterpret_cast<Bytef*>(const_cast<char*>(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<uint8_t>(CHUNK);
auto data_ptr = data.data();
do
{
stream.avail_in = std::min(static_cast<size_t>(CHUNK), data.size() - (data_ptr - data.data()));
stream.next_in = reinterpret_cast<const uint8_t*>(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<const char*>(dest), CHUNK - stream.avail_out);
}
while (stream.avail_out == 0);
}
while (ret != Z_STREAM_END);
inflateEnd(&stream);
return buffer;
}
}
}
#include <std_include.hpp>
#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<char>(length);
if (compress2(reinterpret_cast<Bytef*>(buffer), &length,
reinterpret_cast<Bytef*>(const_cast<char*>(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<uint8_t>(CHUNK);
auto data_ptr = data.data();
do
{
stream.avail_in = std::min(static_cast<size_t>(CHUNK), data.size() - (data_ptr - data.data()));
stream.next_in = reinterpret_cast<const uint8_t*>(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<const char*>(dest), CHUNK - stream.avail_out);
}
while (stream.avail_out == 0);
}
while (ret != Z_STREAM_END);
inflateEnd(&stream);
return buffer;
}
}

View File

@ -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);
};
};

View File

@ -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<char*>(buffer), length);
}
return {};
}
void ecc::key::set(const std::string& pub_key_buffer)
{
this->free();
if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr,
find_prng("sprng"), key.get());
return std::string(reinterpret_cast<char*>(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<const uint8_t*>(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<const uint8_t*>(signature.data()), signature.size(),
reinterpret_cast<const uint8_t*>(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<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(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<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_decrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(message.data()), message.size(), buffer, &length, nullptr,
find_prng("sprng"), key.get());
return std::string(reinterpret_cast<char*>(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<const uint8_t*>(signature.data()), signature.size(),
reinterpret_cast<const uint8_t*>(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<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(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<const uint8_t*>(iv.data()), reinterpret_cast<const uint8_t*>(key.data()),
key.size(), 0, &cbc);
cbc_decrypt(reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<uint8_t*>(const_cast<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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<const uint8_t*>(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<char*>(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;
}
}

View File

@ -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);
};
}

View File

@ -2,51 +2,48 @@
#include "flags.hpp"
#include "string.hpp"
namespace utils
namespace utils::flags
{
namespace flags
void parse_flags(std::vector<std::string>& flags)
{
void parse_flags(std::vector<std::string>& 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<std::string> 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<std::string> 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;
}
}

View File

@ -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);
}

View File

@ -1,110 +1,107 @@
#include <std_include.hpp>
#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<uint32_t>(size));
stream.read(const_cast<char*>(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<uint32_t>(size));
stream.read(const_cast<char*>(data->data()), size);
stream.close();
return true;
}
return static_cast<size_t>(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<std::string> list_files(const std::string& directory)
{
std::vector<std::string> 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<size_t>(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<std::string> list_files(const std::string& directory)
{
std::vector<std::string> files;
for (auto& file : std::experimental::filesystem::directory_iterator(directory))
{
files.push_back(file.path().generic_string());
}
return files;
}
return files;
}
}

View File

@ -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<std::string> 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<std::string> list_files(const std::string& directory);
}

View File

@ -1,207 +1,204 @@
#include <std_include.hpp>
#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<LPCSTR>(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<PIMAGE_NT_HEADERS>(this->get_ptr() + this->get_dos_header()->e_lfanew);
}
PIMAGE_DOS_HEADER module::get_dos_header() const
{
return reinterpret_cast<PIMAGE_DOS_HEADER>(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<PIMAGE_SECTION_HEADER> module::get_section_headers() const
{
std::vector<PIMAGE_SECTION_HEADER> 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<std::uint8_t*>(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<LPCSTR>(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<PIMAGE_NT_HEADERS>(this->get_ptr() + this->get_dos_header()->e_lfanew);
}
PIMAGE_DOS_HEADER module::get_dos_header() const
{
return reinterpret_cast<PIMAGE_DOS_HEADER>(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<PIMAGE_SECTION_HEADER> module::get_section_headers() const
{
std::vector<PIMAGE_SECTION_HEADER> 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<std::uint8_t*>(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<void*>(proc_name);
if (!target_function) return nullptr;
auto* header = this->get_optional_header();
if (!header) return nullptr;
auto* import_descriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(this->get_ptr() + header->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (import_descriptor->Name)
{
if (!_stricmp(reinterpret_cast<char*>(this->get_ptr() + import_descriptor->Name), module_name.data()))
{
auto* original_thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor->
OriginalFirstThunk + this->get_ptr());
auto* thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(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<char*>(ordinal_number)) ==
target_function)
{
return reinterpret_cast<void**>(&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<void>("RtlAdjustPrivilege", 19, true, false, &data);
ntdll.invoke_pascal<void>("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<void*>(proc_name);
if (!target_function) return nullptr;
auto* header = this->get_optional_header();
if (!header) return nullptr;
auto* import_descriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(this->get_ptr() + header->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (import_descriptor->Name)
{
if (!_stricmp(reinterpret_cast<char*>(this->get_ptr() + import_descriptor->Name), module_name.data()))
{
auto* original_thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(import_descriptor->
OriginalFirstThunk + this->get_ptr());
auto* thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(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<char*>(ordinal_number)) ==
target_function)
{
return reinterpret_cast<void**>(&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<void>("RtlAdjustPrivilege", 19, true, false, &data);
ntdll.invoke_pascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, 6, &data);
}
}

View File

@ -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 <typename T>
T get_proc(const std::string& process) const
{
if (!this->is_valid()) T{};
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
}
template <typename T>
std::function<T> get(const std::string& process) const
{
if (!this->is_valid()) std::function<T>();
return reinterpret_cast<T*>(this->get_proc<void*>(process));
}
template <typename T, typename... Args>
T invoke(const std::string& process, Args ... args) const
{
auto method = this->get<T(__cdecl)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T invoke_pascal(const std::string& process, Args ... args) const
{
auto method = this->get<T(__stdcall)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T invoke_this(const std::string& process, void* this_ptr, Args ... args) const
{
auto method = this->get<T(__thiscall)(void*, Args ...)>(this_ptr, process);
if (method) return method(args...);
return T();
}
std::vector<PIMAGE_SECTION_HEADER> 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 <typename T>
T get_proc(const std::string& process) const
{
if (!this->is_valid()) T{};
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
}
template <typename T>
std::function<T> get(const std::string& process) const
{
if (!this->is_valid()) std::function<T>();
return reinterpret_cast<T*>(this->get_proc<void*>(process));
}
template <typename T, typename... Args>
T invoke(const std::string& process, Args ... args) const
{
auto method = this->get<T(__cdecl)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T invoke_pascal(const std::string& process, Args ... args) const
{
auto method = this->get<T(__stdcall)(Args ...)>(process);
if (method) return method(args...);
return T();
}
template <typename T, typename... Args>
T invoke_this(const std::string& process, void* this_ptr, Args ... args) const
{
auto method = this->get<T(__thiscall)(void*, Args ...)>(this_ptr, process);
if (method) return method(args...);
return T();
}
std::vector<PIMAGE_SECTION_HEADER> 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();
}

View File

@ -1,58 +1,55 @@
#include <std_include.hpp>
#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 <std_include.hpp>
#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;
}
}

View File

@ -1,84 +1,81 @@
#pragma once
#include "memory.hpp"
namespace utils
{
namespace string
{
template <size_t Buffers, size_t MinBufferSize>
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<char>(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 <size_t Buffers, size_t MinBufferSize>
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<char>(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 = " ");
}