From dbed984eea678c794391666c1fa3bf43163aca86 Mon Sep 17 00:00:00 2001 From: EternityDev Date: Fri, 27 Sep 2024 11:10:12 +0700 Subject: [PATCH] v1.0.13 --- src/Index/Client/ClientProcess/Logger.luau | 7 +- src/Index/Client/ClientProcess/init.luau | 104 ++++++++++--------- src/Index/Client/Index.luau | 42 +++----- src/Index/Event.luau | 1 - src/Index/Server/Index.luau | 42 +++----- src/Index/Server/ServerProcess/Logger.luau | 7 +- src/Index/Server/ServerProcess/init.luau | 113 +++++++++++---------- src/Index/Signal/Dedicated.luau | 1 + src/Index/Signal/init.luau | 21 ++-- src/Index/Util/Assert.luau | 4 +- src/Index/Util/Buffer/Dedicated.luau | 2 +- src/Index/Util/Key.luau | 3 +- src/Index/Util/RateLimit.luau | 1 - src/Index/Util/Serdes.luau | 23 ++++- src/Index/Util/Spawn.luau | 38 ++++--- src/init.luau | 2 +- 16 files changed, 209 insertions(+), 202 deletions(-) diff --git a/src/Index/Client/ClientProcess/Logger.luau b/src/Index/Client/ClientProcess/Logger.luau index 29b0208..58401dd 100644 --- a/src/Index/Client/ClientProcess/Logger.luau +++ b/src/Index/Client/ClientProcess/Logger.luau @@ -1,5 +1,4 @@ --!strict ---!native --!optimize 2 local Logger = {} local Logs: { @@ -31,4 +30,8 @@ function Logger.read(Identifier: string) return Logs[Identifier] end -return Logger \ No newline at end of file +function Logger.clear(Identifier: string) + Logs[Identifier] = nil +end + +return Logger :: typeof(Logger) \ No newline at end of file diff --git a/src/Index/Client/ClientProcess/init.luau b/src/Index/Client/ClientProcess/init.luau index 00dbded..f595c1e 100644 --- a/src/Index/Client/ClientProcess/init.luau +++ b/src/Index/Client/ClientProcess/init.luau @@ -84,7 +84,7 @@ end function ClientProcess.add(Identifier: any, originId: string, conf: Type.ClientConf) if not table.find(registeredIdentifier, Identifier) then table.insert(registeredIdentifier, Identifier) - + if conf.logging then ClientProcess.logger(Identifier, conf.logging.store, conf.logging.opt) end @@ -122,6 +122,22 @@ function ClientProcess.add(Identifier: any, originId: string, conf: Type.ClientC end end +function ClientProcess.remove(Identifier: string) + if not table.find(registeredIdentifier, Identifier) then return end + table.remove(registeredIdentifier, table.find(registeredIdentifier, Identifier)) + clientQueue[Identifier] = nil + unreliableClientQueue[Identifier] = nil + clientRequestQueue[Identifier] = nil + clientCallback[Identifier] = nil + clientRatelimit[Identifier] = nil + queueOutRequest[1][Identifier] = nil + queueOutRequest[2][Identifier] = nil + queueInRequest[1][Identifier] = nil + queueInRequest[2][Identifier] = nil + queueIn[Identifier] = nil + Logger.clear(Identifier) +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) @@ -147,55 +163,49 @@ end function ClientProcess.start() debug.setmemorycategory("Warp") - local clock_limit = 1/60 - local past_clock = os.clock() - RunService.PostSimulation:Connect(function() - if (os.clock()-past_clock) >= (clock_limit - 0.006) then -- less potential to skip frames - past_clock = os.clock() - -- Unreliable - for Identifier: string, data: any in unreliableClientQueue do - if #data == 0 then continue end + -- Unreliable + 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 + unreliableClientQueue[Identifier] = nil + end + -- Reliable + for Identifier: string, data: any in clientQueue do + if #data > 0 then if clientRatelimit[Identifier](#data) then - UnreliableEvent:FireServer(Buffer.revert(Identifier), data) + ReliableEvent:FireServer(Buffer.revert(Identifier), data) if logger[Identifier] then - task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#data} data.`) + task.defer(Logger.write, Identifier, `state: out -> reliable -> {#data} data.`) end end - unreliableClientQueue[Identifier] = nil - end - -- Reliable - for Identifier: string, data: any in clientQueue do - 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 - clientQueue[Identifier] = nil - end - end - -- Sent new invokes - 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 - queueOutRequest[1][Identifier] = nil - end - -- Sent returning invokes - 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 - queueOutRequest[2][Identifier] = nil + clientQueue[Identifier] = nil end end - + -- Sent new invokes + 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 + queueOutRequest[1][Identifier] = nil + end + -- Sent returning invokes + 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 + queueOutRequest[2][Identifier] = nil + end + for _, Identifier: string in registeredIdentifier do if clientRequestQueue[Identifier] then for _, requestData in clientRequestQueue[Identifier] do @@ -207,11 +217,11 @@ function ClientProcess.start() requestData[3] = nil end end - + -- Unreliable & Reliable local callback = clientCallback[Identifier] or nil if not callback then continue end - + if queueIn[Identifier] then for _, packedDatas: any in queueIn[Identifier] do if #packedDatas == 0 then continue end @@ -223,7 +233,7 @@ function ClientProcess.start() end queueIn[Identifier] = nil end - + -- Return Invoke if queueInRequest[1][Identifier] then for _, packetDatas: any in queueInRequest[1][Identifier] do @@ -247,7 +257,7 @@ function ClientProcess.start() end queueInRequest[1][Identifier] = nil end - + -- Call to Invoke if queueInRequest[2][Identifier] then if clientRequestQueue[Identifier] then diff --git a/src/Index/Client/Index.luau b/src/Index/Client/Index.luau index eecfc0b..683e9f3 100644 --- a/src/Index/Client/Index.luau +++ b/src/Index/Client/Index.luau @@ -13,16 +13,14 @@ local Assert = require(Util.Assert) local Key = require(Util.Key) local Serdes = require(Util.Serdes) local Buffer = require(Util.Buffer) -local Middleware = require(Util.Middleware) function Client.new(Identifier: string, conf: Type.ClientConf?) local self = setmetatable({}, Client) self._buffer = Buffer.new() - self._buffer:wu8(Serdes(Identifier, conf and conf.yieldWait)) + self._buffer:wu8(Serdes.increment(Identifier, conf and conf.yieldWait)) self.id = Buffer.convert(self._buffer:build()) self.fn = {} - self.middleware = {} self._conf = table.freeze(conf or {}) self.IsConnected = false @@ -45,39 +43,23 @@ function Client:Invoke(timeout: number, ...: any): any return ClientProcess.insertRequest(self.id, timeout, ...) end -function Client:Connect(callback: (args: any) -> ()) +function Client:Connect(callback: (args: any) -> ()): string local key = tostring(Key()) - local _middleware = Middleware(key) - table.insert(self.fn, key) - self.middleware[key] = _middleware - self.IsConnected = #self.fn > 0 - ClientProcess.addCallback(self.id, key, function(...) - if _middleware.bridge(...) then - return callback(...) - end - return nil - end) - return _middleware + ClientProcess.addCallback(self.id, key, callback) + return key end -function Client:Once(callback: (args: any) -> ()) +function Client:Once(callback: (args: any) -> ()): string local key = tostring(Key()) - local _middleware = Middleware(key) - table.insert(self.fn, key) - self.middleware[key] = _middleware - self.IsConnected = #self.fn > 0 - ClientProcess.addCallback(self.id, key, function(...) + ClientProcess.addCallback(self.id, key, function(...: any?) self:Disconnect(key) - if _middleware.bridge(...) then - return callback(...) - end - return nil + task.spawn(callback, ...) end) - return _middleware + return key end function Client:Wait() @@ -99,14 +81,14 @@ function Client:Disconnect(key: string) ClientProcess.removeCallback(self.id, key) table.remove(self.fn, table.find(self.fn, key)) self.IsConnected = #self.fn > 0 - if self.middleware[key] then - self.middleware[key]:destroy() - self.middleware[key] = nil - end end function Client:Destroy() self:DisconnectAll() + self._buffer:remove() + ClientProcess.remove(self.id) + Serdes.decrement() + table.clear(self) setmetatable(self, nil) end diff --git a/src/Index/Event.luau b/src/Index/Event.luau index fd09c6e..909aed9 100644 --- a/src/Index/Event.luau +++ b/src/Index/Event.luau @@ -1,5 +1,4 @@ --!strict ---!native --!optimize 2 local RunService = game:GetService("RunService") local Type = require(script.Parent.Type) diff --git a/src/Index/Server/Index.luau b/src/Index/Server/Index.luau index f41f668..0078711 100644 --- a/src/Index/Server/Index.luau +++ b/src/Index/Server/Index.luau @@ -13,16 +13,14 @@ local Assert = require(Util.Assert) local Key = require(Util.Key) local Serdes = require(Util.Serdes) local Buffer = require(Util.Buffer) -local Middleware = require(Util.Middleware) function Server.new(Identifier: string, conf: Type.ServerConf?) local self = setmetatable({}, Server) self._buffer = Buffer.new() - self._buffer:wu8(Serdes(Identifier)) + self._buffer:wu8(Serdes.increment(Identifier)) self.id = Buffer.convert(self._buffer:build()) self.fn = {} - self.middleware = {} self._conf = table.freeze(conf or {}) self.IsConnected = false @@ -65,39 +63,23 @@ function Server:Invoke(timeout: number, player: Player, ...: any): any return ServerProcess.insertRequest(self.id, timeout, player, ...) end -function Server:Connect(callback: (plyer: Player, args: any) -> ()) +function Server:Connect(callback: (plyer: Player, args: any) -> ()): string local key = tostring(Key()) - local _middleware = Middleware(key) - table.insert(self.fn, key) - self.middleware[key] = _middleware - + ServerProcess.addCallback(self.id, key, callback) self.IsConnected = #self.fn > 0 - ServerProcess.addCallback(self.id, key, function(...) - if _middleware.bridge(...) then - return callback(...) - end - return nil - end) - return _middleware + return key end -function Server:Once(callback: (plyer: Player, args: any) -> ()) +function Server:Once(callback: (plyer: Player, args: any) -> ()): string local key = tostring(Key()) - local _middleware = Middleware(key) - table.insert(self.fn, key) - self.middleware[key] = _middleware - self.IsConnected = #self.fn > 0 - ServerProcess.addCallback(self.id, key, function(...) + ServerProcess.addCallback(self.id, key, function(player: Player, ...: any?) self:Disconnect(key) - if _middleware.bridge(...) then - return callback(...) - end - return nil + task.spawn(callback, player, ...) end) - return _middleware + return key end function Server:Wait() @@ -119,15 +101,15 @@ function Server:Disconnect(key: string): boolean ServerProcess.removeCallback(self.id, key) table.remove(self.fn, table.find(self.fn, key)) self.IsConnected = #self.fn > 0 - if self.middleware[key] then - self.middleware[key]:destroy() - self.middleware[key] = nil - end return table.find(self.fn, key) == nil end function Server:Destroy() self:DisconnectAll() + self._buffer:remove() + ServerProcess.remove(self.id) + Serdes.decrement() + table.clear(self) setmetatable(self, nil) end diff --git a/src/Index/Server/ServerProcess/Logger.luau b/src/Index/Server/ServerProcess/Logger.luau index 29b0208..58401dd 100644 --- a/src/Index/Server/ServerProcess/Logger.luau +++ b/src/Index/Server/ServerProcess/Logger.luau @@ -1,5 +1,4 @@ --!strict ---!native --!optimize 2 local Logger = {} local Logs: { @@ -31,4 +30,8 @@ function Logger.read(Identifier: string) return Logs[Identifier] end -return Logger \ No newline at end of file +function Logger.clear(Identifier: string) + Logs[Identifier] = nil +end + +return Logger :: typeof(Logger) \ No newline at end of file diff --git a/src/Index/Server/ServerProcess/init.luau b/src/Index/Server/ServerProcess/init.luau index d32b667..4beb9b6 100644 --- a/src/Index/Server/ServerProcess/init.luau +++ b/src/Index/Server/ServerProcess/init.luau @@ -142,9 +142,9 @@ end function ServerProcess.add(Identifier: string, originId: string, conf: Type.ServerConf) if not table.find(registeredIdentifier, Identifier) then table.insert(registeredIdentifier, Identifier) - + 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 @@ -183,6 +183,21 @@ function ServerProcess.add(Identifier: string, originId: string, conf: Type.Serv end end +function ServerProcess.remove(Identifier: string) + if not table.find(registeredIdentifier, Identifier) then return end + table.remove(registeredIdentifier, table.find(registeredIdentifier, Identifier)) + serverQueue[Identifier] = nil + serverRequestQueue[Identifier] = nil + serverCallback[Identifier] = nil + unreliableServerQueue[Identifier] = nil + queueIn[Identifier] = nil + queueInRequest[1][Identifier] = nil + queueInRequest[2][Identifier] = nil + queueOutRequest[1][Identifier] = nil + queueOutRequest[2][Identifier] = nil + Logger.clear(Identifier) +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) @@ -208,60 +223,54 @@ end function ServerProcess.start() debug.setmemorycategory("Warp") - local clock_limit = 1/60 - local past_clock = os.clock() - RunService.PostSimulation:Connect(function() - if (os.clock()-past_clock) >= (clock_limit - 0.006) then -- less potential to skip frames - past_clock = os.clock() - -- Unreliable - for Identifier: string, players in unreliableServerQueue do - for player: Player, content: any in players do - if #content == 0 then continue end - UnreliableEvent:FireClient(player, Buffer.revert(Identifier), content) + -- Unreliable + for Identifier: string, players in unreliableServerQueue do + for player: Player, content: any in players do + if #content == 0 then continue end + UnreliableEvent:FireClient(player, Buffer.revert(Identifier), content) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#content} data.`) + end + unreliableServerQueue[Identifier][player] = nil + end + unreliableServerQueue[Identifier] = nil + end + -- Reliable + for Identifier: string, contents: { [Player]: { any } } in serverQueue do + for player, content: any in contents do + if #content > 0 and queueOut[player] then + ReliableEvent:FireClient(player, Buffer.revert(Identifier), content) + end + serverQueue[Identifier][player] = nil + end + serverQueue[Identifier] = nil + end + -- Sent new invokes + for Identifier: string, contents in queueOutRequest[1] do + for player: Player, requestsData: any in contents do + if #requestsData > 0 then + RequestEvent:FireClient(player, Buffer.revert(Identifier), "\1", requestsData) if logger[Identifier] then - task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#content} data.`) + task.defer(Logger.write, Identifier, `state: out -> request -> {#requestsData} data.`) end - unreliableServerQueue[Identifier][player] = nil end - unreliableServerQueue[Identifier] = nil + queueOutRequest[1][Identifier][player] = nil end - -- Reliable - for Identifier: string, contents: { [Player]: { any } } in serverQueue do - for player, content: any in contents do - if #content > 0 and queueOut[player] then - ReliableEvent:FireClient(player, Buffer.revert(Identifier), content) + queueOutRequest[1][Identifier] = nil + end + -- Sent returning invokes + for Identifier: string, contents in queueOutRequest[2] do + for player: Player, toReturnDatas: any in contents do + if #toReturnDatas > 0 then + RequestEvent:FireClient(player, Buffer.revert(Identifier), "\0", toReturnDatas) + if logger[Identifier] then + task.defer(Logger.write, Identifier, `state: out -> return request -> {#toReturnDatas} data.`) end - serverQueue[Identifier][player] = nil end - serverQueue[Identifier] = nil - end - -- Sent new invokes - for Identifier: string, contents in queueOutRequest[1] do - for player: Player, requestsData: any in contents do - if #requestsData > 0 then - RequestEvent:FireClient(player, Buffer.revert(Identifier), "\1", requestsData) - if logger[Identifier] then - task.defer(Logger.write, Identifier, `state: out -> request -> {#requestsData} data.`) - end - end - queueOutRequest[1][Identifier][player] = nil - end - queueOutRequest[1][Identifier] = nil - end - -- Sent returning invokes - for Identifier: string, contents in queueOutRequest[2] do - for player: Player, toReturnDatas: any in contents do - if #toReturnDatas > 0 then - RequestEvent:FireClient(player, Buffer.revert(Identifier), "\0", toReturnDatas) - if logger[Identifier] then - task.defer(Logger.write, Identifier, `state: out -> return request -> {#toReturnDatas} data.`) - end - end - queueOutRequest[2][Identifier][player] = nil - end - queueOutRequest[2][Identifier] = nil + queueOutRequest[2][Identifier][player] = nil end + queueOutRequest[2][Identifier] = nil end for _, Identifier: string in registeredIdentifier do @@ -281,10 +290,10 @@ function ServerProcess.start() end end end - + local callback = serverCallback[Identifier] or nil if not callback then continue end - + -- Unreliable & Reliable for player, content in queueIn[Identifier] do if not callback then break end @@ -299,7 +308,7 @@ function ServerProcess.start() end queueIn[Identifier][player] = nil end - + -- Return Invoke for player, content in queueInRequest[1][Identifier] do if not callback then break end @@ -328,7 +337,7 @@ function ServerProcess.start() end queueInRequest[1][Identifier][player] = nil end - + -- Call to Invoke for player, content in queueInRequest[2][Identifier] do if not callback then break end diff --git a/src/Index/Signal/Dedicated.luau b/src/Index/Signal/Dedicated.luau index a4df234..8ffcf52 100644 --- a/src/Index/Signal/Dedicated.luau +++ b/src/Index/Signal/Dedicated.luau @@ -12,6 +12,7 @@ function Dedicated.new(signal: any, handler: (...any) -> ()) end function Dedicated:Disconnect() + table.clear(self) setmetatable(self, nil) end diff --git a/src/Index/Signal/init.luau b/src/Index/Signal/init.luau index df0cbbc..79fba7c 100644 --- a/src/Index/Signal/init.luau +++ b/src/Index/Signal/init.luau @@ -3,6 +3,7 @@ --!optimize 2 local Signal = {} Signal.__index = Signal +Signal.ClassName = "Signal" local DedicatedSignal = require(script.Dedicated) @@ -22,15 +23,15 @@ function Signal.new(Identifier: string) return Signals[Identifier] end -function Signal:Connect(fn: (...any) -> ()): string - local key = tostring(Key()) +function Signal:Connect(fn: (...any) -> (), optKey: string?): string + local key: typeof(Signal) = optKey or tostring(Key()) :: any self[key] = DedicatedSignal(self, fn) - return key + return key :: any end function Signal:Once(fn: (...any) -> ()): string local key: string - key = self:Connect(function(...) + key = self:Connect(function(...: any) self:Disconnect(key) task.spawn(fn, ...) end) @@ -38,19 +39,17 @@ function Signal:Once(fn: (...any) -> ()): string end function Signal:Disconnect(key: string) + if not self[key] then return end self[key]:Disconnect() self[key] = nil end function Signal:DisconnectAll(): () - for _, handle in self do - handle:Disconnect() - end table.clear(self) end function Signal:Wait(): number - local thread, t = coroutine.running(), os.clock() + local t, thread = os.clock(), coroutine.running() self:Once(function() task.spawn(thread, os.clock()-t) end) @@ -88,12 +87,6 @@ end function Signal:Destroy(): () self:DisconnectAll() - for idx: string, signal in Signals do - if self :: any == signal then - Signals[idx] = nil - break - end - end setmetatable(self, nil) end diff --git a/src/Index/Util/Assert.luau b/src/Index/Util/Assert.luau index de68818..770df1a 100644 --- a/src/Index/Util/Assert.luau +++ b/src/Index/Util/Assert.luau @@ -1,6 +1,6 @@ --!strict --!native --!optimize 2 -return function(condition: (any), errorMessage: string?): () - if not (condition) then error(`Warp: {errorMessage}`, 2) end +return function(condition: (any), errorMessage: string, level: number?): () + if not (condition) then error(`Warp: {errorMessage}`, level or 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 9dc446a..ac1f8f6 100644 --- a/src/Index/Util/Buffer/Dedicated.luau +++ b/src/Index/Util/Buffer/Dedicated.luau @@ -128,7 +128,7 @@ function DedicatedBuffer.new() end function DedicatedBuffer.remove(self: any) - self:flush() + table.clear(self) setmetatable(self, nil) end diff --git a/src/Index/Util/Key.luau b/src/Index/Util/Key.luau index db0ac6b..bb80093 100644 --- a/src/Index/Util/Key.luau +++ b/src/Index/Util/Key.luau @@ -1,6 +1,5 @@ --!strict ---!native --!optimize 2 return function(): number? - return tonumber(string.sub(tostring(Random.new():NextNumber()), 3, 6)) -- 4 digits + return tonumber(tostring(Random.new():NextNumber()):sub(3, 7)) -- 4-5 digits end \ No newline at end of file diff --git a/src/Index/Util/RateLimit.luau b/src/Index/Util/RateLimit.luau index 9b8177e..dc0470d 100644 --- a/src/Index/Util/RateLimit.luau +++ b/src/Index/Util/RateLimit.luau @@ -1,5 +1,4 @@ --!strict ---!native --!optimize 2 local RateLimit = {} diff --git a/src/Index/Util/Serdes.luau b/src/Index/Util/Serdes.luau index c028357..9b20775 100644 --- a/src/Index/Util/Serdes.luau +++ b/src/Index/Util/Serdes.luau @@ -1,18 +1,19 @@ --!strict ---!native --!optimize 2 +local SerDes = {} local RunService = game:GetService("RunService") local SerInt = 0 local Event = require(script.Parent.Parent.Event).Reliable local Assert = require(script.Parent.Assert) -return function(Identifier: string, timeout: number?): number +function SerDes.increment(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 + Assert(SerInt < 255, "reached max 255 identifiers.") if not Event:GetAttribute(Identifier) then SerInt += 1 + Event:SetAttribute(`{SerInt}`, Identifier) Event:SetAttribute(Identifier, SerInt) --Event:SetAttribute(Identifier, string.pack("I1", SerInt)) -- I1 -> 255 max, I2 -> ~ 6.5e4 max. (SerInt), removed/disabled for buffer migration. end @@ -20,11 +21,11 @@ return function(Identifier: string, timeout: number?): number 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) + error(`Serdes: {Identifier} is taking too long to retrieve, seems like it's not replicated on server.`, 2) end) task.spawn(function() while coroutine.status(cancel) ~= "dead" and task.wait(0.5) do -- let it loop for yields! - if (Event:GetAttribute(Identifier)) then + if Event:GetAttribute(Identifier) then task.cancel(cancel) task.spawn(yieldThread, Event:GetAttribute(Identifier)) break @@ -35,3 +36,15 @@ return function(Identifier: string, timeout: number?): number end return Event:GetAttribute(Identifier) end + +function SerDes.decrement() + if not RunService:IsServer() or SerInt <= 0 then return end + local Identifier = Event:GetAttribute(`{SerInt}`) + if not Identifier then return end + Event:SetAttribute(`{Identifier}`, nil) + Event:SetAttribute(`{SerInt}`, nil) + SerInt -= 1 + Identifier = nil +end + +return SerDes :: typeof(SerDes) \ No newline at end of file diff --git a/src/Index/Util/Spawn.luau b/src/Index/Util/Spawn.luau index 9281b82..f495ace 100644 --- a/src/Index/Util/Spawn.luau +++ b/src/Index/Util/Spawn.luau @@ -1,13 +1,20 @@ --!native --!strict --!optimize 2 -local thread: thread? = nil +local thread: thread? +local threads: { + thread +} = {} -local function passer(fn, ...): () - local hold = thread +local function passer(func: (T...) -> (), ...: T...): () + local HoldThread: thread = thread :: thread thread = nil - fn(...) - thread = hold + func(...) + if not thread then + thread = HoldThread + return + end + table.insert(threads, HoldThread) end local function yield(): never @@ -16,15 +23,22 @@ local function yield(): never end end -if not thread then - thread = coroutine.create(yield) - coroutine.resume(thread :: any, thread) +local function createThread(): () + local newThread: thread = coroutine.create(yield) + coroutine.resume(newThread, newThread) + table.insert(threads, newThread) end -return function(fn: (...any) -> (...any?), ...: any): () +for _=1,5 do + createThread() +end + +return function(func: (T...) -> (), ...: T...): () if not thread then - thread = coroutine.create(yield) - coroutine.resume(thread :: any, thread) + if #threads == 0 then + createThread() + end + thread = table.remove(threads, 1) end - task.spawn(thread :: thread, fn, ...) + task.spawn(thread :: thread, func, ...) end \ No newline at end of file diff --git a/src/init.luau b/src/init.luau index 15eae29..219e40d 100644 --- a/src/init.luau +++ b/src/init.luau @@ -1,5 +1,5 @@ -- Warp Library (@Eternity_Devs) --- version 1.0.12 +-- version 1.0.13 --!strict --!native --!optimize 2