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
-- Let's make the event have ratelimit with max 50 entrance for 2 seconds.
local Remote = Warp.Server("Remote1", {
rateLimit = {
maxEntrance = 50, -- maximum 50 fires.
interval = 2, -- 2 seconds
}
})
-- Now the Event RateLimit is configured, and ready to use.
-- No need anything to adds on client side.

View file

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

View file

@ -102,7 +102,23 @@ Signal1:DisconnectAll()
## `: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
```lua [Variable]
@ -122,7 +138,7 @@ This uses `pcall`, which means it never error (safe-mode, sacrificed debugging),
## `:FireTo`
Fire to other signal, this also use `:Fire`.
Fire to other signal, this uses `:Fire`.
::: code-group
```lua [Variable]

View file

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

View file

@ -19,6 +19,7 @@ local clientQueue: Type.QueueMap = {}
local unreliableClientQueue: Type.QueueMap = {}
local clientCallback: Type.CallbackMap = {}
local clientRequestQueue: Type.QueueMap = {}
local registeredIdentifier: { string } = {}
local queueIn: {
[string]: {any}
@ -37,11 +38,6 @@ local queueOutRequest: {
}
}
} = {}
local incoming_cache: {
[string]: {
any
}
} = {}
local logger: {
[string]: boolean
} = {}
@ -86,7 +82,9 @@ function ClientProcess.insertRequest(Identifier: string, timeout: number, ...: a
end
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
ClientProcess.logger(Identifier, conf.logging.store, conf.logging.opt)
end
@ -149,7 +147,13 @@ 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
if clientRatelimit[Identifier](#data) then
@ -160,8 +164,8 @@ function ClientProcess.start()
end
unreliableClientQueue[Identifier] = nil
end
-- Reliable
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)
@ -171,6 +175,28 @@ function ClientProcess.start()
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
for _, requestData in clientRequestQueue[Identifier] do
if not requestData[3] then continue end
@ -179,20 +205,12 @@ function ClientProcess.start()
end
table.insert(queueOutRequest[1][Identifier], { requestData[1], requestData[3] })
end
clientRequestQueue[Identifier] = nil
end
if callback then
if incoming_cache[Identifier] then
for _, packet in incoming_cache[Identifier] do
if #packet == 0 then continue end
for _, fn: any in callback do
for i=1,#packet do
Spawn(fn, table.unpack(packet[i] or {}))
end
end
end
incoming_cache[Identifier] = nil
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
@ -204,25 +222,32 @@ function ClientProcess.start()
end
queueIn[Identifier] = nil
end
-- Return Invoke
if queueInRequest[1][Identifier] then
for _, packetDatas: any in queueInRequest[1][Identifier] 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
if not packetDatas[i] then continue end
local packetData1 = packetDatas[i][1]
local packetData2 = packetDatas[i][2]
Spawn(function()
local requestReturn = { fn(table.unpack(packetData[2])) }
local requestReturn = { fn(table.unpack(packetData1)) }
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
table.insert(queueOutRequest[2][Identifier], { packetData[1], requestReturn })
table.insert(queueOutRequest[2][Identifier], { packetData2, requestReturn })
packetData1 = nil
packetData2 = nil
end)
end
end
end
queueInRequest[1][Identifier] = nil
end
-- Call to Invoke
if queueInRequest[2][Identifier] then
if clientRequestQueue[Identifier] then
for _, packetDatas: any in queueInRequest[2][Identifier] do
@ -243,23 +268,6 @@ function ClientProcess.start()
queueInRequest[2][Identifier] = nil
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)
local function onClientNetworkReceive(Identifier: any, data: any)
if not Identifier or not data then return end
@ -267,16 +275,6 @@ function ClientProcess.start()
if not queueIn[Identifier] then
queueIn[Identifier] = {}
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)
if logger[Identifier] then
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
queueOut[player][Identifier] = {}
end
if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {}
end
if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {}
end
if not queueIn[Identifier][player] then
queueIn[Identifier][player] = {}
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
queueInRequest[1][Identifier][player] = {}
queueInRequest[2][Identifier][player] = {}
@ -93,12 +102,18 @@ Players.PlayerAdded:Connect(initializeEachPlayer)
function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player: Player, ...: any)
if not reliable then
if not unreliableServerQueue[Identifier] then
unreliableServerQueue[Identifier] = {}
end
if not unreliableServerQueue[Identifier][player] then
unreliableServerQueue[Identifier][player] = {}
end
table.insert(unreliableServerQueue[Identifier][player], { ... })
return
end
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end
@ -106,12 +121,12 @@ function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player
end
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
serverRequestQueue[Identifier] = {}
end
if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {}
end
local yieldThread: thread, start = coroutine.running(), os.clock()
local cancel = task.delay(timeout, function()
task.spawn(yieldThread, nil)
@ -127,7 +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
@ -191,7 +208,13 @@ 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
@ -201,11 +224,21 @@ function ServerProcess.start()
end
unreliableServerQueue[Identifier][player] = nil
end
unreliableServerQueue[Identifier] = nil
end
-- Reliable
for Identifier: string, contents: { [Player]: { any } } in serverQueue do
for player: Player, requestsData: any in queueOutRequest[1][Identifier] 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
@ -214,8 +247,11 @@ function ServerProcess.start()
end
queueOutRequest[1][Identifier][player] = nil
end
for player: Player, toReturnDatas: any in queueOutRequest[2][Identifier] do
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
@ -224,66 +260,79 @@ function ServerProcess.start()
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)
queueOutRequest[2][Identifier] = nil
end
end
serverQueue[Identifier][player] = nil
if serverRequestQueue[Identifier][player] then
for _, requestData in serverRequestQueue[Identifier][player] do
for _, Identifier: string in registeredIdentifier do
if serverRequestQueue[Identifier] then
for player, content in serverRequestQueue[Identifier] do
for _, requestData in content do
if not requestData[3] then continue end
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
if not queueOutRequest[1][Identifier][player] then
queueOutRequest[1][Identifier][player] = {}
end
table.insert(queueOutRequest[1][Identifier][player], { requestData[1], requestData[3] })
end
serverRequestQueue[Identifier][player] = nil
end
end
if callback then
local requestIn1: any = queueInRequest[1][Identifier][player]
local requestIn2: any = queueInRequest[2][Identifier][player]
local incoming: any = queueIn[Identifier][player]
local callback = serverCallback[Identifier] or nil
if not callback then continue end
if incoming then
for _, packedDatas: any in incoming do
if #packedDatas == 0 then continue end
-- Unreliable & Reliable
for player, content in queueIn[Identifier] do
if not callback then break end
for _, incoming in content do
if not callback then break end
if #incoming == 0 then continue end
for _, fn: any in callback do
for i=1,#packedDatas do
Spawn(fn, player, table.unpack(packedDatas[i] or {}))
for i=1,#incoming do
Spawn(fn, player, table.unpack(incoming[i] or {}))
end
end
end
incoming = nil
queueIn[Identifier][player] = nil
end
if requestIn1 then
for _, packetDatas: any in requestIn1 do
-- 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
local packetData = packetDatas[i]
if not packetData then continue end
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(packetData[2])) }
local state = queueOutRequest[2][Identifier][player]
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], { packetData[1], requestReturn })
table.insert(queueOutRequest[2][Identifier][player], { packetData1, requestReturn })
packetData1 = nil
packetData2 = nil
end)
end
end
end
requestIn1 = nil
queueInRequest[1][Identifier][player] = nil
end
if requestIn2 then
for _, packetDatas: any in requestIn2 do
-- 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
@ -297,10 +346,8 @@ function ServerProcess.start()
end
end
end
requestIn2 = nil
queueInRequest[2][Identifier][player] = nil
end
end
serverRequestQueue[Identifier] = nil
end
end
end)
@ -330,6 +377,9 @@ function ServerProcess.start()
queueInRequest[1][Identifier][player] = {}
queueInRequest[2][Identifier][player] = {}
end
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end

View file

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

View file

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

View file

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