diff --git a/zap/src/config.rs b/zap/src/config.rs index aa8a4129..90775a0a 100644 --- a/zap/src/config.rs +++ b/zap/src/config.rs @@ -31,9 +31,55 @@ pub struct Config<'src> { pub disable_fire_all: bool, } -impl<'src> Config<'src> { - pub fn event_id_ty(&self) -> NumTy { - NumTy::from_f64(1.0, (self.evdecls.len() + self.fndecls.len()) as f64) +impl Config<'_> { + pub fn server_reliable_count(&self) -> usize { + let reliable_count = self + .evdecls + .iter() + .filter(|evdecl| evdecl.from == EvSource::Client && evdecl.evty == EvType::Reliable) + .count(); + + reliable_count + self.fndecls.len() + } + + pub fn server_unreliable_count(&self) -> usize { + self.evdecls + .iter() + .filter(|evdecl| evdecl.from == EvSource::Client && evdecl.evty == EvType::Unreliable) + .count() + } + + pub fn client_reliable_count(&self) -> usize { + let reliable_count = self + .evdecls + .iter() + .filter(|evdecl| evdecl.from == EvSource::Server && evdecl.evty == EvType::Reliable) + .count(); + + reliable_count + self.fndecls.len() + } + + pub fn client_unreliable_count(&self) -> usize { + self.evdecls + .iter() + .filter(|evdecl| evdecl.from == EvSource::Server && evdecl.evty == EvType::Unreliable) + .count() + } + + pub fn server_reliable_ty(&self) -> NumTy { + NumTy::from_f64(0.0, self.server_reliable_count() as f64 - 1.0) + } + + pub fn server_unreliable_ty(&self) -> NumTy { + NumTy::from_f64(0.0, self.server_unreliable_count() as f64 - 1.0) + } + + pub fn client_reliable_ty(&self) -> NumTy { + NumTy::from_f64(0.0, self.client_reliable_count() as f64 - 1.0) + } + + pub fn client_unreliable_ty(&self) -> NumTy { + NumTy::from_f64(0.0, self.client_unreliable_count() as f64 - 1.0) } } @@ -78,7 +124,8 @@ pub struct FnDecl<'src> { pub call: FnCall, pub args: Vec>, pub rets: Option>>, - pub id: usize, + pub client_id: usize, + pub server_id: usize, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/zap/src/output/luau/client.rs b/zap/src/output/luau/client.rs index ab2f05d8..075394d1 100644 --- a/zap/src/output/luau/client.rs +++ b/zap/src/output/luau/client.rs @@ -1,7 +1,10 @@ use crate::{ - config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, Parameter, TyDecl, YieldType}, + config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, NumTy, Parameter, TyDecl, YieldType}, irgen::{des, ser}, - output::{get_named_values, get_unnamed_values}, + output::{ + get_named_values, get_unnamed_values, + luau::{event_queue_table_name, events_table_name}, + }, }; use super::Output; @@ -12,7 +15,7 @@ struct ClientOutput<'src> { buf: String, } -impl<'a> Output for ClientOutput<'a> { +impl Output for ClientOutput<'_> { fn push(&mut self, s: &str) { self.buf.push_str(s); } @@ -172,10 +175,12 @@ impl<'src> ClientOutput<'src> { self.indent(); + let client_reliable_ty = self.config.client_reliable_ty(); + self.push_line(&format!( "local id = buffer.read{}(buff, read({}))", - self.config.event_id_ty(), - self.config.event_id_ty().size() + client_reliable_ty, + client_reliable_ty.size() )); } @@ -228,21 +233,21 @@ impl<'src> ClientOutput<'src> { } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { - self.push_line(&format!("if events[{id}] then")); + self.push_line(&format!("if reliable_events[{id}] then")); } else { - self.push_line(&format!("if events[{id}][1] then")); + self.push_line(&format!("if reliable_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.push_line(&format!("for _, cb in reliable_events[{id}] do")); self.indent(); } match ev.call { - EvCall::SingleSync => self.push_line(&format!("events[{id}]({values})")), - EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], {values})")), + EvCall::SingleSync => self.push_line(&format!("reliable_events[{id}]({values})")), + EvCall::SingleAsync => self.push_line(&format!("task.spawn(reliable_events[{id}], {values})")), EvCall::ManySync => self.push_line(&format!("cb({values})")), EvCall::ManyAsync => self.push_line(&format!("task.spawn(cb, {values})")), } @@ -258,15 +263,15 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { if ev.data.len() > 1 { - self.push_line(&format!("table.insert(event_queue[{id}], {{ {values} }})")); + self.push_line(&format!("table.insert(reliable_event_queue[{id}], {{ {values} }})")); } else { - self.push_line(&format!("table.insert(event_queue[{id}], value)")); + self.push_line(&format!("table.insert(reliable_event_queue[{id}], value)")); } - self.push_line(&format!("if #event_queue[{id}] > 64 then")); + self.push_line(&format!("if #reliable_event_queue[{id}] > 64 then")); } else { - self.push_line(&format!("event_queue[{id}] += 1")); - self.push_line(&format!("if event_queue[{id}] > 16 then")); + self.push_line(&format!("reliable_event_queue[{id}] += 1")); + self.push_line(&format!("if reliable_event_queue[{id}] > 16 then")); } self.indent(); @@ -279,7 +284,7 @@ impl<'src> ClientOutput<'src> { } self.push(&format!( - "event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)\n", + "reliable_event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)\n", ev.name )); @@ -293,7 +298,7 @@ impl<'src> ClientOutput<'src> { } fn push_fn_callback(&mut self, first: bool, fndecl: &FnDecl) { - let id = fndecl.id; + let client_id = fndecl.client_id; self.push_indent(); @@ -306,7 +311,7 @@ impl<'src> ClientOutput<'src> { // push_line is not used here as indent was pushed above // and we don't want to push it twice, especially after // the if/elseif - self.push(&format!("id == {id} then")); + self.push(&format!("id == {client_id} then")); self.push("\n"); self.indent(); @@ -321,7 +326,7 @@ impl<'src> ClientOutput<'src> { self.push_stmts(&des::gen(data, &get_unnamed_values("value", data.len()), true)); } - self.push_line(&format!("local thread = event_queue[{id}][call_id]")); + self.push_line(&format!("local thread = reliable_event_queue[{client_id}][call_id]")); self.push_line("-- When using actors it's possible for multiple Zap clients to exist, but only one called the Zap remote function."); self.push_line("if thread then"); self.indent(); @@ -336,7 +341,7 @@ impl<'src> ClientOutput<'src> { self.dedent(); self.push_line("end"); - self.push_line(&format!("event_queue[{id}][call_id] = nil")); + self.push_line(&format!("reliable_event_queue[{client_id}][call_id] = nil")); self.dedent(); } @@ -384,10 +389,12 @@ impl<'src> ClientOutput<'src> { self.push_line("incoming_read = 0"); self.push_line("incoming_ipos = 0"); + let client_unreliable_ty = self.config.client_unreliable_ty(); + self.push_line(&format!( "local id = buffer.read{}(buff, read({}))", - self.config.event_id_ty(), - self.config.event_id_ty().size() + client_unreliable_ty, + client_unreliable_ty.size() )); } @@ -423,21 +430,21 @@ impl<'src> ClientOutput<'src> { } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { - self.push_line(&format!("if events[{id}] then")); + self.push_line(&format!("if unreliable_events[{id}] then")); } else { - self.push_line(&format!("if events[{id}][1] then")); + self.push_line(&format!("if unreliable_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.push_line(&format!("for _, cb in unreliable_events[{id}] do")); self.indent(); } match ev.call { - EvCall::SingleSync => self.push_line(&format!("events[{id}]({values})")), - EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], {values})")), + EvCall::SingleSync => self.push_line(&format!("unreliable_events[{id}]({values})")), + EvCall::SingleAsync => self.push_line(&format!("task.spawn(unreliable_events[{id}], {values})")), EvCall::ManySync => self.push_line(&format!("cb({values})")), EvCall::ManyAsync => self.push_line(&format!("task.spawn(cb, {values})")), } @@ -453,15 +460,15 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { if ev.data.len() > 1 { - self.push_line(&format!("table.insert(event_queue[{id}], {{ {values} }})")); + self.push_line(&format!("table.insert(unreliable_event_queue[{id}], {{ {values} }})")); } else { - self.push_line(&format!("table.insert(event_queue[{id}], value)")); + self.push_line(&format!("table.insert(unreliable_event_queue[{id}], value)")); } - self.push_line(&format!("if #event_queue[{id}] > 64 then")); + self.push_line(&format!("if #unreliable_event_queue[{id}] > 64 then")); } else { - self.push_line(&format!("event_queue[{id}] += 1")); - self.push_line(&format!("if event_queue[{id}] > 16 then")); + self.push_line(&format!("unreliable_event_queue[{id}] += 1")); + self.push_line(&format!("if unreliable_event_queue[{id}] > 16 then")); } self.indent(); @@ -474,7 +481,7 @@ impl<'src> ClientOutput<'src> { } self.push(&format!( - "event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)\n", + "unreliable_event_queue[{id}]}} events in queue for {}. Did you forget to attach a listener?`)\n", ev.name )); @@ -517,12 +524,20 @@ impl<'src> ClientOutput<'src> { fn push_callback_lists(&mut self) { self.push_line(&format!( - "local events = table.create({})", - self.config.evdecls.len() + self.config.fndecls.len() + "local reliable_events = table.create({})", + self.config.client_reliable_count() + )); + self.push_line(&format!( + "local unreliable_events = table.create({})", + self.config.client_unreliable_count() + )); + self.push_line(&format!( + "local reliable_event_queue: {{ [number]: {{ any }} }} = table.create({})", + self.config.client_reliable_count() )); self.push_line(&format!( - "local event_queue: {{ [number]: {{ any }} }} = table.create({})", - self.config.evdecls.len() + self.config.fndecls.len() + "local unreliable_event_queue: {{ [number]: {{ any }} }} = table.create({})", + self.config.client_unreliable_count() )); if !self.config.fndecls.is_empty() { @@ -544,27 +559,36 @@ impl<'src> ClientOutput<'src> { let id = evdecl.id; if evdecl.call == EvCall::ManyAsync || evdecl.call == EvCall::ManySync { - self.push_line(&format!("events[{id}] = {{}}")); + self.push_line(&format!("{}[{}] = {{}}", events_table_name(evdecl), id)); } if !evdecl.data.is_empty() { - self.push_line(&format!("event_queue[{id}] = {{}}")); + self.push_line(&format!("{}[{id}] = {{}}", event_queue_table_name(evdecl))); } else { - self.push_line(&format!("event_queue[{id}] = 0")); + self.push_line(&format!("{}[{id}] = 0", event_queue_table_name(evdecl))); } } for fndecl in self.config.fndecls.iter() { - self.push_line(&format!("event_queue[{}] = table.create(255)", fndecl.id)); + self.push_line(&format!( + "reliable_event_queue[{}] = table.create(255)", + fndecl.client_id + )); } } - fn push_write_event_id(&mut self, id: usize) { - self.push_line(&format!("alloc({})", self.config.event_id_ty().size())); - self.push_line(&format!( - "buffer.write{}(outgoing_buff, outgoing_apos, {id})", - self.config.event_id_ty() - )); + fn push_write_event_id(&mut self, id: usize, num_ty: NumTy) { + self.push_line(&format!("alloc({})", num_ty.size())); + self.push_line(&format!("buffer.write{}(outgoing_buff, outgoing_apos, {id})", num_ty)); + } + + fn push_write_evdecl_event_id(&mut self, ev: &EvDecl) { + let num_ty = match ev.evty { + EvType::Reliable => self.config.server_reliable_ty(), + EvType::Unreliable => self.config.server_unreliable_ty(), + }; + + self.push_write_event_id(ev.id, num_ty); } fn push_value_parameters(&mut self, parameters: &[Parameter]) { @@ -608,7 +632,7 @@ impl<'src> ClientOutput<'src> { self.push_line("load_empty()"); } - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !ev.data.is_empty() { self.push_stmts(&ser::gen( @@ -670,10 +694,12 @@ impl<'src> ClientOutput<'src> { self.push(") -> ()): () -> ()\n"); self.indent(); - self.push_line(&format!("events[{id}] = {callback}")); + self.push_line(&format!("{}[{id}] = {callback}", events_table_name(ev))); + + let event_queue_name = event_queue_table_name(ev); if !ev.data.is_empty() { - self.push_line(&format!("for _, value in event_queue[{id}] do")); + self.push_line(&format!("for _, value in {event_queue_name}[{id}] do")); self.indent(); if ev.call == EvCall::SingleSync { @@ -691,9 +717,9 @@ impl<'src> ClientOutput<'src> { self.dedent(); self.push_line("end"); - self.push_line(&format!("event_queue[{id}] = {{}}")); + self.push_line(&format!("{event_queue_name}[{id}] = {{}}")); } else { - self.push_line(&format!("for _ = 1, event_queue[{id}] do")); + self.push_line(&format!("for _ = 1, {event_queue_name}[{id}] do")); self.indent(); if ev.call == EvCall::SingleSync { @@ -705,13 +731,13 @@ impl<'src> ClientOutput<'src> { self.dedent(); self.push_line("end"); - self.push_line(&format!("event_queue[{id}] = 0")); + self.push_line(&format!("{event_queue_name}[{id}] = 0")); } self.push_line("return function()"); self.indent(); - self.push_line(&format!("events[{id}] = nil")); + self.push_line(&format!("{}[{id}] = nil", events_table_name(ev))); self.dedent(); self.push_line("end"); @@ -736,10 +762,13 @@ impl<'src> ClientOutput<'src> { self.push(") -> ())\n"); self.indent(); - self.push_line(&format!("table.insert(events[{id}], {callback})")); + let events_table_name = events_table_name(ev); + let event_queue_name = event_queue_table_name(ev); + + self.push_line(&format!("table.insert({events_table_name}[{id}], {callback})")); if !ev.data.is_empty() { - self.push_line(&format!("for _, value in event_queue[{id}] do")); + self.push_line(&format!("for _, value in {event_queue_name}[{id}] do")); self.indent(); if ev.call == EvCall::ManySync { @@ -757,9 +786,9 @@ impl<'src> ClientOutput<'src> { self.dedent(); self.push_line("end"); - self.push_line(&format!("event_queue[{id}] = {{}}")); + self.push_line(&format!("{event_queue_name}[{id}] = {{}}")); } else { - self.push_line(&format!("for _ = 1, event_queue[{id}] do")); + self.push_line(&format!("for _ = 1, {event_queue_name}[{id}] do")); self.indent(); if ev.call == EvCall::ManySync { @@ -771,14 +800,14 @@ impl<'src> ClientOutput<'src> { self.dedent(); self.push_line("end"); - self.push_line(&format!("event_queue[{id}] = 0")); + self.push_line(&format!("{event_queue_name}[{id}] = 0")); } self.push_line("return function()"); self.indent(); self.push_line(&format!( - "table.remove(events[{id}], table.find(events[{id}], {callback}))" + "table.remove({events_table_name}[{id}], table.find({events_table_name}[{id}], {callback}))" )); self.dedent(); @@ -813,7 +842,7 @@ impl<'src> ClientOutput<'src> { let value = self.config.casing.with("Value", "value", "value"); for fndecl in self.config.fndecls.iter() { - let id = fndecl.id; + let client_id = fndecl.client_id; self.push_line(&format!("{name} = {{", name = fndecl.name)); self.indent(); @@ -858,13 +887,13 @@ impl<'src> ClientOutput<'src> { self.push("\n"); self.indent(); - self.push_write_event_id(fndecl.id); + self.push_write_event_id(fndecl.server_id, self.config.server_reliable_ty()); self.push_line("function_call_id += 1"); self.push_line("function_call_id %= 256"); - self.push_line(&format!("if event_queue[{id}][function_call_id] then")); + self.push_line(&format!("if reliable_event_queue[{client_id}][function_call_id] then")); self.indent(); self.push_line("function_call_id -= 1"); @@ -886,14 +915,18 @@ impl<'src> ClientOutput<'src> { match self.config.yield_type { YieldType::Yield => { - self.push_line(&format!("event_queue[{id}][function_call_id] = coroutine.running()",)); + self.push_line(&format!( + "reliable_event_queue[{client_id}][function_call_id] = coroutine.running()" + )); self.push_line("return coroutine.yield()"); } YieldType::Future => { self.push_line("return Future.new(function()"); self.indent(); - self.push_line(&format!("event_queue[{id}][function_call_id] = coroutine.running()",)); + self.push_line(&format!( + "reliable_event_queue[{client_id}][function_call_id] = coroutine.running()" + )); self.push_line("return coroutine.yield()"); self.dedent(); @@ -903,7 +936,9 @@ impl<'src> ClientOutput<'src> { self.push_line("return Promise.new(function(resolve)"); self.indent(); - self.push_line(&format!("event_queue[{id}][function_call_id] = resolve")); + self.push_line(&format!( + "reliable_event_queue[{client_id}][function_call_id] = resolve" + )); self.dedent(); self.push_line("end)"); diff --git a/zap/src/output/luau/mod.rs b/zap/src/output/luau/mod.rs index 364b5824..66a146ff 100644 --- a/zap/src/output/luau/mod.rs +++ b/zap/src/output/luau/mod.rs @@ -1,5 +1,5 @@ use crate::{ - config::{Enum, Ty}, + config::{Enum, EvDecl, EvType, Ty}, irgen::Stmt, }; @@ -210,3 +210,17 @@ pub trait Output { )); } } + +fn events_table_name<'a>(evdecl: &EvDecl) -> &'a str { + match evdecl.evty { + EvType::Reliable => "reliable_events", + EvType::Unreliable => "unreliable_events", + } +} + +fn event_queue_table_name<'a>(evdecl: &EvDecl) -> &'a str { + match evdecl.evty { + EvType::Reliable => "reliable_event_queue", + EvType::Unreliable => "unreliable_event_queue", + } +} diff --git a/zap/src/output/luau/server.rs b/zap/src/output/luau/server.rs index 5ea4fefd..a66688c3 100644 --- a/zap/src/output/luau/server.rs +++ b/zap/src/output/luau/server.rs @@ -1,7 +1,7 @@ use crate::{ - config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, Parameter, TyDecl}, + config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, NumTy, Parameter, TyDecl}, irgen::{des, ser}, - output::{get_named_values, get_unnamed_values}, + output::{get_named_values, get_unnamed_values, luau::events_table_name}, }; use super::Output; @@ -184,10 +184,12 @@ impl<'a> ServerOutput<'a> { self.indent(); + let server_reliable_ty = self.config.server_reliable_ty(); + self.push_line(&format!( "local id = buffer.read{}(buff, read({}))", - self.config.event_id_ty(), - self.config.event_id_ty().size() + server_reliable_ty, + server_reliable_ty.size() )); } @@ -240,16 +242,16 @@ impl<'a> ServerOutput<'a> { } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { - self.push_line(&format!("if events[{id}] then")) + self.push_line(&format!("if reliable_events[{id}] then")) } else { - self.push_line(&format!("for _, cb in events[{id}] do")) + self.push_line(&format!("for _, cb in reliable_events[{id}] do")) } self.indent(); match ev.call { - EvCall::SingleSync => self.push_line(&format!("events[{id}](player, {values})")), - EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], player, {values})")), + EvCall::SingleSync => self.push_line(&format!("reliable_events[{id}](player, {values})")), + EvCall::SingleAsync => self.push_line(&format!("task.spawn(reliable_events[{id}], player, {values})")), EvCall::ManySync => self.push_line(&format!("cb(player, {values})")), EvCall::ManyAsync => self.push_line(&format!("task.spawn(cb, player, {values})")), } @@ -261,7 +263,7 @@ impl<'a> ServerOutput<'a> { } fn push_fn_callback(&mut self, first: bool, fndecl: &FnDecl) { - let id = fndecl.id; + let server_id = fndecl.server_id; self.push_indent(); @@ -271,7 +273,7 @@ impl<'a> ServerOutput<'a> { self.push("elseif "); } - self.push(&format!("id == {id} then")); + self.push(&format!("id == {server_id} then")); self.push("\n"); self.indent(); @@ -290,7 +292,7 @@ impl<'a> ServerOutput<'a> { )); } - self.push_line(&format!("if events[{id}] then")); + self.push_line(&format!("if events[{server_id}] then")); self.indent(); @@ -323,10 +325,10 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("task.spawn(function(player_2, call_id_2, {args})")); self.indent(); - self.push_line(&format!("local {rets} = events[{id}](player_2, {args})")); + self.push_line(&format!("local {rets} = events[{server_id}](player_2, {args})")); self.push_line("load_player(player_2)"); - self.push_write_event_id(fndecl.id); + self.push_write_event_id(fndecl.client_id, self.config.client_reliable_ty()); self.push_line("alloc(1)"); self.push_line("buffer.writeu8(outgoing_buff, outgoing_apos, call_id_2)"); @@ -344,10 +346,10 @@ impl<'a> ServerOutput<'a> { self.dedent(); self.push_line(&format!("end, player, call_id, {values})")); } else { - self.push_line(&format!("local {rets} = events[{id}](player, {values})")); + self.push_line(&format!("local {rets} = events[{server_id}](player, {values})")); self.push_line("load_player(player)"); - self.push_write_event_id(fndecl.id); + self.push_write_event_id(fndecl.client_id, self.config.client_reliable_ty()); self.push_line("alloc(1)"); self.push_line("buffer.writeu8(outgoing_buff, outgoing_apos, call_id)"); @@ -412,10 +414,12 @@ impl<'a> ServerOutput<'a> { self.push_line("incoming_read = 0"); self.push_line("incoming_ipos = 0"); + let server_unreliable_ty = self.config.server_unreliable_ty(); + self.push_line(&format!( "local id = buffer.read{}(buff, read({}))", - self.config.event_id_ty(), - self.config.event_id_ty().size() + server_unreliable_ty, + server_unreliable_ty.size() )); } @@ -451,16 +455,16 @@ impl<'a> ServerOutput<'a> { } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { - self.push_line(&format!("if events[{id}] then")) + self.push_line(&format!("if unreliable_events[{id}] then")) } else { - self.push_line(&format!("for _, cb in events[{id}] do")) + self.push_line(&format!("for _, cb in unreliable_events[{id}] do")) } self.indent(); match ev.call { - EvCall::SingleSync => self.push_line(&format!("events[{id}](player, {values})")), - EvCall::SingleAsync => self.push_line(&format!("task.spawn(events[{id}], player, {values})")), + EvCall::SingleSync => self.push_line(&format!("unreliable_events[{id}](player, {values})")), + EvCall::SingleAsync => self.push_line(&format!("task.spawn(unreliable_events[{id}], player, {values})")), EvCall::ManySync => self.push_line(&format!("cb(player, {values})")), EvCall::ManyAsync => self.push_line(&format!("task.spawn(cb, player, {values})")), } @@ -501,23 +505,37 @@ impl<'a> ServerOutput<'a> { fn push_callback_lists(&mut self) { self.push_line(&format!( - "local events = table.create({})", - self.config.evdecls.len() + self.config.fndecls.len() + "local reliable_events = table.create({})", + self.config.server_reliable_count() + )); + + self.push_line(&format!( + "local unreliable_events = table.create({})", + self.config.server_unreliable_count() )); for evdecl in self.config.evdecls.iter().filter(|ev_decl| { ev_decl.from == EvSource::Client && matches!(ev_decl.call, EvCall::ManyAsync | EvCall::ManySync) }) { - self.push_line(&format!("events[{}] = {{}}", evdecl.id)); + match evdecl.evty { + EvType::Reliable => self.push_line(&format!("reliable_events[{}] = {{}}", evdecl.id)), + EvType::Unreliable => self.push_line(&format!("unreliable_events[{}] = {{}}", evdecl.id)), + } } } - fn push_write_event_id(&mut self, id: usize) { - self.push_line(&format!("alloc({})", self.config.event_id_ty().size())); - self.push_line(&format!( - "buffer.write{}(outgoing_buff, outgoing_apos, {id})", - self.config.event_id_ty() - )); + fn push_write_event_id(&mut self, id: usize, num_ty: NumTy) { + self.push_line(&format!("alloc({})", num_ty.size())); + self.push_line(&format!("buffer.write{}(outgoing_buff, outgoing_apos, {id})", num_ty)); + } + + fn push_write_evdecl_event_id(&mut self, ev: &EvDecl) { + let num_ty = match ev.evty { + EvType::Reliable => self.config.server_reliable_ty(), + EvType::Unreliable => self.config.server_unreliable_ty(), + }; + + self.push_write_event_id(ev.id, num_ty); } fn push_value_parameters(&mut self, parameters: &[Parameter]) { @@ -565,7 +583,7 @@ impl<'a> ServerOutput<'a> { EvType::Unreliable => self.push_line("load_empty()"), } - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !parameters.is_empty() { self.push_stmts(&ser::gen( @@ -606,7 +624,7 @@ impl<'a> ServerOutput<'a> { self.push_line("load_empty()"); - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !parameters.is_empty() { self.push_stmts(&ser::gen( @@ -661,7 +679,7 @@ impl<'a> ServerOutput<'a> { self.push_line("load_empty()"); - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !parameters.is_empty() { self.push_stmts(&ser::gen( @@ -728,7 +746,7 @@ impl<'a> ServerOutput<'a> { self.push_line("load_empty()"); - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !parameters.is_empty() { self.push_stmts(&ser::gen( @@ -787,7 +805,7 @@ impl<'a> ServerOutput<'a> { self.push_line("load_empty()"); - self.push_write_event_id(ev.id); + self.push_write_evdecl_event_id(ev); if !parameters.is_empty() { self.push_stmts(&ser::gen( @@ -869,12 +887,12 @@ impl<'a> ServerOutput<'a> { self.push(") -> ()): () -> ()\n"); self.indent(); - self.push_line(&format!("events[{id}] = {callback}")); + self.push_line(&format!("{}[{id}] = {callback}", events_table_name(ev))); self.push_line("return function()"); self.indent(); - self.push_line(&format!("events[{id}] = nil")); + self.push_line(&format!("{}[{id}] = nil", events_table_name(ev))); self.dedent(); self.push_line("end"); @@ -901,13 +919,15 @@ impl<'a> ServerOutput<'a> { self.push(") -> ()): () -> ()\n"); self.indent(); - self.push_line(&format!("table.insert(events[{id}], {callback})")); + let events_table = events_table_name(ev); + + self.push_line(&format!("table.insert({events_table}[{id}], {callback})")); self.push_line("return function()"); self.indent(); self.push_line(&format!( - "table.remove(events[{id}], table.find(events[{id}], {callback}))" + "table.remove({events_table}[{id}], table.find({events_table}[{id}], {callback}))", )); self.dedent(); @@ -918,7 +938,7 @@ impl<'a> ServerOutput<'a> { } fn push_fn_return(&mut self, fndecl: &FnDecl) { - let id = fndecl.id; + let server_id = fndecl.server_id; let set_callback = self.config.casing.with("SetCallback", "setCallback", "set_callback"); let callback = self.config.casing.with("Callback", "callback", "callback"); @@ -946,12 +966,12 @@ impl<'a> ServerOutput<'a> { self.push(")): () -> ()\n"); self.indent(); - self.push_line(&format!("events[{id}] = {callback}")); + self.push_line(&format!("reliable_events[{server_id}] = {callback}")); self.push_line("return function()"); self.indent(); - self.push_line(&format!("events[{id}] = nil")); + self.push_line(&format!("reliable_events[{server_id}] = nil")); self.dedent(); self.push_line("end"); diff --git a/zap/src/output/tooling.rs b/zap/src/output/tooling.rs index 10ffb5da..a3b417b9 100644 --- a/zap/src/output/tooling.rs +++ b/zap/src/output/tooling.rs @@ -1,5 +1,5 @@ use crate::{ - config::{Config, EvDecl, FnDecl, Parameter, TyDecl}, + config::{Config, EvDecl, EvSource, EvType, FnDecl, NumTy, Parameter, TyDecl}, irgen::{des, Stmt}, output::get_unnamed_values, Output, @@ -201,8 +201,12 @@ impl<'src> ToolingOutput<'src> { self.dedent(); } - fn push_function_callback(&mut self, first: bool, fn_decl: &FnDecl) { - let id = fn_decl.id; + fn push_function_callback(&mut self, first: bool, is_server: bool, fn_decl: &FnDecl) { + let id = if is_server { + fn_decl.server_id + } else { + fn_decl.client_id + }; let event_id = self.config.casing.with("EventId", "eventId", "event_id"); let call_id = self.config.casing.with("CallId", "callId", "call_id"); @@ -224,70 +228,62 @@ impl<'src> ToolingOutput<'src> { self.push_line("local call_id = buffer.readu8(incoming_buff, read(1))"); - self.push_line("if isServer then"); - self.indent(); - let values = self.get_values(&fn_decl.args); - self.push_line(&format!("local {values}")); + if is_server { + self.push_line(&format!("local {values}")); - if !fn_decl.args.is_empty() { - self.push_stmts(&des::gen( - fn_decl.args.iter().map(|parameter| ¶meter.ty), - &get_unnamed_values("value", fn_decl.args.len()), - true, - )); - } + if !fn_decl.args.is_empty() { + self.push_stmts(&des::gen( + fn_decl.args.iter().map(|parameter| ¶meter.ty), + &get_unnamed_values("value", fn_decl.args.len()), + true, + )); + } - self.push_line("table.insert(events, {"); - self.indent(); + self.push_line("table.insert(events, {"); + self.indent(); - self.push_line(&format!("Name = \"{} (request)\",", fn_decl.name)); + self.push_line(&format!("Name = \"{} (request)\",", fn_decl.name)); - self.push_indent(); - self.push("Arguments = { "); + self.push_indent(); + self.push("Arguments = { "); - if self.config.tooling_show_internal_data { - self.push(&format!("{{ {} = id, {} = call_id }}, ", event_id, call_id)); - } + if self.config.tooling_show_internal_data { + self.push(&format!("{{ {} = id, {} = call_id }}, ", event_id, call_id)); + } - self.push(&format!("{values} }}")); - self.push("\n"); + self.push(&format!("{values} }}")); + self.push("\n"); - self.dedent(); - self.push_line("})"); + self.dedent(); + self.push_line("})"); + } else { + self.push_line(&format!("local {values}")); - self.dedent(); - self.push_line("else"); - self.indent(); + if let Some(data) = &fn_decl.rets { + self.push_stmts(&des::gen(data, &get_unnamed_values("value", data.len()), true)); + } - self.push_line(&format!("local {values}")); + self.push_line("table.insert(events, {"); + self.indent(); - if let Some(data) = &fn_decl.rets { - self.push_stmts(&des::gen(data, &get_unnamed_values("value", data.len()), true)); - } + self.push_line(&format!("Name = \"{} (callback)\",", fn_decl.name)); - self.push_line("table.insert(events, {"); - self.indent(); + self.push_indent(); + self.push("Arguments = { "); - self.push_line(&format!("Name = \"{} (callback)\",", fn_decl.name)); + if self.config.tooling_show_internal_data { + self.push(&format!("{{ {} = id, {} = call_id }}, ", event_id, call_id)); + } - self.push_indent(); - self.push("Arguments = { "); + self.push(&format!("{values} }}")); + self.push("\n"); - if self.config.tooling_show_internal_data { - self.push(&format!("{{ {} = id, {} = call_id }}, ", event_id, call_id)); + self.dedent(); + self.push_line("})"); } - self.push(&format!("{values} }}")); - self.push("\n"); - - self.dedent(); - self.push_line("})"); - - self.dedent(); - self.push_line("end"); - self.dedent(); } @@ -424,43 +420,96 @@ impl<'src> ToolingOutput<'src> { self.indent(); + self.push_line("if isServer and remote_instance == reliable then"); + self.indent(); + self.push_events( + true, + self.config.server_reliable_ty(), + EvSource::Client, + EvType::Reliable, + ); + self.dedent(); + + self.push_line("elseif isServer and remote_instance == unreliable then"); + self.indent(); + self.push_events( + true, + self.config.server_unreliable_ty(), + EvSource::Client, + EvType::Unreliable, + ); + self.dedent(); + + self.push_line("elseif not isServer and remote_instance == reliable then"); + self.indent(); + self.push_events( + false, + self.config.client_reliable_ty(), + EvSource::Server, + EvType::Reliable, + ); + self.dedent(); + + self.push_line("elseif not isServer and remote_instance == unreliable then"); + self.indent(); + self.push_events( + false, + self.config.client_unreliable_ty(), + EvSource::Server, + EvType::Unreliable, + ); + self.dedent(); + + self.push_line("end"); + + self.dedent(); + self.push_line("end"); + + self.push("\n"); + self.push_line("return events"); + + self.dedent(); + self.push_line("end"); + + self.buf + } + + fn push_events( + &mut self, + is_server: bool, + event_ty: NumTy, + expected_ev_source: EvSource, + expected_ev_type: EvType, + ) { self.push_line(&format!( "local id = buffer.read{}(incoming_buff, read({}))", - self.config.event_id_ty(), - self.config.event_id_ty().size() + event_ty, + event_ty.size() )); let mut first = true; for ev in self.config.evdecls.iter() { - self.push_event_callback(first, ev); + if ev.from != expected_ev_source || ev.evty != expected_ev_type { + continue; + } + self.push_event_callback(first, ev); first = false; } - for fn_decl in self.config.fndecls.iter() { - self.push_function_callback(first, fn_decl); - - first = false; + if expected_ev_type == EvType::Reliable { + for fn_decl in self.config.fndecls.iter() { + self.push_function_callback(first, is_server, fn_decl); + first = false; + } } self.push_line("else"); self.indent(); self.push_line("error(\"Unknown event id\")"); - self.dedent(); self.push_line("end"); - - self.dedent(); - self.push_line("end"); - - self.push("\n"); - self.push_line("return events"); - - self.dedent(); - self.push_line("end"); - - self.buf } } diff --git a/zap/src/parser/convert.rs b/zap/src/parser/convert.rs index 957be2d1..ae303f48 100644 --- a/zap/src/parser/convert.rs +++ b/zap/src/parser/convert.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use crate::config::{ - Casing, Config, Enum, EvDecl, EvType, FnDecl, NumTy, Parameter, Range, Struct, Ty, TyDecl, YieldType, + Casing, Config, Enum, EvDecl, EvSource, EvType, FnDecl, NumTy, Parameter, Range, Struct, Ty, TyDecl, YieldType, }; use super::{ @@ -12,7 +12,8 @@ use super::{ struct Converter<'src> { config: SyntaxConfig<'src>, tydecls: HashMap<&'src str, SyntaxTyDecl<'src>>, - max_unreliable_size: usize, + max_server_unreliable_size: usize, + max_client_unreliable_size: usize, reports: Vec>, } @@ -20,7 +21,9 @@ struct Converter<'src> { impl<'src> Converter<'src> { fn new(config: SyntaxConfig<'src>) -> Self { let mut tydecls = HashMap::new(); - let mut ntdecls = 0; + + let mut client_unreliable_event_count = 0; + let mut server_unreliable_event_count = 0; for decl in config.decls.iter() { match decl { @@ -28,17 +31,28 @@ impl<'src> Converter<'src> { tydecls.insert(tydecl.name.name, tydecl.clone()); } - SyntaxDecl::Ev(_) | SyntaxDecl::Fn(_) => ntdecls += 1, + SyntaxDecl::Ev(ev_decl) => { + if ev_decl.evty == EvType::Unreliable { + match ev_decl.from { + EvSource::Server => client_unreliable_event_count += 1, + EvSource::Client => server_unreliable_event_count += 1, + } + } + } + + _ => {} } } // We subtract two for the `inst` array. - let max_unreliable_size = 900 - NumTy::from_f64(1.0, ntdecls as f64).size() - 2; + let max_server_unreliable_size = 900 - NumTy::from_f64(0.0, server_unreliable_event_count as f64).size() - 2; + let max_client_unreliable_size = 900 - NumTy::from_f64(0.0, client_unreliable_event_count as f64).size() - 2; Self { config, tydecls, - max_unreliable_size, + max_server_unreliable_size, + max_client_unreliable_size, reports: Vec::new(), } @@ -53,7 +67,10 @@ impl<'src> Converter<'src> { let mut evdecls = Vec::new(); let mut fndecls = Vec::new(); - let mut ntdecl_id = 0; + let mut server_reliable_id = 0; + let mut server_unreliable_id = 0; + let mut client_reliable_id = 0; + let mut client_unreliable_id = 0; for tydecl in config.decls.iter().filter_map(|decl| match decl { SyntaxDecl::Ty(tydecl) => Some(tydecl), @@ -71,16 +88,43 @@ impl<'src> Converter<'src> { SyntaxDecl::Ev(evdecl) => Some(evdecl), _ => None, }) { - ntdecl_id += 1; - evdecls.push(self.evdecl(evdecl, ntdecl_id, &tydecl_hashmap)); + let id = match evdecl.from { + EvSource::Server => match evdecl.evty { + EvType::Reliable => { + let current_id = client_reliable_id; + client_reliable_id += 1; + current_id + } + EvType::Unreliable => { + let current_id = client_unreliable_id; + client_unreliable_id += 1; + current_id + } + }, + EvSource::Client => match evdecl.evty { + EvType::Reliable => { + let current_id = server_reliable_id; + server_reliable_id += 1; + current_id + } + EvType::Unreliable => { + let current_id = server_unreliable_id; + server_unreliable_id += 1; + current_id + } + }, + }; + + evdecls.push(self.evdecl(evdecl, id, &tydecl_hashmap)); } for fndecl in config.decls.iter().filter_map(|decl| match decl { SyntaxDecl::Fn(fndecl) => Some(fndecl), _ => None, }) { - ntdecl_id += 1; - fndecls.push(self.fndecl(fndecl, ntdecl_id)); + fndecls.push(self.fndecl(fndecl, client_reliable_id, server_reliable_id)); + client_reliable_id += 1; + server_reliable_id += 1; } if evdecls.is_empty() && fndecls.is_empty() { @@ -370,18 +414,23 @@ impl<'src> Converter<'src> { } } - if min > self.max_unreliable_size { + let max_unreliable_size = match from { + EvSource::Server => self.max_client_unreliable_size, + EvSource::Client => self.max_server_unreliable_size, + }; + + if min > max_unreliable_size { self.report(Report::AnalyzeOversizeUnreliable { ev_span: evdecl.span(), ty_span: evdecl.data.as_ref().unwrap().span(), - max_size: self.max_unreliable_size, + max_size: max_unreliable_size, size: min, }); - } else if !max.is_some_and(|max| max < self.max_unreliable_size) { + } else if max.is_none_or(|max| max >= max_unreliable_size) { self.report(Report::AnalyzePotentiallyOversizeUnreliable { ev_span: evdecl.span(), ty_span: evdecl.data.as_ref().unwrap().span(), - max_size: self.max_unreliable_size, + max_size: max_unreliable_size, }); } } @@ -396,7 +445,7 @@ impl<'src> Converter<'src> { } } - fn fndecl(&mut self, fndecl: &SyntaxFnDecl<'src>, id: usize) -> FnDecl<'src> { + fn fndecl(&mut self, fndecl: &SyntaxFnDecl<'src>, client_id: usize, server_id: usize) -> FnDecl<'src> { if let Some(syntax_parameters) = &fndecl.args { self.check_duplicate_parameters(syntax_parameters); } @@ -438,7 +487,8 @@ impl<'src> Converter<'src> { args: args.unwrap_or_default(), call, rets, - id, + client_id, + server_id, } }