This commit is contained in:
EternityDev 2024-09-27 11:10:12 +07:00
parent 064075fbd9
commit dbed984eea
16 changed files with 209 additions and 202 deletions

View file

@ -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
function Logger.clear(Identifier: string)
Logs[Identifier] = nil
end
return Logger :: typeof(Logger)

View file

@ -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,12 +163,7 @@ 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
@ -194,7 +205,6 @@ function ClientProcess.start()
end
queueOutRequest[2][Identifier] = nil
end
end
for _, Identifier: string in registeredIdentifier do
if clientRequestQueue[Identifier] then

View file

@ -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

View file

@ -1,5 +1,4 @@
--!strict
--!native
--!optimize 2
local RunService = game:GetService("RunService")
local Type = require(script.Parent.Type)

View file

@ -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

View file

@ -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
function Logger.clear(Identifier: string)
Logs[Identifier] = nil
end
return Logger :: typeof(Logger)

View file

@ -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,12 +223,7 @@ 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
@ -262,7 +272,6 @@ function ServerProcess.start()
end
queueOutRequest[2][Identifier] = nil
end
end
for _, Identifier: string in registeredIdentifier do
if serverRequestQueue[Identifier] then

View file

@ -12,6 +12,7 @@ function Dedicated.new(signal: any, handler: (...any) -> ())
end
function Dedicated:Disconnect()
table.clear(self)
setmetatable(self, nil)
end

View file

@ -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

View file

@ -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

View file

@ -128,7 +128,7 @@ function DedicatedBuffer.new()
end
function DedicatedBuffer.remove(self: any)
self:flush()
table.clear(self)
setmetatable(self, nil)
end

View file

@ -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

View file

@ -1,5 +1,4 @@
--!strict
--!native
--!optimize 2
local RateLimit = {}

View file

@ -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)

View file

@ -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<T...>(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): ()
if not thread then
thread = coroutine.create(yield)
coroutine.resume(thread :: any, thread)
end
task.spawn(thread :: thread, fn, ...)
for _=1,5 do
createThread()
end
return function<T...>(func: (T...) -> (), ...: T...): ()
if not thread then
if #threads == 0 then
createThread()
end
thread = table.remove(threads, 1)
end
task.spawn(thread :: thread, func, ...)
end

View file

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