From 9aaa382278def97449b25e9849bd631a56476e63 Mon Sep 17 00:00:00 2001 From: EternityDev Date: Tue, 2 Apr 2024 13:10:21 +0700 Subject: [PATCH] v1.0.9 --- Warp.rbxm | Bin 12780 -> 14009 bytes src/Index/Client/ClientProcess.luau | 7 +- src/Index/Client/ClientProcess/Logger.luau | 32 +++ src/Index/Client/ClientProcess/init.luau | 253 ++++++++++++++++++ src/Index/Client/Index.luau | 11 +- src/Index/Server/Index.luau | 7 + src/Index/Server/ServerProcess/Logger.luau | 32 +++ .../init.luau} | 45 +++- src/Index/Signal/init.luau | 2 +- src/Index/Type.luau | 2 + src/Index/Util/Assert.luau | 2 +- src/Index/Util/Buffer/Dedicated.luau | 9 + src/Index/Util/Key.luau | 2 +- src/Index/Util/Serdes.luau | 13 +- src/Index/init.luau | 4 +- src/init.luau | 2 +- wally.toml | 2 +- 17 files changed, 407 insertions(+), 18 deletions(-) create mode 100644 src/Index/Client/ClientProcess/Logger.luau create mode 100644 src/Index/Client/ClientProcess/init.luau create mode 100644 src/Index/Server/ServerProcess/Logger.luau rename src/Index/Server/{ServerProcess.luau => ServerProcess/init.luau} (85%) diff --git a/Warp.rbxm b/Warp.rbxm index d040501f956822d0753e61e8ba82e8c4c24a4255..8dbee97ed6448f648ee169b1d17544ddea5ed26f 100644 GIT binary patch literal 14009 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 literal 12780 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 0 then if clientRatelimit[Identifier](#data) then ReliableEvent:FireServer(Buffer.revert(Identifier), data) @@ -126,11 +127,11 @@ function ClientProcess.start() table.clear(incoming_cache[Identifier]) end end - if clientCallback[Identifier] then + if callback then if #queueIn[Identifier] > 0 then for _, packedDatas: any in queueIn[Identifier] do if #packedDatas == 0 then continue end - for _, fn: any in clientCallback[Identifier] do + for _, fn: any in callback do for i=1,math.min(1e3, #packedDatas) do Spawn(fn, table.unpack(packedDatas[i] or {})) end @@ -141,7 +142,7 @@ function ClientProcess.start() if #queueInRequest[1][Identifier] > 0 then for idx, packetDatas: any in queueInRequest[1][Identifier] do if #packetDatas == 0 then continue end - for _, fn: any in clientCallback[Identifier] do + for _, fn: any in callback do for i=1,math.min(1e3, #packetDatas) do local packetData = packetDatas[i] if not packetData then continue end diff --git a/src/Index/Client/ClientProcess/Logger.luau b/src/Index/Client/ClientProcess/Logger.luau new file mode 100644 index 0000000..b6de03d --- /dev/null +++ b/src/Index/Client/ClientProcess/Logger.luau @@ -0,0 +1,32 @@ +--!strict +local Logger = {} +local Logs: { + [string]: { + [string]: string + } +} = {} +local logging: { + [string]: boolean +} = {} + +local now = tick() + +function Logger.write(Identifier: string, text: string, log: boolean?) + if not Logs[Identifier] then + Logs[Identifier] = {} + end + if log ~= nil then + logging[Identifier] = log + end + now = tick() + Logs[Identifier][tostring(now)] = text + if logging[Identifier] then + print(`[{now}] ->`, text) + end +end + +function Logger.read(Identifier: string) + return Logs[Identifier] +end + +return Logger \ No newline at end of file diff --git a/src/Index/Client/ClientProcess/init.luau b/src/Index/Client/ClientProcess/init.luau new file mode 100644 index 0000000..1f67e51 --- /dev/null +++ b/src/Index/Client/ClientProcess/init.luau @@ -0,0 +1,253 @@ +--!native +--!strict +--!optimize 2 +local ClientProcess = {} + +local RunService = game:GetService("RunService") +local Util = script.Parent.Parent.Util + +local Type = require(script.Parent.Parent.Type) +local Event = require(script.Parent.Parent.Event) +local Spawn = require(Util.Spawn) +local Key = require(Util.Key) +local RateLimit = require(Util.RateLimit) +local Buffer = require(Util.Buffer) +local Logger = require(script.Logger) + +local clientRatelimit: Type.StoredRatelimit = {} +local clientQueue: Type.QueueMap = {} +local unreliableClientQueue: Type.QueueMap = {} +local clientCallback: Type.CallbackMap = {} +local clientRequestQueue: Type.QueueMap = {} + +local queueIn: { + [string]: {any} +} = {} +local queueInRequest: { + [number]: { + [string]: { + any + } + } +} = {} +local queueOutRequest: { + [number]: { + [string]: { + any + } + } +} = {} +local incoming_cache: { + [string]: { + any + } +} = {} +local logger: { + [string]: boolean +} = {} + +queueInRequest[1] = {} +queueInRequest[2] = {} +queueOutRequest[1] = {} +queueOutRequest[2] = {} + +local ReliableEvent = Event.Reliable +local UnreliableEvent = Event.Unreliable +local RequestEvent = Event.Request + +function ClientProcess.insertQueue(Identifier: string, reliable: boolean, ...: any) + if not reliable then + table.insert(unreliableClientQueue[Identifier], { ... }) + return + end + table.insert(clientQueue[Identifier], { ... }) +end + +function ClientProcess.insertRequest(Identifier: string, timeout: number, ...: any) + local yieldThread: thread, start = coroutine.running(), os.clock() + local cancel = task.delay(timeout, function() + task.spawn(yieldThread, nil) + end) + table.insert(clientRequestQueue[Identifier], { tostring(Key()), function(...: any) + if (os.clock() - start) > timeout then return end + task.cancel(cancel) + task.spawn(yieldThread, ...) + end :: any, { ... } :: any }) + return coroutine.yield() +end + +function ClientProcess.add(Identifier: any, originId: string) + if not clientQueue[Identifier] then + clientRatelimit[Identifier] = RateLimit.create(originId) + clientQueue[Identifier] = {} + unreliableClientQueue[Identifier] = {} + clientRequestQueue[Identifier] = {} + clientCallback[Identifier] = {} + + queueOutRequest[1][Identifier] = {} + queueOutRequest[2][Identifier] = {} + queueInRequest[1][Identifier] = {} + queueInRequest[2][Identifier] = {} + queueIn[Identifier] = {} + end +end + +function ClientProcess.logger(Identifier: string, store: boolean, log: boolean) + logger[Identifier] = store + Logger.write(Identifier, `state: change -> {log == true and "enabled" or "disabled"} logger.`, log) +end + +function ClientProcess.getlogs(Identifier: string) + return Logger.read(Identifier) +end + +function ClientProcess.addCallback(Identifier: string, key: string, callback) + clientCallback[Identifier][key] = callback + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: change -> new callback added.`) + end +end + +function ClientProcess.removeCallback(Identifier: string, key: string) + clientCallback[Identifier][key] = nil + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: change -> removed a callback.`) + end +end + +function ClientProcess.start() + RunService.PostSimulation:Connect(function() + for Identifier: string, data: any in unreliableClientQueue do + if #data == 0 then continue end + if clientRatelimit[Identifier](#data) then + UnreliableEvent:FireServer(Buffer.revert(Identifier), data) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#data} data.`) + end + end + table.clear(data) + end + for Identifier: string, data: any in clientQueue do + local callback = clientCallback[Identifier] or nil + if #data > 0 then + if clientRatelimit[Identifier](#data) then + ReliableEvent:FireServer(Buffer.revert(Identifier), data) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> reliable -> {#data} data.`) + end + end + table.clear(data) + end + if #clientRequestQueue[Identifier] > 0 then + for _, requestData in clientRequestQueue[Identifier] do + if not requestData[3] then continue end + table.insert(queueOutRequest[1][Identifier], { requestData[1], requestData[3] }) + table.remove(requestData, #requestData) + end + end + if incoming_cache[Identifier] then + for _, packet in incoming_cache[Identifier] do + if not queueIn[Identifier] then continue end + table.insert(queueIn[Identifier], table.clone(packet)) + table.clear(incoming_cache[Identifier]) + end + end + if callback then + if #queueIn[Identifier] > 0 then + for _, packedDatas: any in queueIn[Identifier] do + if #packedDatas == 0 then continue end + for _, fn: any in callback do + for i=1,math.min(1e3, #packedDatas) do + Spawn(fn, table.unpack(packedDatas[i] or {})) + end + end + end + table.clear(queueIn[Identifier]) + end + if #queueInRequest[1][Identifier] > 0 then + for idx, packetDatas: any in queueInRequest[1][Identifier] do + if #packetDatas == 0 then continue end + for _, fn: any in callback do + for i=1,math.min(1e3, #packetDatas) do + local packetData = packetDatas[i] + if not packetData then continue end + Spawn(function() + local requestReturn = { fn(table.unpack(packetData[2])) } + table.insert(queueOutRequest[2][Identifier], { packetData[1], requestReturn }) + end) + end + end + end + table.clear(queueInRequest[1][Identifier]) + end + if #queueInRequest[2][Identifier] > 0 then + for _, packetDatas: any in queueInRequest[2][Identifier] do + for _, packetData in packetDatas do + if #packetData == 1 then continue end + for y=1, math.min(1e3, #clientRequestQueue[Identifier]) do + local clientRequest = clientRequestQueue[Identifier][y] + if not clientRequest then continue end + if clientRequest[1] == packetData[1] then + Spawn(clientRequest[2], table.unpack(packetData[2])) + table.remove(clientRequestQueue[Identifier], y) + break + end + end + end + end + table.clear(queueInRequest[2][Identifier]) + end + end + end + for Identifier: string, requestsData in queueOutRequest[1] do + if #requestsData == 0 then continue end + RequestEvent:FireServer(Buffer.revert(Identifier), "\1", requestsData) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> request -> {#requestsData} data.`) + end + table.clear(queueOutRequest[1][Identifier]) + end + for Identifier: string, toReturnDatas in queueOutRequest[2] do + if #toReturnDatas == 0 then continue end + RequestEvent:FireServer(Buffer.revert(Identifier), "\0", toReturnDatas) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> return request -> {#toReturnDatas} data.`) + end + table.clear(queueOutRequest[2][Identifier]) + end + end) + local function onClientNetworkReceive(Identifier: any, data: any) + if not Identifier or not data then return end + Identifier = Buffer.convert(Identifier) + if not queueIn[Identifier] then + queueIn[Identifier] = {} + end + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: in -> net -> {#data} data.`) + end + if not clientCallback[Identifier] then + if not incoming_cache[Identifier] then + incoming_cache[Identifier] = {} + end + table.insert(incoming_cache[Identifier], data) + return + end + table.insert(queueIn[Identifier], data) + end + ReliableEvent.OnClientEvent:Connect(onClientNetworkReceive) + UnreliableEvent.OnClientEvent:Connect(onClientNetworkReceive) + RequestEvent.OnClientEvent:Connect(function(Identifier: any, action: string, data) + if not Identifier or not data then return end + Identifier = Buffer.convert(Identifier) + if action == "\1" then + table.insert(queueInRequest[1][Identifier], data) + else + table.insert(queueInRequest[2][Identifier], data) + end + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: in -> request -> {#data} data.`) + end + end) +end + +return ClientProcess \ No newline at end of file diff --git a/src/Index/Client/Index.luau b/src/Index/Client/Index.luau index a5c3f7e..fc925ff 100644 --- a/src/Index/Client/Index.luau +++ b/src/Index/Client/Index.luau @@ -13,10 +13,10 @@ local Key = require(Util.Key) local Serdes = require(Util.Serdes) local Buffer = require(Util.Buffer) -function Client.new(Identifier: string) +function Client.new(Identifier: string, yieldWait: number?) local self = setmetatable({}, Client) self._buffer = Buffer.new() - self._buffer:wu8(Serdes(Identifier)) + self._buffer:wu8(Serdes(Identifier, yieldWait)) self.id = Buffer.convert(self._buffer:build()) self.fn = {} self.IsConnected = false @@ -25,6 +25,13 @@ function Client.new(Identifier: string) return self end +function Client:Logging(store: boolean, opt: boolean) + ClientProcess.logger(self.id, store, opt) + return function() + return ClientProcess.getlogs(self.id) + end +end + function Client:Fire(reliable: boolean,...: any) ClientProcess.insertQueue(self.id, reliable, ...) end diff --git a/src/Index/Server/Index.luau b/src/Index/Server/Index.luau index 48785a0..7202fd8 100644 --- a/src/Index/Server/Index.luau +++ b/src/Index/Server/Index.luau @@ -26,6 +26,13 @@ function Server.new(Identifier: string, rateLimit: Type.rateLimitArg?) return self end +function Server:Logging(store: boolean, opt: boolean) + ServerProcess.logger(self.id, store, opt) + return function() + return ServerProcess.getlogs(self.id) + end +end + function Server:Fire(reliable: boolean, player: Player, ...: any) ServerProcess.insertQueue(self.id, reliable, player, ...) end diff --git a/src/Index/Server/ServerProcess/Logger.luau b/src/Index/Server/ServerProcess/Logger.luau new file mode 100644 index 0000000..b6de03d --- /dev/null +++ b/src/Index/Server/ServerProcess/Logger.luau @@ -0,0 +1,32 @@ +--!strict +local Logger = {} +local Logs: { + [string]: { + [string]: string + } +} = {} +local logging: { + [string]: boolean +} = {} + +local now = tick() + +function Logger.write(Identifier: string, text: string, log: boolean?) + if not Logs[Identifier] then + Logs[Identifier] = {} + end + if log ~= nil then + logging[Identifier] = log + end + now = tick() + Logs[Identifier][tostring(now)] = text + if logging[Identifier] then + print(`[{now}] ->`, text) + end +end + +function Logger.read(Identifier: string) + return Logs[Identifier] +end + +return Logger \ No newline at end of file diff --git a/src/Index/Server/ServerProcess.luau b/src/Index/Server/ServerProcess/init.luau similarity index 85% rename from src/Index/Server/ServerProcess.luau rename to src/Index/Server/ServerProcess/init.luau index 3614246..f13e716 100644 --- a/src/Index/Server/ServerProcess.luau +++ b/src/Index/Server/ServerProcess/init.luau @@ -13,6 +13,7 @@ local Spawn = require(Util.Spawn) local Key = require(Util.Key) local RateLimit = require(Util.RateLimit) local Buffer = require(Util.Buffer) +local Logger = require(script.Logger) local serverQueue: Type.QueueMap = {} local unreliableServerQueue: Type.QueueMap = {} @@ -43,6 +44,10 @@ local queueOutRequest: { } } } = {} +local logger: { + [string]: boolean +} = {} + queueInRequest[1] = {} queueInRequest[2] = {} queueOutRequest[1] = {} @@ -131,12 +136,27 @@ function ServerProcess.add(Identifier: string, originId: string, ratelimit: Type end end +function ServerProcess.logger(Identifier: string, store: boolean, log: boolean) + logger[Identifier] = store + Logger.write(Identifier, `state: change -> {log == true and "enabled" or "disabled"} logger.`, log) +end + +function ServerProcess.getlogs(Identifier: string) + return Logger.read(Identifier) +end + function ServerProcess.addCallback(Identifier: string, key: string, callback) serverCallback[Identifier][key] = callback + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: change -> new callback added.`) + end end function ServerProcess.removeCallback(Identifier: string, key: string) serverCallback[Identifier][key] = nil + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: change -> removed a callback.`) + end end function ServerProcess.start() @@ -145,6 +165,9 @@ function ServerProcess.start() for player: Player, data: any in players do if #data == 0 then continue end UnreliableEvent:FireClient(player, Buffer.revert(Identifier), data) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#data} data.`) + end table.clear(data) end end @@ -153,10 +176,14 @@ function ServerProcess.start() for Identifier: string, data: any in queueOut[player] do if #data == 0 then continue end ReliableEvent:FireClient(player, Buffer.revert(Identifier), data) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> reliable -> {#data} data.`) + end table.clear(data) end end for Identifier: string, players in serverQueue do + local callback = serverCallback[Identifier] or nil for player: Player, data in players do if #data > 0 and queueOut[player] then queueOut[player][Identifier] = table.clone(data) @@ -169,11 +196,11 @@ function ServerProcess.start() table.remove(requestData, #requestData) end end - if serverCallback[Identifier] then + if callback then if #queueIn[Identifier][player] > 0 then for _, packedDatas: any in queueIn[Identifier][player] do if #packedDatas == 0 then continue end - for _, fn: any in serverCallback[Identifier] do + for _, fn: any in callback do for i=1,math.min(1e3, #packedDatas) do Spawn(fn, player, table.unpack(packedDatas[i] or {})) end @@ -184,7 +211,7 @@ function ServerProcess.start() if #queueInRequest[1][Identifier][player] > 0 then for idx, packetDatas: any in queueInRequest[1][Identifier][player] do if #packetDatas == 0 then continue end - for _, fn: any in serverCallback[Identifier] do + for _, fn: any in callback do for i=1,math.min(1e3, #packetDatas) do local packetData = packetDatas[i] if not packetData then continue end @@ -218,11 +245,17 @@ function ServerProcess.start() for player: Player, requestsData: any in queueOutRequest[1][Identifier] do if #requestsData == 0 then continue end RequestEvent:FireClient(player, Buffer.revert(Identifier), "\1", requestsData) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> request -> {#requestsData} data.`) + end table.clear(requestsData) end for player: Player, toReturnDatas: any in queueOutRequest[2][Identifier] do if #toReturnDatas == 0 then continue end RequestEvent:FireClient(player, Buffer.revert(Identifier), "\0", toReturnDatas) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> return request -> {#toReturnDatas} data.`) + end table.clear(toReturnDatas) end end @@ -241,6 +274,9 @@ function ServerProcess.start() if not queueIn[Identifier][player] then queueIn[Identifier][player] = {} end + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: in -> net -> {#data} data.`) + end table.insert(queueIn[Identifier][player], data) end ReliableEvent.OnServerEvent:Connect(onServerNetworkReceive) @@ -260,6 +296,9 @@ function ServerProcess.start() else table.insert(queueInRequest[2][Identifier][player], data) end + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: in -> request -> {#data} data.`) + end end) end diff --git a/src/Index/Signal/init.luau b/src/Index/Signal/init.luau index 5b7387c..567ab01 100644 --- a/src/Index/Signal/init.luau +++ b/src/Index/Signal/init.luau @@ -55,7 +55,7 @@ end function Signal:Fire(...: any): () for _, handle in self do - pcall(handle.fn, ...) + task.spawn(handle.fn, ...) end end diff --git a/src/Index/Type.luau b/src/Index/Type.luau index 0d3832e..79cbf04 100644 --- a/src/Index/Type.luau +++ b/src/Index/Type.luau @@ -13,6 +13,7 @@ export type Client = { DisconnectAll: (self: Client) -> (), Destroy: (self: Client) -> (), Wait: (self: Client) -> number, + Logging: (self: Client, store: boolean, opt: boolean) -> (), } export type Server = { @@ -25,6 +26,7 @@ export type Server = { DisconnectAll: (self: Server) -> (), Destroy: (self: Server) -> (), Wait: (self: Server) -> number, + Logging: (self: Server, store: boolean, opt: boolean) -> (), } export type Signal = { diff --git a/src/Index/Util/Assert.luau b/src/Index/Util/Assert.luau index c0932f3..ed9e790 100644 --- a/src/Index/Util/Assert.luau +++ b/src/Index/Util/Assert.luau @@ -1,4 +1,4 @@ --!strict return function(condition: (any), errorMessage: string?): () - if not (condition) then error(errorMessage, 2) end + if not (condition) then error(`Warp: {errorMessage}`, 2) end end \ No newline at end of file diff --git a/src/Index/Util/Buffer/Dedicated.luau b/src/Index/Util/Buffer/Dedicated.luau index 4860b69..552eb60 100644 --- a/src/Index/Util/Buffer/Dedicated.luau +++ b/src/Index/Util/Buffer/Dedicated.luau @@ -58,46 +58,55 @@ function DedicatedBuffer.build(self: any): buffer end function DedicatedBuffer.wi8(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 1) writei8(self.buffer, self.point, val) end function DedicatedBuffer.wi16(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 2) writei16(self.buffer, self.point, val) end function DedicatedBuffer.wi32(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 4) writei32(self.buffer, self.point, val) end function DedicatedBuffer.wu8(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 1) writeu8(self.buffer, self.point, val) end function DedicatedBuffer.wu16(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 2) writeu16(self.buffer, self.point, val) end function DedicatedBuffer.wu32(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 4) writeu32(self.buffer, self.point, val) end function DedicatedBuffer.wf32(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 4) writef32(self.buffer, self.point, val) end function DedicatedBuffer.wf64(self: any, val: number) + if not val then return end DedicatedBuffer.alloc(self, 8) writef64(self.buffer, self.point, val) end function DedicatedBuffer.wstring(self: any, val: string) + if not val then return end DedicatedBuffer.alloc(self, #val) writestring(self.buffer, self.point, val) end diff --git a/src/Index/Util/Key.luau b/src/Index/Util/Key.luau index 5ec0ed9..e807e73 100644 --- a/src/Index/Util/Key.luau +++ b/src/Index/Util/Key.luau @@ -1,4 +1,4 @@ --!strict return function(): number? - return tonumber(string.sub(tostring(Random.new():NextNumber()), 3, 6)) + return tonumber(string.sub(tostring(Random.new():NextNumber()), 3, 7)) -- 4 digits end \ No newline at end of file diff --git a/src/Index/Util/Serdes.luau b/src/Index/Util/Serdes.luau index d71743b..025fd68 100644 --- a/src/Index/Util/Serdes.luau +++ b/src/Index/Util/Serdes.luau @@ -5,19 +5,26 @@ local SerInt = 0 local Event = require(script.Parent.Parent.Event).Reliable local Assert = require(script.Parent.Assert) -return function(Identifier: string): number +return function(Identifier: string, timeout: number?): number Assert(typeof(Identifier) == "string", "Identifier must be a string type.") Assert(SerInt < 255, "reached max 255 identifiers.") if RunService:IsServer() then if not Event:GetAttribute(Identifier) then SerInt += 1 Event:SetAttribute(Identifier, SerInt) - --Event:SetAttribute(Identifier, string.pack("I1", SerInt)) -- I1 -> 255 max, I2 -> ~ 6.5e4 max. (SerInt) + --Event:SetAttribute(Identifier, string.pack("I1", SerInt)) -- I1 -> 255 max, I2 -> ~ 6.5e4 max. (SerInt), removed/disabled for buffer migration. end else - while not Event:GetAttribute(Identifier) do + local retreived = false + task.delay(timeout or 10, function() + if retreived then return end + retreived = true + 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) end + retreived = true end return Event:GetAttribute(Identifier) end \ No newline at end of file diff --git a/src/Index/init.luau b/src/Index/init.luau index 35ced65..7197f5f 100644 --- a/src/Index/init.luau +++ b/src/Index/init.luau @@ -25,10 +25,10 @@ function Index.Server(Identifier: string, rateLimit: Type.rateLimitArg?): Type.S Assert(typeof(Identifier) == "string", `[Warp]: Identifier must be a string type, got {typeof(Identifier)}`) return require(Server.Index)(Identifier, rateLimit) :: Type.Server end -function Index.Client(Identifier: string): Type.Client +function Index.Client(Identifier: string, yieldWait: number?): 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) :: Type.Client + return require(Client.Index)(Identifier, yieldWait) :: Type.Client end function Index.fromServerArray(arrays: { any }): Type.fromServerArray diff --git a/src/init.luau b/src/init.luau index fbaec6f..80607e0 100644 --- a/src/init.luau +++ b/src/init.luau @@ -1,5 +1,5 @@ -- Warp Library (@Eternity_Devs) --- version 1.0.8 +-- version 1.0.9 --!strict --!native --!optimize 2 diff --git a/wally.toml b/wally.toml index 15522a3..5adbc71 100644 --- a/wally.toml +++ b/wally.toml @@ -1,6 +1,6 @@ [package] name = "imezx/warp" -version = "1.0.8" +version = "1.0.9" registry = "https://github.com/UpliftGames/wally-index" realm = "shared" license = "MIT"