Warp/src/Index/Server/ServerProcess/init.luau

404 lines
12 KiB
Lua
Raw Normal View History

2024-01-30 06:36:08 +00:00
--!native
2024-01-05 12:14:38 +00:00
--!strict
2024-03-13 01:13:01 +00:00
--!optimize 2
2024-01-05 12:14:38 +00:00
local ServerProcess = {}
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
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)
2024-03-13 01:13:01 +00:00
local Buffer = require(Util.Buffer)
2024-04-02 06:10:21 +00:00
local Logger = require(script.Logger)
2024-01-05 12:14:38 +00:00
local serverQueue: Type.QueueMap = {}
local unreliableServerQueue: Type.QueueMap = {}
local serverCallback: Type.CallbackMap = {}
local serverRequestQueue: Type.QueueMap = {}
2024-05-10 09:15:39 +00:00
local registeredIdentifier: { string } = {}
2024-01-31 06:33:19 +00:00
2024-01-05 12:14:38 +00:00
local queueOut: {
[Player]: {
[string]: {any},
}
} = {}
local queueIn: {
[string]: {
[Player]: {any},
}
} = {}
local queueInRequest: {
[number]: {
[string]: {
[Player]: {any}
}
}
} = {}
local queueOutRequest: {
[number]: {
[string]: {
[Player]: {any}
}
}
} = {}
2024-04-02 06:10:21 +00:00
local logger: {
[string]: boolean
} = {}
2024-04-13 02:00:52 +00:00
local players: {
Player
} = {}
2024-04-02 06:10:21 +00:00
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
local function initializeEachPlayer(player: Player)
if not player then return end
if not queueOut[player] then
queueOut[player] = {}
end
2024-05-10 09:15:39 +00:00
for _, Identifier: string in registeredIdentifier do
2024-03-02 16:43:36 +00:00
if not player then break end
2024-01-05 12:14:38 +00:00
if not queueOut[player][Identifier] then
queueOut[player][Identifier] = {}
end
2024-05-19 06:17:07 +00:00
if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {}
end
2024-01-05 12:14:38 +00:00
if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {}
end
if not queueIn[Identifier][player] then
queueIn[Identifier][player] = {}
end
2024-05-19 06:17:07 +00:00
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
2024-01-05 12:14:38 +00:00
if not queueInRequest[1][Identifier][player] then
queueInRequest[1][Identifier][player] = {}
queueInRequest[2][Identifier][player] = {}
end
if not queueOutRequest[1][Identifier][player] then
queueOutRequest[1][Identifier][player] = {}
queueOutRequest[2][Identifier][player] = {}
end
end
end
Players.PlayerAdded:Connect(initializeEachPlayer)
function ServerProcess.insertQueue(Identifier: string, reliable: boolean, player: Player, ...: any)
if not reliable then
2024-05-19 06:17:07 +00:00
if not unreliableServerQueue[Identifier] then
unreliableServerQueue[Identifier] = {}
end
2024-01-05 12:14:38 +00:00
if not unreliableServerQueue[Identifier][player] then
unreliableServerQueue[Identifier][player] = {}
end
table.insert(unreliableServerQueue[Identifier][player], { ... })
return
end
2024-05-19 06:17:07 +00:00
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
2024-01-05 12:14:38 +00:00
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end
table.insert(serverQueue[Identifier][player], { ... })
end
function ServerProcess.insertRequest(Identifier: string, timeout: number, player: Player, ...: any)
2024-05-11 02:29:53 +00:00
if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {}
end
2024-05-19 06:17:07 +00:00
if not serverRequestQueue[Identifier][player] then
serverRequestQueue[Identifier][player] = {}
end
2024-01-05 12:14:38 +00:00
local yieldThread: thread, start = coroutine.running(), os.clock()
local cancel = task.delay(timeout, function()
task.spawn(yieldThread, nil)
end)
table.insert(serverRequestQueue[Identifier][player], { 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
2024-05-04 05:49:50 +00:00
function ServerProcess.add(Identifier: string, originId: string, conf: Type.ServerConf)
2024-05-10 09:15:39 +00:00
if not table.find(registeredIdentifier, Identifier) then
table.insert(registeredIdentifier, Identifier)
2024-05-19 06:17:07 +00:00
2024-05-04 05:49:50 +00:00
RateLimit.create(originId, conf.rateLimit and conf.rateLimit.maxEntrance or 200, conf.rateLimit and conf.rateLimit.interval or 2)
2024-05-19 06:17:07 +00:00
2024-05-04 05:49:50 +00:00
if conf.logging then
ServerProcess.logger(Identifier, conf.logging.store, conf.logging.opt)
end
2024-04-09 08:49:06 +00:00
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
2024-05-10 09:15:39 +00:00
if not serverRequestQueue[Identifier] then
serverRequestQueue[Identifier] = {}
2024-04-09 08:49:06 +00:00
end
if not serverCallback[Identifier] then
serverCallback[Identifier] = {}
end
2024-05-10 09:15:39 +00:00
if not unreliableServerQueue[Identifier] then
unreliableServerQueue[Identifier] = {}
2024-04-09 08:49:06 +00:00
end
2024-05-04 05:49:50 +00:00
2024-04-09 08:49:06 +00:00
if not queueIn[Identifier] then
queueIn[Identifier] = {}
end
if not queueInRequest[1][Identifier] then
queueInRequest[1][Identifier] = {}
end
if not queueInRequest[2][Identifier] then
queueInRequest[2][Identifier] = {}
end
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
if not queueOutRequest[2][Identifier] then
queueOutRequest[2][Identifier] = {}
end
2024-05-04 05:49:50 +00:00
2024-01-06 03:41:10 +00:00
for _, player: Player in ipairs(Players:GetPlayers()) do
task.spawn(initializeEachPlayer, player)
end
2024-01-05 12:14:38 +00:00
end
end
2024-04-02 06:10:21 +00:00
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
2024-01-05 12:14:38 +00:00
function ServerProcess.addCallback(Identifier: string, key: string, callback)
serverCallback[Identifier][key] = callback
2024-04-02 06:10:21 +00:00
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: change -> new callback added.`)
end
2024-01-05 12:14:38 +00:00
end
function ServerProcess.removeCallback(Identifier: string, key: string)
serverCallback[Identifier][key] = nil
2024-04-02 06:10:21 +00:00
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: change -> removed a callback.`)
end
2024-01-05 12:14:38 +00:00
end
function ServerProcess.start()
2024-04-12 12:15:22 +00:00
debug.setmemorycategory("Warp")
2024-05-19 06:17:07 +00:00
local clock_limit = 1/60
local past_clock = os.clock()
2024-01-05 12:14:38 +00:00
RunService.PostSimulation:Connect(function()
2024-05-19 06:17:07 +00:00
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)
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: out -> unreliable -> {#content} data.`)
end
unreliableServerQueue[Identifier][player] = nil
2024-04-02 06:10:21 +00:00
end
2024-05-19 06:17:07 +00:00
unreliableServerQueue[Identifier] = nil
2024-01-05 12:14:38 +00:00
end
2024-05-19 06:17:07 +00:00
-- 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)
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
serverQueue[Identifier][player] = nil
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
serverQueue[Identifier] = nil
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
-- 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
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
queueOutRequest[1][Identifier][player] = nil
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
queueOutRequest[1][Identifier] = nil
2024-05-11 02:29:53 +00:00
end
2024-05-19 06:17:07 +00:00
-- 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
2024-01-05 12:14:38 +00:00
end
2024-05-19 06:17:07 +00:00
queueOutRequest[2][Identifier] = nil
end
end
for _, Identifier: string in registeredIdentifier do
if serverRequestQueue[Identifier] then
for player, content in serverRequestQueue[Identifier] do
2024-05-25 15:33:58 +00:00
if #content == 0 then serverRequestQueue[Identifier][player] = nil continue end
2024-05-19 06:17:07 +00:00
for _, requestData in content do
2024-01-05 12:14:38 +00:00
if not requestData[3] then continue end
2024-05-19 06:17:07 +00:00
if not queueOutRequest[1][Identifier] then
queueOutRequest[1][Identifier] = {}
end
2024-05-10 09:15:39 +00:00
if not queueOutRequest[1][Identifier][player] then
queueOutRequest[1][Identifier][player] = {}
end
2024-01-05 12:14:38 +00:00
table.insert(queueOutRequest[1][Identifier][player], { requestData[1], requestData[3] })
2024-05-25 15:33:58 +00:00
requestData[3] = nil
2024-01-05 12:14:38 +00:00
end
end
2024-05-19 06:17:07 +00:00
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
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,#incoming do
Spawn(fn, player, table.unpack(incoming[i] or {}))
2024-01-05 12:14:38 +00:00
end
end
2024-05-19 06:17:07 +00:00
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] = {}
2024-01-05 12:14:38 +00:00
end
2024-05-19 06:17:07 +00:00
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)
2024-01-05 12:14:38 +00:00
end
end
2024-05-19 06:17:07 +00:00
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
2024-01-05 12:14:38 +00:00
end
end
end
2024-05-10 09:15:39 +00:00
end
2024-05-19 06:17:07 +00:00
queueInRequest[2][Identifier][player] = nil
2024-01-05 12:14:38 +00:00
end
end
end)
2024-03-13 01:13:01 +00:00
local function onServerNetworkReceive(player: Player, Identifier: any, data: any)
2024-01-05 12:14:38 +00:00
if not Identifier or not data then return end
2024-03-13 01:13:01 +00:00
Identifier = Buffer.convert(Identifier)
2024-01-05 12:14:38 +00:00
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end
if not queueIn[Identifier][player] then
queueIn[Identifier][player] = {}
end
2024-04-02 06:10:21 +00:00
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: in -> net -> {#data} data.`)
end
2024-01-05 12:14:38 +00:00
table.insert(queueIn[Identifier][player], data)
end
ReliableEvent.OnServerEvent:Connect(onServerNetworkReceive)
UnreliableEvent.OnServerEvent:Connect(onServerNetworkReceive)
2024-03-13 01:13:01 +00:00
RequestEvent.OnServerEvent:Connect(function(player: Player, Identifier: any, action: string, data: any)
2024-01-05 12:14:38 +00:00
if not Identifier or not data then return end
2024-03-13 01:13:01 +00:00
Identifier = Buffer.convert(Identifier)
2024-01-05 12:14:38 +00:00
if not queueInRequest[1][Identifier][player] then
queueInRequest[1][Identifier][player] = {}
2024-05-25 15:33:58 +00:00
end
if not queueInRequest[2][Identifier][player] then
2024-01-05 12:14:38 +00:00
queueInRequest[2][Identifier][player] = {}
end
2024-05-19 06:17:07 +00:00
if not serverQueue[Identifier] then
serverQueue[Identifier] = {}
end
2024-01-05 12:14:38 +00:00
if not serverQueue[Identifier][player] then
serverQueue[Identifier][player] = {}
end
if action == "\1" then
table.insert(queueInRequest[1][Identifier][player], data)
else
table.insert(queueInRequest[2][Identifier][player], data)
end
2024-04-02 06:10:21 +00:00
if logger[Identifier] then
task.defer(Logger.write, Identifier, `state: in -> request -> {#data} data.`)
end
2024-01-05 12:14:38 +00:00
end)
end
for _, player: Player in ipairs(Players:GetPlayers()) do
task.spawn(initializeEachPlayer, player)
end
2024-01-31 06:33:19 +00:00
return ServerProcess