This commit is contained in:
EternityDev 2024-05-19 13:17:07 +07:00
parent 44fa07df85
commit aa693aee4f
10 changed files with 284 additions and 208 deletions

BIN
Warp.rbxm

Binary file not shown.

View file

@ -13,8 +13,10 @@ When creating a event on Server, you can add second argument (optional) as table
-- Server -- Server
-- Let's make the event have ratelimit with max 50 entrance for 2 seconds. -- Let's make the event have ratelimit with max 50 entrance for 2 seconds.
local Remote = Warp.Server("Remote1", { local Remote = Warp.Server("Remote1", {
maxEntrance = 50, -- maximum 50 fires. rateLimit = {
interval = 2, -- 2 seconds maxEntrance = 50, -- maximum 50 fires.
interval = 2, -- 2 seconds
}
}) })
-- Now the Event RateLimit is configured, and ready to use. -- Now the Event RateLimit is configured, and ready to use.
-- No need anything to adds on client side. -- No need anything to adds on client side.

View file

@ -36,12 +36,16 @@ Create new Warp events with array.
```lua [Example] ```lua [Example]
local Events = Warp.fromServerArray({ local Events = Warp.fromServerArray({
["Remote1"] = { ["Remote1"] = {
maxEntrance: 50, rateLimit = {
interval: 1, maxEntrance: 50,
interval: 1,
}
}, -- with rateLimit configuration }, -- with rateLimit configuration
"Remote2", -- without rateLimit configuration "Remote2", -- without rateLimit configuration
["Remote3"] = { ["Remote3"] = {
maxEntrance: 10, rateLimit = {
maxEntrance: 10,
}
}, -- with rateLimit configuration }, -- with rateLimit configuration
}) })

View file

@ -102,7 +102,23 @@ Signal1:DisconnectAll()
## `:Fire` ## `:Fire`
Fire the signal. Fire the signal (Immediate)
::: code-group
```lua [Variable]
(
...: any
)
```
```lua [Example]
Signal1:Fire("Hello World!")
```
:::
## `:DeferFire`
Fire the signal (Deferred)
::: code-group ::: code-group
```lua [Variable] ```lua [Variable]
@ -122,7 +138,7 @@ This uses `pcall`, which means it never error (safe-mode, sacrificed debugging),
## `:FireTo` ## `:FireTo`
Fire to other signal, this also use `:Fire`. Fire to other signal, this uses `:Fire`.
::: code-group ::: code-group
```lua [Variable] ```lua [Variable]

View file

@ -8,7 +8,7 @@
::: code-group ::: code-group
```toml [wally.toml] ```toml [wally.toml]
[dependencies] [dependencies]
warp = "imezx/warp@1.0.5" warp = "imezx/warp@1.0.11"
``` ```
3. Run `wally install` in command. 3. Run `wally install` in command.

View file

@ -19,6 +19,7 @@ local clientQueue: Type.QueueMap = {}
local unreliableClientQueue: Type.QueueMap = {} local unreliableClientQueue: Type.QueueMap = {}
local clientCallback: Type.CallbackMap = {} local clientCallback: Type.CallbackMap = {}
local clientRequestQueue: Type.QueueMap = {} local clientRequestQueue: Type.QueueMap = {}
local registeredIdentifier: { string } = {}
local queueIn: { local queueIn: {
[string]: {any} [string]: {any}
@ -37,11 +38,6 @@ local queueOutRequest: {
} }
} }
} = {} } = {}
local incoming_cache: {
[string]: {
any
}
} = {}
local logger: { local logger: {
[string]: boolean [string]: boolean
} = {} } = {}
@ -86,7 +82,9 @@ function ClientProcess.insertRequest(Identifier: string, timeout: number, ...: a
end end
function ClientProcess.add(Identifier: any, originId: string, conf: Type.ClientConf) function ClientProcess.add(Identifier: any, originId: string, conf: Type.ClientConf)
if not clientQueue[Identifier] then if not table.find(registeredIdentifier, Identifier) then
table.insert(registeredIdentifier, Identifier)
if conf.logging then if conf.logging then
ClientProcess.logger(Identifier, conf.logging.store, conf.logging.opt) ClientProcess.logger(Identifier, conf.logging.store, conf.logging.opt)
end end
@ -149,28 +147,56 @@ end
function ClientProcess.start() function ClientProcess.start()
debug.setmemorycategory("Warp") debug.setmemorycategory("Warp")
local clock_limit = 1/60
local past_clock = os.clock()
RunService.PostSimulation:Connect(function() RunService.PostSimulation:Connect(function()
for Identifier: string, data: any in unreliableClientQueue do if (os.clock()-past_clock) >= (clock_limit - 0.006) then -- less potential to skip frames
if #data == 0 then continue end past_clock = os.clock()
if clientRatelimit[Identifier](#data) then -- Unreliable
UnreliableEvent:FireServer(Buffer.revert(Identifier), data) for Identifier: string, data: any in unreliableClientQueue do
if logger[Identifier] then if #data == 0 then continue end
task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#data} data.`)
end
end
unreliableClientQueue[Identifier] = nil
end
for Identifier: string, data: any in clientQueue do
local callback = clientCallback[Identifier] or nil
if #data > 0 then
if clientRatelimit[Identifier](#data) then if clientRatelimit[Identifier](#data) then
ReliableEvent:FireServer(Buffer.revert(Identifier), data) UnreliableEvent:FireServer(Buffer.revert(Identifier), data)
if logger[Identifier] then if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: out -> reliable -> {#data} data.`) task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#data} data.`)
end end
end end
clientQueue[Identifier] = nil unreliableClientQueue[Identifier] = nil
end 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
end
end
for _, Identifier: string in registeredIdentifier do
if clientRequestQueue[Identifier] then if clientRequestQueue[Identifier] then
for _, requestData in clientRequestQueue[Identifier] do for _, requestData in clientRequestQueue[Identifier] do
if not requestData[3] then continue end if not requestData[3] then continue end
@ -179,87 +205,69 @@ function ClientProcess.start()
end end
table.insert(queueOutRequest[1][Identifier], { requestData[1], requestData[3] }) table.insert(queueOutRequest[1][Identifier], { requestData[1], requestData[3] })
end end
clientRequestQueue[Identifier] = nil
end end
if callback then
if incoming_cache[Identifier] then -- Unreliable & Reliable
for _, packet in incoming_cache[Identifier] do local callback = clientCallback[Identifier] or nil
if #packet == 0 then continue end if not callback then continue end
for _, fn: any in callback do
for i=1,#packet do if queueIn[Identifier] then
Spawn(fn, table.unpack(packet[i] or {})) for _, packedDatas: any in queueIn[Identifier] do
end if #packedDatas == 0 then continue end
for _, fn: any in callback do
for i=1,#packedDatas do
Spawn(fn, table.unpack(packedDatas[i] or {}))
end end
end end
incoming_cache[Identifier] = nil
end end
if queueIn[Identifier] then queueIn[Identifier] = nil
for _, packedDatas: any in queueIn[Identifier] do end
if #packedDatas == 0 then continue end
for _, fn: any in callback do -- Return Invoke
for i=1,#packedDatas do if queueInRequest[1][Identifier] then
Spawn(fn, table.unpack(packedDatas[i] or {})) for _, packetDatas: any in queueInRequest[1][Identifier] do
end if #packetDatas == 0 then continue end
for _, fn: any in callback do
for i=1,#packetDatas do
if not packetDatas[i] then continue end
local packetData1 = packetDatas[i][1]
local packetData2 = packetDatas[i][2]
Spawn(function()
local requestReturn = { fn(table.unpack(packetData1)) }
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
table.insert(queueOutRequest[2][Identifier], { packetData2, requestReturn })
packetData1 = nil
packetData2 = nil
end)
end end
end end
queueIn[Identifier] = nil
end end
if queueInRequest[1][Identifier] then queueInRequest[1][Identifier] = nil
for _, packetDatas: any in queueInRequest[1][Identifier] do end
if #packetDatas == 0 then continue end
for _, fn: any in callback do -- Call to Invoke
for i=1,#packetDatas do if queueInRequest[2][Identifier] then
local packetData = packetDatas[i] if clientRequestQueue[Identifier] then
if not packetData then continue end for _, packetDatas: any in queueInRequest[2][Identifier] do
Spawn(function() for _, packetData in packetDatas do
local requestReturn = { fn(table.unpack(packetData[2])) } if #packetData == 1 then continue end
if not queueOutRequest[2][Identifier] then for y=1,#clientRequestQueue[Identifier] do
queueOutRequest[2][Identifier] = {} local clientRequest = clientRequestQueue[Identifier][y]
end if not clientRequest then continue end
table.insert(queueOutRequest[2][Identifier], { packetData[1], requestReturn }) if clientRequest[1] == packetData[1] then
end) Spawn(clientRequest[2], table.unpack(packetData[2]))
end table.remove(clientRequestQueue[Identifier], y)
end break
end
queueInRequest[1][Identifier] = nil
end
if queueInRequest[2][Identifier] then
if clientRequestQueue[Identifier] then
for _, packetDatas: any in queueInRequest[2][Identifier] do
for _, packetData in packetDatas do
if #packetData == 1 then continue end
for y=1,#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 end
end end
end end
queueInRequest[2][Identifier] = nil
end end
queueInRequest[2][Identifier] = nil
end 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
queueOutRequest[1][Identifier] = nil
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
queueOutRequest[2][Identifier] = nil
end
end) end)
local function onClientNetworkReceive(Identifier: any, data: any) local function onClientNetworkReceive(Identifier: any, data: any)
if not Identifier or not data then return end if not Identifier or not data then return end
@ -267,16 +275,6 @@ function ClientProcess.start()
if not queueIn[Identifier] then if not queueIn[Identifier] then
queueIn[Identifier] = {} queueIn[Identifier] = {}
end end
if not clientCallback[Identifier] then
if not incoming_cache[Identifier] then
incoming_cache[Identifier] = {}
end
table.insert(incoming_cache[Identifier], data)
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: cache -> net -> {#data} data.`)
end
return
end
table.insert(queueIn[Identifier], data) table.insert(queueIn[Identifier], data)
if logger[Identifier] then if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: in -> net -> {#data} data.`) task.defer(Logger.write, Identifier, `state: in -> net -> {#data} data.`)

View file

@ -72,12 +72,21 @@ local function initializeEachPlayer(player: Player)
if not queueOut[player][Identifier] then if not queueOut[player][Identifier] then
queueOut[player][Identifier] = {} queueOut[player][Identifier] = {}
end end
if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {}
end
if not serverRequestQueue[Identifier][player] then if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {} serverRequestQueue[Identifier][player] = {}
end end
if not queueIn[Identifier][player] then if not queueIn[Identifier][player] then
queueIn[Identifier][player] = {} queueIn[Identifier][player] = {}
end end
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
if not queueInRequest[1][Identifier][player] then if not queueInRequest[1][Identifier][player] then
queueInRequest[1][Identifier][player] = {} queueInRequest[1][Identifier][player] = {}
queueInRequest[2][Identifier][player] = {} queueInRequest[2][Identifier][player] = {}
@ -93,12 +102,18 @@ Players.PlayerAdded:Connect(initializeEachPlayer)
function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player: Player, ...: any) function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player: Player, ...: any)
if not reliable then if not reliable then
if not unreliableServerQueue[Identifier] then
unreliableServerQueue[Identifier] = {}
end
if not unreliableServerQueue[Identifier][player] then if not unreliableServerQueue[Identifier][player] then
unreliableServerQueue[Identifier][player] = {} unreliableServerQueue[Identifier][player] = {}
end end
table.insert(unreliableServerQueue[Identifier][player], { ... }) table.insert(unreliableServerQueue[Identifier][player], { ... })
return return
end end
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
if not serverQueue[Identifier][player] then if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {} serverQueue[Identifier][player] = {}
end end
@ -106,12 +121,12 @@ function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player
end end
function ServerProcess.insertRequest(Identifier: string, timeout: number, player: Player, ...: any) function ServerProcess.insertRequest(Identifier: string, timeout: number, player: Player, ...: any)
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end
if not serverRequestQueue[Identifier] then if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {} serverRequestQueue[Identifier] = {}
end end
if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {}
end
local yieldThread: thread, start = coroutine.running(), os.clock() local yieldThread: thread, start = coroutine.running(), os.clock()
local cancel = task.delay(timeout, function() local cancel = task.delay(timeout, function()
task.spawn(yieldThread, nil) task.spawn(yieldThread, nil)
@ -127,7 +142,9 @@ end
function ServerProcess.add(Identifier: string, originId: string, conf: Type.ServerConf) function ServerProcess.add(Identifier: string, originId: string, conf: Type.ServerConf)
if not table.find(registeredIdentifier, Identifier) then if not table.find(registeredIdentifier, Identifier) then
table.insert(registeredIdentifier, Identifier) table.insert(registeredIdentifier, Identifier)
RateLimit.create(originId, conf.rateLimit and conf.rateLimit.maxEntrance or 200, conf.rateLimit and conf.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 if conf.logging then
ServerProcess.logger(Identifier, conf.logging.store, conf.logging.opt) ServerProcess.logger(Identifier, conf.logging.store, conf.logging.opt)
end end
@ -191,116 +208,146 @@ end
function ServerProcess.start() function ServerProcess.start()
debug.setmemorycategory("Warp") debug.setmemorycategory("Warp")
local clock_limit = 1/60
local past_clock = os.clock()
RunService.PostSimulation:Connect(function() RunService.PostSimulation:Connect(function()
for Identifier: string, players in unreliableServerQueue do if (os.clock()-past_clock) >= (clock_limit - 0.006) then -- less potential to skip frames
for player: Player, content: any in players do past_clock = os.clock()
if #content == 0 then continue end -- Unreliable
UnreliableEvent:FireClient(player, Buffer.revert(Identifier), content) for Identifier: string, players in unreliableServerQueue do
if logger[Identifier] then for player: Player, content: any in players do
task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#content} data.`) 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 end
unreliableServerQueue[Identifier][player] = nil 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 -> 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
end end
end end
for Identifier: string, contents: { [Player]: { any } } in serverQueue do for _, Identifier: string in registeredIdentifier do
if serverRequestQueue[Identifier] then
for player: Player, requestsData: any in queueOutRequest[1][Identifier] do for player, content in serverRequestQueue[Identifier] do
if #requestsData > 0 then for _, requestData in content do
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
for player: Player, toReturnDatas: any in queueOutRequest[2][Identifier] 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
local callback = serverCallback[Identifier] or nil
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
if serverRequestQueue[Identifier][player] then
for _, requestData in serverRequestQueue[Identifier][player] do
if not requestData[3] then continue end if not requestData[3] then continue end
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
if not queueOutRequest[1][Identifier][player] then if not queueOutRequest[1][Identifier][player] then
queueOutRequest[1][Identifier][player] = {} queueOutRequest[1][Identifier][player] = {}
end end
table.insert(queueOutRequest[1][Identifier][player], { requestData[1], requestData[3] }) table.insert(queueOutRequest[1][Identifier][player], { requestData[1], requestData[3] })
end end
serverRequestQueue[Identifier][player] = nil
end end
end
if callback then local callback = serverCallback[Identifier] or nil
local requestIn1: any = queueInRequest[1][Identifier][player] if not callback then continue end
local requestIn2: any = queueInRequest[2][Identifier][player]
local incoming: any = queueIn[Identifier][player]
if incoming then -- Unreliable & Reliable
for _, packedDatas: any in incoming do for player, content in queueIn[Identifier] do
if #packedDatas == 0 then continue end if not callback then break end
for _, fn: any in callback do for _, incoming in content do
for i=1,#packedDatas do if not callback then break end
Spawn(fn, player, table.unpack(packedDatas[i] or {})) if #incoming == 0 then continue end
end for _, fn: any in callback do
end for i=1,#incoming do
Spawn(fn, player, table.unpack(incoming[i] or {}))
end end
incoming = nil
queueIn[Identifier][player] = nil
end
if requestIn1 then
for _, packetDatas: any in requestIn1 do
if #packetDatas == 0 then continue end
for _, fn: any in callback do
for i=1,#packetDatas do
local packetData = packetDatas[i]
if not packetData then continue end
Spawn(function()
local requestReturn = { fn(player, table.unpack(packetData[2])) }
local state = queueOutRequest[2][Identifier][player]
if not queueOutRequest[2][Identifier][player] then
queueOutRequest[2][Identifier][player] = {}
end
table.insert(queueOutRequest[2][Identifier][player], { packetData[1], requestReturn })
end)
end
end
end
requestIn1 = nil
queueInRequest[1][Identifier][player] = nil
end
if requestIn2 then
for _, packetDatas: any in requestIn2 do
for _, packetData in packetDatas do
if #packetData == 1 then continue end
local data = serverRequestQueue[Identifier][player]
for i=1,#data do
local serverRequest = data[i]
if not serverRequest then continue end
if serverRequest[1] == packetData[1] then
Spawn(serverRequest[2], table.unpack(packetData[2]))
table.remove(data, i)
break
end
end
end
end
requestIn2 = nil
queueInRequest[2][Identifier][player] = nil
end end
end end
queueIn[Identifier][player] = nil
end
-- Return Invoke
for player, content in queueInRequest[1][Identifier] do
if not callback then break end
for _, packetDatas in content do
if not callback then break end
if #packetDatas == 0 then continue end
for _, fn: any in callback do
for i=1,#packetDatas do
if not packetDatas[i] then continue end
local packetData1 = packetDatas[i][1]
local packetData2 = packetDatas[i][2]
Spawn(function()
local requestReturn = { fn(player, table.unpack(packetData2)) }
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
if not queueOutRequest[2][Identifier][player] then
queueOutRequest[2][Identifier][player] = {}
end
table.insert(queueOutRequest[2][Identifier][player], { packetData1, requestReturn })
packetData1 = nil
packetData2 = nil
end)
end
end
end
queueInRequest[1][Identifier][player] = nil
end
-- Call to Invoke
for player, content in queueInRequest[2][Identifier] do
if not callback then break end
for _, packetDatas in content do
for _, packetData in packetDatas do
if not callback then break end
if #packetData == 1 then continue end
local data = serverRequestQueue[Identifier][player]
for i=1,#data do
local serverRequest = data[i]
if not serverRequest then continue end
if serverRequest[1] == packetData[1] then
Spawn(serverRequest[2], table.unpack(packetData[2]))
table.remove(data, i)
break
end
end
end
end
queueInRequest[2][Identifier][player] = nil
serverRequestQueue[Identifier] = nil
end end
end end
end) end)
@ -330,6 +377,9 @@ function ServerProcess.start()
queueInRequest[1][Identifier][player] = {} queueInRequest[1][Identifier][player] = {}
queueInRequest[2][Identifier][player] = {} queueInRequest[2][Identifier][player] = {}
end end
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
if not serverQueue[Identifier][player] then if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {} serverQueue[Identifier][player] = {}
end end

View file

@ -53,6 +53,12 @@ function Signal:Wait(): number
return coroutine.yield() return coroutine.yield()
end end
function Signal:DeferFire(...: any): ()
for _, handle in self do
task.defer(handle.fn, ...)
end
end
function Signal:Fire(...: any): () function Signal:Fire(...: any): ()
for _, handle in self do for _, handle in self do
task.spawn(handle.fn, ...) task.spawn(handle.fn, ...)

View file

@ -1,5 +1,5 @@
-- Warp Library (@Eternity_Devs) -- Warp Library (@Eternity_Devs)
-- version 1.0.10 -- version 1.0.11
--!strict --!strict
--!native --!native
--!optimize 2 --!optimize 2

View file

@ -1,6 +1,6 @@
[package] [package]
name = "imezx/warp" name = "imezx/warp"
version = "1.0.10" version = "1.0.11"
registry = "https://github.com/UpliftGames/wally-index" registry = "https://github.com/UpliftGames/wally-index"
realm = "shared" realm = "shared"
license = "MIT" license = "MIT"