Skip to content

Commit

Permalink
Impliment Event Queueing (#35)
Browse files Browse the repository at this point in the history
* Impliment Event Queueing

* Only call the initial callback function in a Many event

This is due to the fact that Luau is single threaded and it will be never called with > 1 callback

* Add warning if queue size is > 64
  • Loading branch information
sasial-dev authored Dec 31, 2023
1 parent c4834fe commit 325a4a9
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 8 deletions.
2 changes: 2 additions & 0 deletions zap/src/output/luau/client.luau
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ end
local reliable = game:GetService("ReplicatedStorage"):WaitForChild("ZAP_RELIABLE")
local unreliable = game:GetService("ReplicatedStorage"):WaitForChild("ZAP_UNRELIABLE")

local event_queue: { [number]: { any } }

local time = 0

game:GetService("RunService").Heartbeat:Connect(function(dt)
Expand Down
106 changes: 98 additions & 8 deletions zap/src/output/luau/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,47 @@ impl<'src> ClientOutput<'src> {
self.push_stmts(&des::gen(&ev.data, "value", true));

if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync {
self.push_line(&format!("if events[{id}] then"))
self.push_line(&format!("if events[{id}] then"));
} else {
self.push_line(&format!("for _, cb in events[{id}] do"))
self.push_line(&format!("if events[{id}][1] then"));
}

self.indent();

if ev.call == EvCall::ManySync || ev.call == EvCall::ManyAsync {
self.push_line(&format!("for _, cb in events[{id}] do"));
self.indent();
}

match ev.call {
EvCall::SingleSync => self.push_line(&format!("events[{id}](value)")),
EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], value)")),
EvCall::ManySync => self.push_line("cb(value)"),
EvCall::ManyAsync => self.push_line("task.spawn(cb, value)"),
}

if ev.call == EvCall::ManySync || ev.call == EvCall::ManyAsync {
self.dedent();
self.push_line("end");
}

self.dedent();
self.push_line("else");
self.indent();

self.push_line(&format!("table.insert(event_queue[{id}], value)"));

self.push_line(&format!("if #event_queue[{id}] > 64 then"));
self.indent();

self.push_line(&format!(
"warn(`[ZAP] {{#event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)",
ev.name
));

self.dedent();
self.push_line("end");

self.dedent();
self.push_line("end");

Expand Down Expand Up @@ -199,20 +226,47 @@ impl<'src> ClientOutput<'src> {
self.push_stmts(&des::gen(&ev.data, "value", self.config.write_checks));

if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync {
self.push_line(&format!("if events[{id}] then"))
self.push_line(&format!("if events[{id}] then"));
} else {
self.push_line(&format!("for _, cb in events[{id}] do"))
self.push_line(&format!("if events[{id}][1] then"));
}

self.indent();

if ev.call == EvCall::ManySync || ev.call == EvCall::ManyAsync {
self.push_line(&format!("for _, cb in events[{id}] do"));
self.indent();
}

match ev.call {
EvCall::SingleSync => self.push_line(&format!("events[{id}](value)")),
EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], value)")),
EvCall::ManySync => self.push_line("cb(value)"),
EvCall::ManyAsync => self.push_line("task.spawn(cb, value)"),
}

if ev.call == EvCall::ManySync || ev.call == EvCall::ManyAsync {
self.dedent();
self.push_line("end");
}

self.dedent();
self.push_line("else");
self.indent();

self.push_line(&format!("table.insert(event_queue[{id}], value)"));

self.push_line(&format!("if #event_queue[{id}] > 64 then"));
self.indent();

self.push_line(&format!(
"warn(`[ZAP] {{#event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)",
ev.name
));

self.dedent();
self.push_line("end");

self.dedent();
self.push_line("end");

Expand Down Expand Up @@ -253,12 +307,20 @@ impl<'src> ClientOutput<'src> {
fn push_callback_lists(&mut self) {
self.push_line(&format!("local events = table.create({})", self.config.evdecls.len()));

for (i, _) in self.config.evdecls.iter().enumerate().filter(|(_, ev_decl)| {
ev_decl.from == EvSource::Server && matches!(ev_decl.call, EvCall::ManyAsync | EvCall::ManySync)
}) {
for (i, ev_decl) in self
.config
.evdecls
.iter()
.enumerate()
.filter(|(_, ev_decl)| ev_decl.from == EvSource::Server)
{
let id = i + 1;

self.push_line(&format!("events[{id}] = {{}}"));
if ev_decl.call == EvCall::ManyAsync || ev_decl.call == EvCall::ManySync {
self.push_line(&format!("events[{id}] = {{}}"));
}

self.push_line(&format!("event_queue[{id}] = {{}}"));
}
}

Expand Down Expand Up @@ -336,6 +398,20 @@ impl<'src> ClientOutput<'src> {

self.push_line(&format!("events[{id}] = {callback}"));

self.push_line(&format!("for _, value in event_queue[{id}] do"));
self.indent();

if ev.call == EvCall::SingleSync {
self.push_line(&format!("{callback}(value)"))
} else {
self.push_line(&format!("task.spawn({callback}, value)"))
}

self.dedent();
self.push_line("end");

self.push_line(&format!("event_queue[{id}] = {{}}"));

self.dedent();
self.push_line("end,");
}
Expand All @@ -354,6 +430,20 @@ impl<'src> ClientOutput<'src> {

self.push_line(&format!("table.insert(events[{id}], {callback})"));

self.push_line(&format!("for _, value in event_queue[{id}] do"));
self.indent();

if ev.call == EvCall::ManySync {
self.push_line(&format!("{callback}(value)"))
} else {
self.push_line(&format!("task.spawn({callback}, value)"))
}

self.dedent();
self.push_line("end");

self.push_line(&format!("event_queue[{id}] = {{}}"));

self.dedent();
self.push_line("end,");
}
Expand Down

0 comments on commit 325a4a9

Please sign in to comment.