354d022967
commit f44d146e4ac906ff898e8968c6857fd2280f6d20 Author: project-bo4 <127137346+project-bo4@users.noreply.github.com> Date: Thu May 11 13:39:29 2023 -0700 remove lpc package from repository commit 29fb0f63e50de468ab0b9db35f7e8fdadf58afc3 Author: project-bo4 <themanwithantidote@gmail.com> Date: Thu May 11 13:06:13 2023 -0700 generic improvements + added identity configuration + objectstore improvements + added battlenet 'US' servers to blocklist + some other minor improvements commit 5d5e31099ebcce5a637b9a02d4936a97fb0802a7 Author: project-bo4 <themanwithantidote@gmail.com> Date: Sat Mar 25 16:32:52 2023 -0700 lpc improvements + fix lpc issue with foreign languages(non-english) not being considered in listing + check lpc files pre-start and warn user if missing any of core items commit 2de1a54b6f4cc5c44dc906871021cfbc85057ca9 Author: project-bo4 <themanwithantidote@gmail.com> Date: Thu Mar 23 12:45:56 2023 -0700 demonware improvements + handle object store uploadUserObject + silence bdUNK125 commit 710dcc3ec6178071d67c27e5bf6705f08cabe7e2 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 13:43:56 2023 -0700 forgot to update names commit 217682dfb07b35f7a09399fb2698924bb7fe8b77 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 11:09:18 2023 -0700 upload lpc and update readme commit 83f812b33b90791a8d13b9468f27da51e0a4f2b9 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 10:53:43 2023 -0700 demonware emulator + demonware emulator + platform name and id + xxhash and picoproto - remove g_runframe hook -disable discovery(save time) + improvements to utils + add new resources
184 lines
3.7 KiB
C++
184 lines
3.7 KiB
C++
#include <std_include.hpp>
|
|
#include "loader/component_loader.hpp"
|
|
|
|
#include "scheduler.hpp"
|
|
|
|
#include <cassert>
|
|
#include <utils/hook.hpp>
|
|
#include <utils/concurrency.hpp>
|
|
#include <utils/thread.hpp>
|
|
|
|
namespace scheduler
|
|
{
|
|
namespace
|
|
{
|
|
struct task
|
|
{
|
|
std::function<bool()> handler{};
|
|
std::chrono::milliseconds interval{};
|
|
std::chrono::high_resolution_clock::time_point last_call{};
|
|
};
|
|
|
|
using task_list = std::vector<task>;
|
|
|
|
class task_pipeline
|
|
{
|
|
public:
|
|
void add(task&& task)
|
|
{
|
|
new_callbacks_.access([&task](task_list& tasks)
|
|
{
|
|
tasks.emplace_back(std::move(task));
|
|
});
|
|
}
|
|
|
|
void execute()
|
|
{
|
|
callbacks_.access([&](task_list& tasks)
|
|
{
|
|
this->merge_callbacks();
|
|
|
|
for (auto i = tasks.begin(); i != tasks.end();)
|
|
{
|
|
const auto now = std::chrono::high_resolution_clock::now();
|
|
const auto diff = now - i->last_call;
|
|
|
|
if (diff < i->interval)
|
|
{
|
|
++i;
|
|
continue;
|
|
}
|
|
|
|
i->last_call = now;
|
|
|
|
const auto res = i->handler();
|
|
if (res == cond_end)
|
|
{
|
|
i = tasks.erase(i);
|
|
}
|
|
else
|
|
{
|
|
++i;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private:
|
|
utils::concurrency::container<task_list> new_callbacks_;
|
|
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
|
|
|
|
void merge_callbacks()
|
|
{
|
|
callbacks_.access([&](task_list& tasks)
|
|
{
|
|
new_callbacks_.access([&](task_list& new_tasks)
|
|
{
|
|
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()),
|
|
std::move_iterator<task_list::iterator>(new_tasks.end()));
|
|
new_tasks = {};
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
volatile bool kill = false;
|
|
std::thread thread;
|
|
task_pipeline pipelines[pipeline::count];
|
|
|
|
utils::hook::detour r_end_frame_hook;
|
|
utils::hook::detour g_run_frame_hook;
|
|
utils::hook::detour main_frame_hook;
|
|
|
|
void execute(const pipeline type)
|
|
{
|
|
assert(type >= 0 && type < pipeline::count);
|
|
pipelines[type].execute();
|
|
}
|
|
|
|
void r_end_frame_stub()
|
|
{
|
|
execute(pipeline::renderer);
|
|
r_end_frame_hook.invoke<void>();
|
|
}
|
|
|
|
void server_frame_stub()
|
|
{
|
|
g_run_frame_hook.invoke<void>();
|
|
execute(pipeline::server);
|
|
}
|
|
|
|
void main_frame_stub()
|
|
{
|
|
main_frame_hook.invoke<void>();
|
|
execute(pipeline::main);
|
|
}
|
|
}
|
|
|
|
void schedule(const std::function<bool()>& callback, const pipeline type,
|
|
const std::chrono::milliseconds delay)
|
|
{
|
|
assert(type >= 0 && type < pipeline::count);
|
|
|
|
task task;
|
|
task.handler = callback;
|
|
task.interval = delay;
|
|
task.last_call = std::chrono::high_resolution_clock::now();
|
|
|
|
pipelines[type].add(std::move(task));
|
|
}
|
|
|
|
void loop(const std::function<void()>& callback, const pipeline type,
|
|
const std::chrono::milliseconds delay)
|
|
{
|
|
schedule([callback]()
|
|
{
|
|
callback();
|
|
return cond_continue;
|
|
}, type, delay);
|
|
}
|
|
|
|
void once(const std::function<void()>& callback, const pipeline type,
|
|
const std::chrono::milliseconds delay)
|
|
{
|
|
schedule([callback]()
|
|
{
|
|
callback();
|
|
return cond_end;
|
|
}, type, delay);
|
|
}
|
|
|
|
class component final : public component_interface
|
|
{
|
|
public:
|
|
void pre_start() override
|
|
{
|
|
thread = utils::thread::create_named_thread("Async Scheduler", []()
|
|
{
|
|
while (!kill)
|
|
{
|
|
execute(pipeline::async);
|
|
std::this_thread::sleep_for(10ms);
|
|
}
|
|
});
|
|
}
|
|
|
|
void post_unpack() override
|
|
{
|
|
r_end_frame_hook.create(0x14361E260_g, r_end_frame_stub); // R_EndFrame
|
|
//main_frame_hook.create(0x14288BAE0_g, main_frame_stub); // Com_Frame
|
|
//g_run_frame_hook.create(0x142D08FC0_g, server_frame_stub); // G_RunFrame
|
|
}
|
|
|
|
void pre_destroy() override
|
|
{
|
|
kill = true;
|
|
if (thread.joinable())
|
|
{
|
|
thread.join();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
REGISTER_COMPONENT(scheduler::component) |