2019-01-13 05:16:19 -05:00
|
|
|
#include <std_include.hpp>
|
2019-01-13 15:28:05 -05:00
|
|
|
#include "notification.hpp"
|
|
|
|
#include "utils/io.hpp"
|
2019-01-16 10:19:21 -05:00
|
|
|
#include "scheduler.hpp"
|
2019-01-13 05:16:19 -05:00
|
|
|
|
2019-01-13 13:03:46 -05:00
|
|
|
utils::hook scripting::start_hook_;
|
|
|
|
utils::hook scripting::stop_hook_;
|
|
|
|
|
|
|
|
std::mutex scripting::mutex_;
|
|
|
|
std::vector<std::function<void()>> scripting::start_callbacks_;
|
|
|
|
std::vector<std::function<void()>> scripting::stop_callbacks_;
|
|
|
|
|
2019-01-13 15:28:05 -05:00
|
|
|
void scripting::post_start()
|
|
|
|
{
|
2019-01-16 10:19:21 -05:00
|
|
|
on_start([this]()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2019-01-20 07:21:43 -05:00
|
|
|
this->load_scripts();
|
|
|
|
notification::listen([this](game::scripting::event* event)
|
|
|
|
{
|
|
|
|
for(const auto& script : this->scripts_)
|
|
|
|
{
|
|
|
|
script->get_event_handler()->dispatch(event);
|
|
|
|
}
|
|
|
|
});
|
2019-01-16 10:19:21 -05:00
|
|
|
}
|
|
|
|
catch (std::exception& e)
|
|
|
|
{
|
2019-01-17 15:05:48 -05:00
|
|
|
propagate_error(e);
|
2019-01-16 10:19:21 -05:00
|
|
|
}
|
|
|
|
});
|
2019-01-13 15:28:05 -05:00
|
|
|
on_stop([this]()
|
|
|
|
{
|
2019-01-20 07:21:43 -05:00
|
|
|
this->scripts_.clear();
|
2019-01-13 15:28:05 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-13 13:03:46 -05:00
|
|
|
void scripting::post_load()
|
|
|
|
{
|
|
|
|
start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), []()
|
2019-01-13 05:16:19 -05:00
|
|
|
{
|
2019-01-13 13:03:46 -05:00
|
|
|
start_execution();
|
2019-01-19 20:58:28 -05:00
|
|
|
reinterpret_cast<void(*)()>(start_hook_.get_original())();
|
2019-01-13 13:03:46 -05:00
|
|
|
}, HOOK_CALL)->install()->quick();
|
|
|
|
|
|
|
|
stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), []()
|
|
|
|
{
|
|
|
|
stop_execution();
|
2019-01-19 20:58:28 -05:00
|
|
|
reinterpret_cast<void(*)()>(stop_hook_.get_original())();
|
2019-01-13 13:03:46 -05:00
|
|
|
}, HOOK_CALL)->install()->quick();
|
2019-01-13 15:28:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void scripting::pre_destroy()
|
|
|
|
{
|
2019-01-20 07:21:43 -05:00
|
|
|
this->scripts_.clear();
|
2019-01-13 15:28:05 -05:00
|
|
|
start_callbacks_.clear();
|
|
|
|
stop_callbacks_.clear();
|
|
|
|
}
|
2019-01-13 13:03:46 -05:00
|
|
|
|
2019-01-20 07:21:43 -05:00
|
|
|
void scripting::load_scripts()
|
2019-01-13 13:03:46 -05:00
|
|
|
{
|
2019-01-13 15:28:05 -05:00
|
|
|
const auto scripts = utils::io::list_files("open-iw5/scripts/");
|
|
|
|
|
|
|
|
for (const auto& script : scripts)
|
|
|
|
{
|
|
|
|
if (script.substr(script.find_last_of('.') + 1) == "chai")
|
|
|
|
{
|
2019-01-13 15:53:52 -05:00
|
|
|
try
|
|
|
|
{
|
2019-01-20 07:21:43 -05:00
|
|
|
auto context = std::make_unique<game::scripting::context>();
|
|
|
|
context->get_chai()->eval_file(script);
|
|
|
|
this->scripts_.push_back(std::move(context));
|
2019-01-13 15:53:52 -05:00
|
|
|
}
|
2019-01-16 10:19:21 -05:00
|
|
|
catch (chaiscript::exception::eval_error& e)
|
2019-01-13 16:59:01 -05:00
|
|
|
{
|
2019-01-16 10:19:21 -05:00
|
|
|
throw std::runtime_error(e.pretty_print());
|
2019-01-13 15:53:52 -05:00
|
|
|
}
|
2019-01-13 15:28:05 -05:00
|
|
|
}
|
|
|
|
}
|
2019-01-13 13:03:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void scripting::on_start(const std::function<void()>& callback)
|
|
|
|
{
|
|
|
|
std::lock_guard _(mutex_);
|
|
|
|
start_callbacks_.push_back(callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void scripting::on_stop(const std::function<void()>& callback)
|
|
|
|
{
|
|
|
|
std::lock_guard _(mutex_);
|
|
|
|
stop_callbacks_.push_back(callback);
|
|
|
|
}
|
|
|
|
|
2019-01-17 15:05:48 -05:00
|
|
|
void scripting::propagate_error(const std::exception& e)
|
2019-01-16 16:44:50 -05:00
|
|
|
{
|
|
|
|
printf("\n******* Script execution error *******\n");
|
|
|
|
printf("%s\n", e.what());
|
|
|
|
printf("**************************************\n\n");
|
|
|
|
|
|
|
|
scheduler::error("Script execution error\n(see console for actual details)\n", 5);
|
|
|
|
}
|
|
|
|
|
2019-01-13 13:03:46 -05:00
|
|
|
void scripting::start_execution()
|
|
|
|
{
|
2019-01-13 15:28:05 -05:00
|
|
|
decltype(start_callbacks_) copy;
|
2019-01-13 13:03:46 -05:00
|
|
|
{
|
|
|
|
std::lock_guard _(mutex_);
|
|
|
|
copy = start_callbacks_;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& callback : copy)
|
|
|
|
{
|
|
|
|
callback();
|
2019-01-13 05:16:19 -05:00
|
|
|
}
|
2019-01-13 13:03:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void scripting::stop_execution()
|
|
|
|
{
|
2019-01-13 15:28:05 -05:00
|
|
|
decltype(stop_callbacks_) copy;
|
2019-01-13 13:03:46 -05:00
|
|
|
{
|
|
|
|
std::lock_guard _(mutex_);
|
|
|
|
copy = stop_callbacks_;
|
2019-01-13 15:28:05 -05:00
|
|
|
std::reverse(copy.begin(), copy.end());
|
2019-01-13 13:03:46 -05:00
|
|
|
}
|
2019-01-13 06:07:19 -05:00
|
|
|
|
2019-01-13 13:03:46 -05:00
|
|
|
for (const auto& callback : copy)
|
|
|
|
{
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
}
|
2019-01-13 06:07:19 -05:00
|
|
|
|
2019-01-13 05:16:19 -05:00
|
|
|
REGISTER_MODULE(scripting)
|