Compare commits

..

6 commits

Author SHA1 Message Date
EternityDev
0b1304f4c5 v1.0.14 2024-12-02 14:37:46 +07:00
EternityDev
d8526c7e25 pre v1.0.14 2024-12-01 21:10:56 +07:00
EternityDev
d065bc2e50 oops 2024-11-30 23:55:07 +07:00
EternityDev
925df47d4c improvements 2024-11-30 23:49:37 +07:00
EternityDev
f3b674b377 rewrite buffer instance type serialization for fix issues 2024-11-23 19:51:14 +07:00
EternityDev
677d3fa675 rewrite buffer instance type serialization for fix issues 2024-11-23 19:50:06 +07:00
10 changed files with 128 additions and 55 deletions

BIN
Warp.rbxm

Binary file not shown.

View file

@ -230,20 +230,18 @@ function ClientProcess.start()
end end
end end
end) end)
local function onClientNetworkReceive(Identifier: buffer | string, data: buffer) local function onClientNetworkReceive(Identifier: buffer | string, data: buffer, ref: { any }?)
if not Identifier or not data then return end if not Identifier or typeof(Identifier) ~= "buffer" or not data or typeof(data) ~= "buffer" then return end
Identifier = Buffer.convert(Identifier :: buffer) Identifier = Buffer.convert(Identifier)
local read = Buffer.read(data) if not registeredIdentifier[Identifier :: string] then return end
local read = Buffer.read(data, ref)
if not read then return end if not read then return end
for idx: string in registeredIdentifier do local callback = clientCallback[Identifier :: string]
if idx ~= Identifier then continue end if not callback then return end
local callback = clientCallback[idx] or nil
if not callback then continue end
for _, fn: any in callback do for _, fn: any in callback do
Spawn(fn, table.unpack(read)) Spawn(fn, table.unpack(read))
end end
end end
end
ReliableEvent.OnClientEvent:Connect(onClientNetworkReceive) ReliableEvent.OnClientEvent:Connect(onClientNetworkReceive)
UnreliableEvent.OnClientEvent:Connect(onClientNetworkReceive) UnreliableEvent.OnClientEvent:Connect(onClientNetworkReceive)
RequestEvent.OnClientEvent:Connect(function(Identifier: any, action: string, data) RequestEvent.OnClientEvent:Connect(function(Identifier: any, action: string, data)

View file

@ -49,12 +49,13 @@ local ReliableEvent = Event.Reliable
local UnreliableEvent = Event.Unreliable local UnreliableEvent = Event.Unreliable
local RequestEvent = Event.Request local RequestEvent = Event.Request
RateLimit.Protect()
local function initializeEachPlayer(player: Player) local function initializeEachPlayer(player: Player)
if not player then return end if not player then return end
if not queueOut[player] then if not queueOut[player] then
queueOut[player] = {} queueOut[player] = {}
end end
for Identifier: string in registeredIdentifier do for Identifier: string in registeredIdentifier do
if not player then break end if not player then break end
if not queueOut[player][Identifier] then if not queueOut[player][Identifier] then
@ -84,6 +85,29 @@ local function initializeEachPlayer(player: Player)
end end
Players.PlayerAdded:Connect(initializeEachPlayer) Players.PlayerAdded:Connect(initializeEachPlayer)
Players.PlayerRemoving:Connect(function(player: Player)
if not player then return end
if queueOut[player] then
queueOut[player] = nil
end
for _, map in { serverQueue, unreliableServerQueue, serverRequestQueue } do
for Identifier: string in map do
map[Identifier][player] = nil
end
end
for i=1,2 do
for Identifier: string in queueInRequest[i] do
if queueInRequest[i][Identifier][player] then
queueInRequest[i][Identifier][player] = nil
end
end
for Identifier: string in queueOutRequest[i] do
if queueOutRequest[i][Identifier][player] then
queueOutRequest[i][Identifier][player] = nil
end
end
end
end)
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
@ -303,20 +327,18 @@ function ServerProcess.start()
end end
end end
end) end)
local function onServerNetworkReceive(player: Player, Identifier: buffer | string, data: buffer) local function onServerNetworkReceive(player: Player, Identifier: buffer | string, data: buffer, ref: { any }?)
if not Identifier or not data then return end if not Identifier or typeof(Identifier) ~= "buffer" or not data or typeof(data) ~= "buffer" then return end
Identifier = Buffer.convert(Identifier :: buffer) Identifier = Buffer.convert(Identifier :: buffer)
local read = Buffer.read(data) if not registeredIdentifier[Identifier :: string] then return end
local read = Buffer.read(data, ref)
if not read then return end if not read then return end
for idx: string in registeredIdentifier do local callback = serverCallback[Identifier :: string]
if idx ~= Identifier then continue end if not callback then return end
local callback = serverCallback[idx] or nil
if not callback then continue end
for _, fn: any in callback do for _, fn: any in callback do
Spawn(fn, player, table.unpack(read)) Spawn(fn, player, table.unpack(read))
end end
end end
end
ReliableEvent.OnServerEvent:Connect(onServerNetworkReceive) ReliableEvent.OnServerEvent:Connect(onServerNetworkReceive)
UnreliableEvent.OnServerEvent:Connect(onServerNetworkReceive) UnreliableEvent.OnServerEvent:Connect(onServerNetworkReceive)
RequestEvent.OnServerEvent:Connect(function(player: Player, Identifier: any, action: string, data: any) RequestEvent.OnServerEvent:Connect(function(player: Player, Identifier: any, action: string, data: any)

View file

@ -36,7 +36,7 @@ function DedicatedBuffer.alloc(self: any, byte: number)
local b: buffer = self.buffer local b: buffer = self.buffer
while self.next + byte >= size do while self.next + byte >= size do
size = math.floor(size * 1.2) size = math.floor(size * 1.25) -- +25% increase
end end
local newBuffer: buffer = create(size) local newBuffer: buffer = create(size)
copy(newBuffer, 0, b) copy(newBuffer, 0, b)
@ -56,13 +56,15 @@ function DedicatedBuffer.build(self: any): buffer
return build return build
end end
function DedicatedBuffer.buildAndRemove(self: any): buffer function DedicatedBuffer.buildAndRemove(self: any): (buffer, (any)?)
local p: number = self.next > self.point and self.next or self.point local p: number = self.next > self.point and self.next or self.point
local build: buffer = create(p) local build: buffer = create(p)
local ref = #self.ref > 0 and table.clone(self.ref) or nil
copy(build, 0, self.buffer, 0, p) copy(build, 0, self.buffer, 0, p)
self:remove() self:remove()
return build return build, ref
end end
function DedicatedBuffer.wi8(self: any, val: number, alloc: number?) function DedicatedBuffer.wi8(self: any, val: number, alloc: number?)
@ -124,14 +126,21 @@ function DedicatedBuffer.wType(self: any, ref: number)
self.point += 1 self.point += 1
end end
function DedicatedBuffer.wRef(self: any, value: any, alloc: number?)
if not value then return end
self:alloc(alloc or 1)
table.insert(self.ref, value)
local index = #self.ref
writeu8(self.buffer, self.point, index)
self.point += 1
end
function DedicatedBuffer.pack(self: any, data: {any}) function DedicatedBuffer.pack(self: any, data: {any})
if typeof(data) == "nil" then if typeof(data) == "nil" then
self:wi8(0) self:wi8(0)
elseif typeof(data) == "Instance" then elseif typeof(data) == "Instance" then
self:wi8(-1) -- Instance marker self:wi8(-1) -- Instance marker
self:pack(data.ClassName) -- Serialize ClassName self:wRef(data)
self:pack(data.Name) -- Serialize Name
self:pack(data:GetAttributes())
elseif typeof(data) == "table" then elseif typeof(data) == "table" then
--local isArray = (next(data) ~= nil and #data > 0) and true or false --local isArray = (next(data) ~= nil and #data > 0) and true or false
local isArray = true local isArray = true
@ -232,6 +241,7 @@ function DedicatedBuffer.flush(self: any)
self.next = default.next self.next = default.next
self.size = default.size self.size = default.size
self.buffer = create(default.bufferSize) self.buffer = create(default.bufferSize)
table.clear(self.ref)
end end
function DedicatedBuffer.new() function DedicatedBuffer.new()
@ -239,7 +249,8 @@ function DedicatedBuffer.new()
point = default.point, point = default.point,
next = default.next, next = default.next,
size = default.size, size = default.size,
buffer = create(default.bufferSize) buffer = create(default.bufferSize),
ref = {},
}, DedicatedBuffer) }, DedicatedBuffer)
end end

View file

@ -18,28 +18,27 @@ local readf64 = buffer.readf64
local readstring = buffer.readstring local readstring = buffer.readstring
local len = buffer.len local len = buffer.len
local function readValue(b: buffer, position: number): (any, number) local function readValue(b: buffer, position: number, ref: { any }?): (any, number)
local typeByte = readi8(b, position) local typeByte = readi8(b, position)
position += 1 position += 1
if typeByte == 0 then -- nil if typeByte == 0 then -- nil
return nil, position return nil, position
elseif typeByte == -1 then -- Instance elseif typeByte == -1 then -- Instance
local className, position1 = readValue(b, position) if not ref or #ref == 0 then
local name, position2 = readValue(b, position1) return nil, position + 1
local properties, position3 = readValue(b, position2)
local instance: Instance = Instance.new(className)
instance.Name = name
for key, value in properties do
instance:SetAttribute(key, value)
end end
return instance, position3 local value = ref[readu8(b, position)]
if typeof(value) == "Instance" then
return value, position + 1
end
return nil, position + 1
elseif typeByte == -2 then -- array elseif typeByte == -2 then -- array
local length = readu16(b, position) local length = readu16(b, position)
position += 2 position += 2
local array = {} local array = {}
for _ = 1, length do for _ = 1, length do
local value local value
value, position = readValue(b, position) value, position = readValue(b, position, ref)
table.insert(array, value) table.insert(array, value)
end end
return array, position return array, position
@ -49,8 +48,8 @@ local function readValue(b: buffer, position: number): (any, number)
local dict = {} local dict = {}
for _ = 1, length do for _ = 1, length do
local key, value local key, value
key, position = readValue(b, position) key, position = readValue(b, position, ref)
value, position = readValue(b, position) value, position = readValue(b, position, ref)
dict[key] = value dict[key] = value
end end
return dict, position return dict, position
@ -129,20 +128,21 @@ function Buffer.revert(s: string): buffer
return fromstring(s) return fromstring(s)
end end
function Buffer.write(data: { any }): buffer function Buffer.write(data: { any }): (buffer, (any)?)
local newBuffer = Dedicated() local newBuffer = Dedicated()
newBuffer:pack(data) newBuffer:pack(data)
return newBuffer:buildAndRemove() return newBuffer:buildAndRemove()
end end
function Buffer.read(b: buffer): any? function Buffer.read(b: buffer, ref: { any }?): any?
local position = 0 local position = 0
local result = {} local result = {}
while position < len(b) do while position < len(b) do
local value local value
value, position = readValue(b, position) value, position = readValue(b, position, ref)
table.insert(result, value) table.insert(result, value)
end end
ref = nil
return table.unpack(result) return table.unpack(result)
end end

View file

@ -4,21 +4,51 @@ local RateLimit = {}
local RunService = game:GetService("RunService") local RunService = game:GetService("RunService")
local Assert = require(script.Parent.Assert) local Assert = require(script.Parent.Assert)
local Event = require(script.Parent.Parent.Event).Reliable local Events = require(script.Parent.Parent.Event)
local Reliable, Unreliable, Request = Events.Reliable, Events.Unreliable, Events.Request
local Signal = require(script.Parent.Parent.Signal)("Warp_OnSpamSignal")
local map, activity, meta = {}, {}, {}
setmetatable(meta , {
__index = map,
__newindex = function(self, key, value)
if not activity[key] then
activity[key] = os.clock()
end
if (os.clock()-activity[key]) >= 1 then
activity[key] = os.clock()
map[key] = 1
return
end
if value >= 1e2 then -- 100
Signal:Fire(key)
return
end
map[key] = value
end,
})
local function onReceived(player: Player)
if not meta[player] then
meta[player] = 1
return
end
meta[player] += 1
end
function RateLimit.create(Identifier: string, entrance: number?, interval: number?) function RateLimit.create(Identifier: string, entrance: number?, interval: number?)
Assert(typeof(Identifier) == "string", "Identifier must a string type.") Assert(typeof(Identifier) == "string", "Identifier must a string type.")
if RunService:IsServer() then if RunService:IsServer() then
Assert(typeof(entrance) == "number", "entrance must a number type.") Assert(typeof(entrance) == "number", "entrance must a number type.")
Assert(entrance :: number > 0, "entrance must above 0.") Assert(entrance :: number > 0, "entrance must above 0.")
Event:SetAttribute(Identifier.."_ent", entrance) Reliable:SetAttribute(Identifier.."_ent", entrance)
Event:SetAttribute(Identifier.."_int", interval) Reliable:SetAttribute(Identifier.."_int", interval)
else else
while (not Event:GetAttribute(Identifier.."_ent")) or (not Event:GetAttribute(Identifier.."_int")) do while (not Reliable:GetAttribute(Identifier.."_ent")) or (not Reliable:GetAttribute(Identifier.."_int")) do
task.wait(0.25) task.wait(0.1)
end end
entrance = tonumber(Event:GetAttribute(Identifier.."_ent")) entrance = tonumber(Reliable:GetAttribute(Identifier.."_ent"))
interval = tonumber(Event:GetAttribute(Identifier.."_int")) interval = tonumber(Reliable:GetAttribute(Identifier.."_int"))
end end
local entrances: number = 0 local entrances: number = 0
return function(incoming: number?): boolean return function(incoming: number?): boolean
@ -32,4 +62,14 @@ function RateLimit.create(Identifier: string, entrance: number?, interval: numbe
end end
end end
function RateLimit.Protect()
if not RunService:IsServer() or Reliable:GetAttribute("Protected") or Unreliable:GetAttribute("Protected") or Request:GetAttribute("Protected") then return end
Reliable:SetAttribute("Protected", true)
Unreliable:SetAttribute("Protected", true)
Request:SetAttribute("Protected", true)
Reliable.OnServerEvent:Connect(onReceived)
Unreliable.OnServerEvent:Connect(onReceived)
Request.OnServerEvent:Connect(onReceived)
end
return RateLimit :: typeof(RateLimit) return RateLimit :: typeof(RateLimit)

View file

@ -24,7 +24,7 @@ function SerDes.increment(Identifier: string, timeout: number?): number
error(`Serdes: {Identifier} is taking too long to retrieve, seems like it's not replicated on server.`, 2) error(`Serdes: {Identifier} is taking too long to retrieve, seems like it's not replicated on server.`, 2)
end) end)
task.spawn(function() task.spawn(function()
while coroutine.status(cancel) ~= "dead" and task.wait(0.25) do -- let it loop for yields! while coroutine.status(cancel) ~= "dead" and task.wait(0.04) do -- let it loop for yields! 1/24
if Event:GetAttribute(Identifier) then if Event:GetAttribute(Identifier) then
task.cancel(cancel) task.cancel(cancel)
task.spawn(yieldThread, Event:GetAttribute(Identifier)) task.spawn(yieldThread, Event:GetAttribute(Identifier))

View file

@ -1,5 +1,5 @@
-- Warp Library (@Eternity_Devs) -- Warp Library (@Eternity_Devs)
-- version 1.0.13 -- version 1.0.14
--!strict --!strict
--!native --!native
--!optimize 2 --!optimize 2
@ -11,6 +11,8 @@ return {
fromServerArray = Index.fromServerArray, fromServerArray = Index.fromServerArray,
fromClientArray = Index.fromClientArray, fromClientArray = Index.fromClientArray,
OnSpamSignal = Index.OnSpamSignal,
Signal = Index.Signal, Signal = Index.Signal,
fromSignalArray = Index.fromSignalArray, fromSignalArray = Index.fromSignalArray,

View file

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