1+ #pragma once
2+
3+ #include " entt.hpp"
4+ #include " fs.hpp"
5+ #include " lua.hpp"
6+
7+ namespace ecs {
8+ typedef fs::LuaFile Fd;
9+ typedef std::unique_ptr<lua::ScopedState> State;
10+ typedef sol::protected_function Tick;
11+
12+ inline entt::registry registry;
13+
14+ template <glue::GameEvent>
15+ struct EventHandler {
16+ sol::protected_function handler;
17+ };
18+
19+ [[noreturn]] static void LatentTick () {
20+ static const auto tick_rate = std::chrono::milliseconds (cfg::LoadOrDefault ()->tick_rate );
21+
22+ for (;;) {
23+ std::this_thread::sleep_for (tick_rate);
24+
25+ SKSE::GetTaskInterface ()->AddTask ([] {
26+ auto view = registry.view <const Tick>();
27+ for (auto [_, tick] : view.each ()) tick ();
28+ });
29+ }
30+ }
31+
32+ inline auto EnableLatentTick () { std::jthread (&LatentTick).detach (); }
33+
34+ inline auto BindEventHandlersToEntity (const entt::entity& ent,
35+ std::unique_ptr<lua::ScopedState>& state) {
36+ magic_enum::enum_for_each<glue::GameEvent>([&](auto val) {
37+ constexpr auto func_name = glue::GetLuaFuncName<val>();
38+ state->logger ->trace (" Checking handler: {}" , func_name);
39+ sol::protected_function func = state->skylua [func_name];
40+ if (func.valid ()) {
41+ state->logger ->info (" Bound {}" , func_name);
42+ registry.emplace <EventHandler<val>>(ent, std::move (func));
43+ }
44+ });
45+ }
46+
47+ inline auto AddLuaFileToRegistry (const fs::LuaFile& fd) {
48+ const auto e = registry.create ();
49+ auto state = lua::ScopedState::FromPath (fd);
50+ if (auto maybe_tick = state->MaybeGetTick ()) {
51+ state->logger ->trace (" Tick registered for: {}" , state->name );
52+ registry.emplace <Tick>(e, maybe_tick.value ());
53+ }
54+ BindEventHandlersToEntity (e, state);
55+ registry.emplace <State>(e, std::move (state));
56+ registry.emplace <Fd>(e, fd);
57+ }
58+
59+ inline auto UnbindAllEventHandlersForEntity (const entt::entity& e) {
60+ magic_enum::enum_for_each<glue::GameEvent>([&](auto val) {
61+ if (auto maybe_handler = registry.try_get <EventHandler<val>>(e)) {
62+ maybe_handler->handler .abandon ();
63+ }
64+ });
65+
66+ if (auto maybe_tick = registry.try_get <Tick>(e)) {
67+ maybe_tick->abandon ();
68+ }
69+ }
70+
71+ inline auto RebuildEntityForPath (const fs::LuaFile& fd) {
72+ for (auto e : registry.view <const Fd>()) {
73+ auto ent_fd = registry.get <const Fd>(e);
74+ if (ent_fd.relative_path_str == fd.relative_path_str ) {
75+ UnbindAllEventHandlersForEntity (e);
76+ registry.destroy (e);
77+ AddLuaFileToRegistry (ent_fd);
78+ }
79+ }
80+ }
81+ }
0 commit comments