Warp/src/Index/Client/ClientProcess.luau

208 lines
6.2 KiB
Lua
Raw Normal View History

2024-01-30 06:36:08 +00:00
--!native
2024-01-05 12:14:38 +00:00
--!strict
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 clientRatelimit: Type.StoredRatelimit = {}
local clientQueue: Type.QueueMap = {}
local unreliableClientQueue: Type.QueueMap = {}
local clientCallback: Type.CallbackMap = {}
local clientRequestQueue: Type.QueueMap = {}
2024-01-31 06:33:19 +00:00
2024-01-05 12:14:38 +00:00
local queueIn: {
[string]: {any}
} = {}
local queueInRequest: {
[number]: {
[string]: {
any
}
}
} = {}
local queueOutRequest: {
[number]: {
[string]: {
any
}
}
} = {}
2024-01-31 06:33:19 +00:00
local incoming_cache: {
[string]: {
any
}
} = {}
2024-01-05 12:14:38 +00:00
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: string, 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.addCallback(Identifier: string, key: string, callback)
clientCallback[Identifier][key] = callback
end
function ClientProcess.removeCallback(Identifier: string, key: string)
clientCallback[Identifier][key] = nil
end
function ClientProcess.start()
RunService.PostSimulation:Connect(function()
for Identifier: string, data: any in unreliableClientQueue do
if #data > 0 then
if clientRatelimit[Identifier](#data) then
UnreliableEvent:FireServer(Identifier, data)
end
table.clear(data)
end
end
for Identifier: string, data: any in clientQueue do
if #data > 0 then
if clientRatelimit[Identifier](#data) then
ReliableEvent:FireServer(Identifier, data)
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
2024-01-31 06:33:19 +00:00
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 clientCallback[Identifier] then
2024-01-05 12:14:38 +00:00
if #queueIn[Identifier] > 0 then
for _, packedDatas: any in queueIn[Identifier] do
if #packedDatas == 0 then continue end
for _, v: any in packedDatas do
for _, fn: any in clientCallback[Identifier] do
Spawn(fn, table.unpack(v))
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 _, packetData in packetDatas do
for _, fn: any in clientCallback[Identifier] do
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 idx, clientRequest in clientRequestQueue[Identifier] do
if clientRequest[1] == packetData[1] then
Spawn(clientRequest[2], table.unpack(packetData[2]))
table.remove(clientRequestQueue[Identifier], idx)
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(Identifier, "\1", requestsData)
table.clear(queueOutRequest[1][Identifier])
end
for Identifier: string, requestsData in queueOutRequest[2] do
if #requestsData == 0 then continue end
RequestEvent:FireServer(Identifier, "\0", requestsData)
table.clear(queueOutRequest[2][Identifier])
end
end)
local function onClientNetworkReceive(Identifier: string, data: any)
if not Identifier or not data then return end
if not queueIn[Identifier] then
queueIn[Identifier] = {}
end
2024-01-31 06:33:19 +00:00
if not clientCallback[Identifier] then
if not incoming_cache[Identifier] then
incoming_cache[Identifier] = {}
end
table.insert(incoming_cache[Identifier], data)
return
end
2024-01-05 12:14:38 +00:00
table.insert(queueIn[Identifier], data)
end
ReliableEvent.OnClientEvent:Connect(onClientNetworkReceive)
UnreliableEvent.OnClientEvent:Connect(onClientNetworkReceive)
RequestEvent.OnClientEvent:Connect(function(Identifier: string, action: string, returnDatas)
if not Identifier or not returnDatas then return end
if action == "\1" then
table.insert(queueInRequest[1][Identifier], returnDatas)
else
table.insert(queueInRequest[2][Identifier], returnDatas)
end
end)
end
return ClientProcess