diff --git a/.gitignore b/.gitignore index 1b75fd1..22b6f82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules docs/.vitepress/dist docs/.vitepress/cache -wally.lock \ No newline at end of file +wally.lock +TestEZ +test.project.json \ No newline at end of file diff --git a/Warp.rbxm b/Warp.rbxm index 8dbee97..9ef44cf 100644 Binary files a/Warp.rbxm and b/Warp.rbxm differ diff --git a/src/Index/Client/ClientProcess/init.luau b/src/Index/Client/ClientProcess/init.luau index 0d83711..44a9d1f 100644 --- a/src/Index/Client/ClientProcess/init.luau +++ b/src/Index/Client/ClientProcess/init.luau @@ -76,8 +76,11 @@ function ClientProcess.insertRequest(Identifier: string, timeout: number, ...: a return coroutine.yield() end -function ClientProcess.add(Identifier: any, originId: string) +function ClientProcess.add(Identifier: any, originId: string, conf: Type.ClientConf) if not clientQueue[Identifier] then + if conf.logging then + ClientProcess.logger(Identifier, conf.logging.store, conf.logging.opt) + end if not clientRatelimit[Identifier] then clientRatelimit[Identifier] = RateLimit.create(originId) end @@ -93,7 +96,7 @@ function ClientProcess.add(Identifier: any, originId: string) if not clientCallback[Identifier] then clientCallback[Identifier] = {} end - + if not queueOutRequest[1][Identifier] then queueOutRequest[1][Identifier] = {} end diff --git a/src/Index/Client/Index.luau b/src/Index/Client/Index.luau index fc925ff..5b0fd33 100644 --- a/src/Index/Client/Index.luau +++ b/src/Index/Client/Index.luau @@ -7,29 +7,32 @@ Client.__index = Client local Players = game:GetService("Players") local Util = script.Parent.Parent.Util +local Type = require(script.Parent.Parent.Type) local ClientProcess = require(script.Parent.ClientProcess) local Assert = require(Util.Assert) local Key = require(Util.Key) local Serdes = require(Util.Serdes) local Buffer = require(Util.Buffer) -function Client.new(Identifier: string, yieldWait: number?) +function Client.new(Identifier: string, conf: Type.ClientConf?) local self = setmetatable({}, Client) + self._buffer = Buffer.new() - self._buffer:wu8(Serdes(Identifier, yieldWait)) + self._buffer:wu8(Serdes(Identifier, conf and conf.yieldWait)) self.id = Buffer.convert(self._buffer:build()) self.fn = {} + self._conf = table.freeze(conf or {}) self.IsConnected = false - ClientProcess.add(self.id, Identifier) + + ClientProcess.add(self.id, Identifier, conf or { yieldWait = 10, logging = { store = false, opt = false } }) self._buffer:remove() + return self end -function Client:Logging(store: boolean, opt: boolean) - ClientProcess.logger(self.id, store, opt) - return function() - return ClientProcess.getlogs(self.id) - end +function Client:logs() + Assert(self._conf.logging, "[Client]: Event is not configured with logging.") + return ClientProcess.getlogs(self.id) end function Client:Fire(reliable: boolean,...: any) diff --git a/src/Index/Server/Index.luau b/src/Index/Server/Index.luau index 7202fd8..8a9d5ee 100644 --- a/src/Index/Server/Index.luau +++ b/src/Index/Server/Index.luau @@ -14,23 +14,25 @@ local Key = require(Util.Key) local Serdes = require(Util.Serdes) local Buffer = require(Util.Buffer) -function Server.new(Identifier: string, rateLimit: Type.rateLimitArg?) +function Server.new(Identifier: string, conf: Type.ServerConf?) local self = setmetatable({}, Server) + self._buffer = Buffer.new() self._buffer:wu8(Serdes(Identifier)) self.id = Buffer.convert(self._buffer:build()) self.fn = {} + self._conf = table.freeze(conf or {}) self.IsConnected = false - ServerProcess.add(self.id, Identifier, rateLimit or { maxEntrance = 200, interval = 2 }) + + ServerProcess.add(self.id, Identifier, conf or { rateLimit = { maxEntrance = 200, interval = 2 } }) self._buffer:remove() + return self end -function Server:Logging(store: boolean, opt: boolean) - ServerProcess.logger(self.id, store, opt) - return function() - return ServerProcess.getlogs(self.id) - end +function Server:logs() + Assert(self._conf.logging, "[Server]: Event is not configured with logging.") + return ServerProcess.getlogs(self.id) end function Server:Fire(reliable: boolean, player: Player, ...: any) @@ -50,6 +52,13 @@ function Server:FireExcept(reliable: boolean, except: { Player }, ...: any) end end +function Server:FireIn(reliable: boolean, range: number, from: Vector3, data: { any }, except: { Player }?) + for _, player: Player in ipairs(Players:GetPlayers()) do + if (except and table.find(except, player)) or not player.Character or not player.Character.PrimaryPart or (player.Character.PrimaryPart.Position - from).Magnitude < range then continue end + ServerProcess.insertQueue(self.id, reliable, player, table.unpack(data)) + end +end + function Server:Invoke(timeout: number, player: Player, ...: any): any return ServerProcess.insertRequest(self.id, timeout, player, ...) end diff --git a/src/Index/Server/ServerProcess/init.luau b/src/Index/Server/ServerProcess/init.luau index 5ca8c4c..8bd3c3e 100644 --- a/src/Index/Server/ServerProcess/init.luau +++ b/src/Index/Server/ServerProcess/init.luau @@ -123,9 +123,12 @@ function ServerProcess.insertRequest(Identifier: string, timeout: number, player return coroutine.yield() end -function ServerProcess.add(Identifier: string, originId: string, ratelimit: Type.rateLimitArg) +function ServerProcess.add(Identifier: string, originId: string, conf: Type.ServerConf) if not serverQueue[Identifier] then - RateLimit.create(originId, ratelimit.maxEntrance or 200, ratelimit.interval or 2) + RateLimit.create(originId, conf.rateLimit and conf.rateLimit.maxEntrance or 200, conf.rateLimit and conf.rateLimit.interval or 2) + if conf.logging then + ServerProcess.logger(Identifier, conf.logging.store, conf.logging.opt) + end if not serverQueue[Identifier] then serverQueue[Identifier] = {} end @@ -138,7 +141,7 @@ function ServerProcess.add(Identifier: string, originId: string, ratelimit: Type if not serverRequestQueue[Identifier] then serverRequestQueue[Identifier] = {} end - + if not queueIn[Identifier] then queueIn[Identifier] = {} end @@ -154,7 +157,7 @@ function ServerProcess.add(Identifier: string, originId: string, ratelimit: Type if not queueOutRequest[2][Identifier] then queueOutRequest[2][Identifier] = {} end - + for _, player: Player in ipairs(Players:GetPlayers()) do task.spawn(initializeEachPlayer, player) end diff --git a/src/Index/Type.luau b/src/Index/Type.luau index 79cbf04..57569be 100644 --- a/src/Index/Type.luau +++ b/src/Index/Type.luau @@ -1,9 +1,24 @@ --!strict -export type rateLimitArg = { +type rateLimitArg = { maxEntrance: number?, interval: number?, } +type logging = { + store: boolean, + opt: boolean, +} + +export type ServerConf = { + rateLimit: rateLimitArg?, + logging: logging?, +} + +export type ClientConf = { + yieldWait: number?, + logging: logging?, +} + export type Client = { Fire: (self: Client, reliable: boolean, ...any) -> (), Invoke: (self: Client, timeout: number, ...any) -> any, @@ -11,9 +26,9 @@ export type Client = { Once: (self: Client, callback: (player: Player, ...any) -> ()) -> string, Disconnect: (self: Client, key: string) -> (), DisconnectAll: (self: Client) -> (), - Destroy: (self: Client) -> (), Wait: (self: Client) -> number, - Logging: (self: Client, store: boolean, opt: boolean) -> (), + Destroy: (self: Client) -> (), + logs: (self: Client) -> any, } export type Server = { @@ -24,9 +39,9 @@ export type Server = { Once: (self: Server, callback: (player: Player, ...any) -> ()) -> string, Disconnect: (self: Server, key: string) -> (), DisconnectAll: (self: Server) -> (), - Destroy: (self: Server) -> (), Wait: (self: Server) -> number, - Logging: (self: Server, store: boolean, opt: boolean) -> (), + Destroy: (self: Server) -> (), + logs: (self: Server) -> any, } export type Signal = { diff --git a/src/Index/Util/Assert.luau b/src/Index/Util/Assert.luau index ed9e790..de68818 100644 --- a/src/Index/Util/Assert.luau +++ b/src/Index/Util/Assert.luau @@ -1,4 +1,6 @@ --!strict +--!native +--!optimize 2 return function(condition: (any), errorMessage: string?): () if not (condition) then error(`Warp: {errorMessage}`, 2) end end \ No newline at end of file diff --git a/src/Index/Util/Key.luau b/src/Index/Util/Key.luau index 8c3821b..db0ac6b 100644 --- a/src/Index/Util/Key.luau +++ b/src/Index/Util/Key.luau @@ -1,4 +1,6 @@ --!strict +--!native +--!optimize 2 return function(): number? return tonumber(string.sub(tostring(Random.new():NextNumber()), 3, 6)) -- 4 digits end \ No newline at end of file diff --git a/src/Index/Util/RateLimit.luau b/src/Index/Util/RateLimit.luau index 5a323c2..cf16ba3 100644 --- a/src/Index/Util/RateLimit.luau +++ b/src/Index/Util/RateLimit.luau @@ -26,7 +26,7 @@ function RateLimit.create(Identifier: string, entrance: number?, interval: numbe entrances = 0 end) end - entrances += incoming and incoming or 1 + entrances += incoming or 1 return (entrances <= entrance :: number) end end diff --git a/src/Index/Util/Serdes.luau b/src/Index/Util/Serdes.luau index 025fd68..08b619e 100644 --- a/src/Index/Util/Serdes.luau +++ b/src/Index/Util/Serdes.luau @@ -15,16 +15,19 @@ return function(Identifier: string, timeout: number?): number --Event:SetAttribute(Identifier, string.pack("I1", SerInt)) -- I1 -> 255 max, I2 -> ~ 6.5e4 max. (SerInt), removed/disabled for buffer migration. end else - local retreived = false - task.delay(timeout or 10, function() - if retreived then return end - retreived = true + local yieldThread: thread = coroutine.running() + local cancel = task.delay(timeout or 10, function() -- yield cancelation (timerout) + task.spawn(yieldThread, nil) error(`Serdes: {Identifier} is taking too long to retrieve, seems like not replicated on server.`, 2) end) - while (not retreived) and (not Event:GetAttribute(Identifier)) do - task.wait(0.5) + while coroutine.status(cancel) ~= "dead" and task.wait(0.5) do -- let it loop for yields! + if (Event:GetAttribute(Identifier)) then + task.cancel(cancel) + task.spawn(yieldThread, Event:GetAttribute(Identifier)) + break + end end - retreived = true + return coroutine.yield() -- yield end return Event:GetAttribute(Identifier) -end \ No newline at end of file +end diff --git a/src/Index/init.luau b/src/Index/init.luau index 7197f5f..af51bd7 100644 --- a/src/Index/init.luau +++ b/src/Index/init.luau @@ -1,4 +1,5 @@ --!strict +--!native --!optimize 2 local Index = {} @@ -20,20 +21,20 @@ else require(Client.ClientProcess).start() end -function Index.Server(Identifier: string, rateLimit: Type.rateLimitArg?): Type.Server +function Index.Server(Identifier: string, conf: Type.ServerConf?): Type.Server Assert(IsServer, `[Warp]: Calling .Server({Identifier}) on client side (expected server side)`) Assert(typeof(Identifier) == "string", `[Warp]: Identifier must be a string type, got {typeof(Identifier)}`) - return require(Server.Index)(Identifier, rateLimit) :: Type.Server + return require(Server.Index)(Identifier, conf) :: Type.Server end -function Index.Client(Identifier: string, yieldWait: number?): Type.Client +function Index.Client(Identifier: string, conf: Type.ClientConf?): Type.Client Assert(not IsServer, `[Warp]: Calling .Client({Identifier}) on server side (expected client side)`) Assert(typeof(Identifier) == "string", `[Warp]: Identifier must be a string type, got {typeof(Identifier)}`) - return require(Client.Index)(Identifier, yieldWait) :: Type.Client + return require(Client.Index)(Identifier, conf) :: Type.Client end function Index.fromServerArray(arrays: { any }): Type.fromServerArray Assert(IsServer, `[Warp]: Calling .fromServerArray({arrays}) on client side (expected server side)`) - Assert(typeof(arrays) == "table", "[Warp]: Array must be a table type") + Assert(typeof(arrays) == "table", "[Warp]: Array must be a table type, got {typeof(arrays)}") local copy = {} for param1: any, param2: any in arrays do if typeof(param2) == "table" then @@ -42,17 +43,21 @@ function Index.fromServerArray(arrays: { any }): Type.fromServerArray copy[param2] = Index.Server(param2) end end - return table.freeze(copy) :: typeof(copy) + return copy :: typeof(copy) end function Index.fromClientArray(arrays: { any }): Type.fromClientArray Assert(not IsServer, `[Warp]: Calling .fromClientArray({arrays}) on server side (expected client side)`) Assert(typeof(arrays) == "table", `[Warp]: Array must be a table type, got {typeof(arrays)}`) local copy = {} - for _, identifier: string in arrays do - copy[identifier] = Index.Client(identifier) + for param1: any, param2: any in arrays do + if typeof(param2) == "table" then + copy[param1] = Index.Client(param1, param2) + else + copy[param2] = Index.Client(param2) + end end - return table.freeze(copy) :: typeof(copy) + return copy :: typeof(copy) end function Index.Signal(Identifier: string) @@ -65,7 +70,7 @@ function Index.fromSignalArray(arrays: { any }) for _, identifier: string in arrays do copy[identifier] = Index.Signal(identifier) end - return table.freeze(copy) :: typeof(copy) + return copy :: typeof(copy) end function Index.buffer() diff --git a/src/init.luau b/src/init.luau index 80607e0..7b183f1 100644 --- a/src/init.luau +++ b/src/init.luau @@ -1,5 +1,5 @@ -- Warp Library (@Eternity_Devs) --- version 1.0.9 +-- version 1.0.10 --!strict --!native --!optimize 2 diff --git a/wally.toml b/wally.toml index afb7b27..193ac0c 100644 --- a/wally.toml +++ b/wally.toml @@ -1,10 +1,10 @@ [package] name = "imezx/warp" -version = "1.0.9" +version = "1.0.10" registry = "https://github.com/UpliftGames/wally-index" realm = "shared" license = "MIT" -exclude = ["node_modules", "docs", ".github", "*.rbxl", "*.rbxmx", "*.rbxml"] +exclude = ["node_modules", "docs", ".github", "*.rbxl", "*.rbxmx", "*.rbxml", "TestEZ", "test.project.json"] description = "A very-fast & powerful networking library for Roblox." [dependencies] \ No newline at end of file