Skip to content

Commit

Permalink
Update scheduler & event handler
Browse files Browse the repository at this point in the history
  • Loading branch information
alicealys committed Jul 3, 2021
1 parent 874f2c2 commit 696f5d3
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 208 deletions.
13 changes: 6 additions & 7 deletions src/component/notifies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,17 @@ namespace notifies

scheduler::once([hidden, _cmd, message, clientNum]()
{
const auto teamchat = _cmd == "say_team"s;
const scripting::entity level{*game::levelEntityId};
const auto _player = scripting::call("getEntByNum", {clientNum});

if (_player.get_raw().type != game::SCRIPT_OBJECT)
if (_player.get_raw().type == game::SCRIPT_OBJECT)
{
return;
}

const auto player = _player.as<scripting::entity>();
const auto player = _player.as<scripting::entity>();

scripting::notify(level, _cmd, {player, message});
scripting::notify(player, _cmd, {message});
scripting::notify(level, "say", {player, message, teamchat});
scripting::notify(player, "say", {message, teamchat});
}
});

for (const auto& callback : player_say_callbacks)
Expand Down
150 changes: 126 additions & 24 deletions src/game/scripting/lua/event_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,59 +14,161 @@ namespace scripting::lua
{
this->remove(handle);
};

event_listener_handle_type["endon"] = [this](const event_listener_handle& handle, const entity& entity, const std::string& event)
{
this->add_endon_condition(handle, entity, event);
};
}

void event_handler::dispatch(const event& event)
{
std::vector<sol::lua_value> arguments;
bool has_built_arguments = false;
event_arguments arguments{};

for (const auto& argument : event.arguments)
callbacks_.access([&](task_list& tasks)
{
arguments.emplace_back(convert(this->state_, argument));
}

this->dispatch_to_specific_listeners(event, arguments);
}
this->merge_callbacks();
this->handle_endon_conditions(event);

void event_handler::dispatch_to_specific_listeners(const event& event,
const event_arguments& arguments)
{
for (auto listener : this->event_listeners_)
{
if (listener->event == event.name && listener->entity == event.entity)
for (auto i = tasks.begin(); i != tasks.end();)
{
if (listener->is_volatile)
if (i->event != event.name || i->entity != event.entity)
{
++i;
continue;
}

if (!i->is_deleted)
{
this->event_listeners_.remove(listener);
if (!has_built_arguments)
{
has_built_arguments = true;
arguments = this->build_arguments(event);
}

handle_error(i->callback(sol::as_args(arguments)));
}

handle_error(listener->callback(sol::as_args(arguments)));
if (i->is_volatile || i->is_deleted)
{
i = tasks.erase(i);
}
else
{
++i;
}
}
}
});
}

event_listener_handle event_handler::add_event_listener(event_listener&& listener)
{
const uint64_t id = ++this->current_listener_id_;
listener.id = id;
this->event_listeners_.add(std::move(listener));
listener.is_deleted = false;

new_callbacks_.access([&listener](task_list& tasks)
{
tasks.emplace_back(std::move(listener));
});

return {id};
}

void event_handler::add_endon_condition(const event_listener_handle& handle, const entity& entity,
const std::string& event)
{
auto merger = [&](task_list& tasks)
{
for (auto& task : tasks)
{
if (task.id == handle.id)
{
task.endon_conditions.emplace_back(entity, event);
}
}
};

callbacks_.access([&](task_list& tasks)
{
merger(tasks);
new_callbacks_.access(merger);
});
}

void event_handler::clear()
{
this->event_listeners_.clear();
callbacks_.access([&](task_list& tasks)
{
new_callbacks_.access([&](task_list& new_tasks)
{
new_tasks.clear();
tasks.clear();
});
});
}

void event_handler::remove(const event_listener_handle& handle)
{
for (const auto task : this->event_listeners_)
auto mask_as_deleted = [&](task_list& tasks)
{
if (task->id == handle.id)
for (auto& task : tasks)
{
this->event_listeners_.remove(task);
return;
if (task.id == handle.id)
{
task.is_deleted = true;
break;
}
}
};

callbacks_.access(mask_as_deleted);
new_callbacks_.access(mask_as_deleted);
}

void event_handler::merge_callbacks()
{
callbacks_.access([&](task_list& tasks)
{
new_callbacks_.access([&](task_list& new_tasks)
{
tasks.insert(tasks.end(), std::move_iterator(new_tasks.begin()),
std::move_iterator(new_tasks.end()));
new_tasks = {};
});
});
}

void event_handler::handle_endon_conditions(const event& event)
{
auto deleter = [&](task_list& tasks)
{
for (auto& task : tasks)
{
for (auto& condition : task.endon_conditions)
{
if (condition.first == event.entity && condition.second == event.name)
{
task.is_deleted = true;
break;
}
}
}
};

callbacks_.access(deleter);
}

event_arguments event_handler::build_arguments(const event& event) const
{
event_arguments arguments;

for (const auto& argument : event.arguments)
{
arguments.emplace_back(convert(this->state_, argument));
}

return arguments;
}
}
}
19 changes: 13 additions & 6 deletions src/game/scripting/lua/event_handler.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#pragma once
#include <utils/concurrent_list.hpp>

namespace scripting::lua
{
Expand All @@ -9,7 +8,7 @@ namespace scripting::lua
class event_listener_handle
{
public:
unsigned long long id = 0;
uint64_t id = 0;
};

class event_listener final : public event_listener_handle
Expand All @@ -19,6 +18,8 @@ namespace scripting::lua
entity entity{};
event_callback callback = {};
bool is_volatile = false;
bool is_deleted = false;
std::vector<std::pair<scripting::entity, std::string>> endon_conditions{};
};

class event_handler final
Expand All @@ -42,10 +43,16 @@ namespace scripting::lua
sol::state& state_;
std::atomic_int64_t current_listener_id_ = 0;

utils::concurrent_list<event_listener> event_listeners_;

void dispatch_to_specific_listeners(const event& event, const event_arguments& arguments);
using task_list = std::vector<event_listener>;
utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;

void remove(const event_listener_handle& handle);
void merge_callbacks();
void handle_endon_conditions(const event& event);

void add_endon_condition(const event_listener_handle& handle, const entity& entity, const std::string& event);

event_arguments build_arguments(const event& event) const;
};
}
}
Loading

0 comments on commit 696f5d3

Please sign in to comment.