mirror of
https://github.com/imezx/Warp.git
synced 2026-06-02 12:18:32 +00:00
chore: fix client & server processing for invoke
This commit is contained in:
parent
80646eeebb
commit
b425db5f0b
3 changed files with 102 additions and 102 deletions
|
|
@ -3,10 +3,12 @@
|
||||||
--@EternityDev
|
--@EternityDev
|
||||||
local Client = {}
|
local Client = {}
|
||||||
|
|
||||||
local RunService = game:GetService("RunService")
|
|
||||||
local Thread = require("./Util/Thread")
|
local Thread = require("./Util/Thread")
|
||||||
local Buffer = require("./Util/Buffer")
|
local Buffer = require("./Util/Buffer")
|
||||||
local Replication = require("./Replication")
|
local Replication = require("./Replication")
|
||||||
|
local Xor = require("./Util/Xor")
|
||||||
|
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
local Event: RemoteEvent = script.Parent:WaitForChild("Event")
|
local Event: RemoteEvent = script.Parent:WaitForChild("Event")
|
||||||
local UnreliableEvent: UnreliableRemoteEvent = script.Parent:WaitForChild("UnreliableEvent")
|
local UnreliableEvent: UnreliableRemoteEvent = script.Parent:WaitForChild("UnreliableEvent")
|
||||||
local deltaT: number, cycle: number = 0, 1 / 61
|
local deltaT: number, cycle: number = 0, 1 / 61
|
||||||
|
|
@ -23,9 +25,10 @@ type Event = {
|
||||||
|
|
||||||
local queueEvent: { { any } } = {}
|
local queueEvent: { { any } } = {}
|
||||||
local queueUnreliableEvent: { { any } } = {}
|
local queueUnreliableEvent: { { any } } = {}
|
||||||
local eventListeners: { Event } = {}
|
local eventListeners: { [number]: { Event } } = {}
|
||||||
local eventSchemas: { [number]: Buffer.SchemaType } = {}
|
local eventSchemas: { [number]: Buffer.SchemaType } = {}
|
||||||
|
|
||||||
|
local lastDelta: { [number]: { any } } = {}
|
||||||
local pendingInvokes: { [string]: thread } = {}
|
local pendingInvokes: { [string]: thread } = {}
|
||||||
local invokeId = 0
|
local invokeId = 0
|
||||||
|
|
||||||
|
|
@ -52,13 +55,21 @@ Client.Connect = function(remoteName: string, fn: (Player, ...any?) -> ...any?):
|
||||||
local id = Replication.get_id[remoteName]
|
local id = Replication.get_id[remoteName]
|
||||||
if not id then
|
if not id then
|
||||||
warn(`[Warp]: ".Connect"::"{remoteName}" does not exist, likely its not registered on the server yet.`)
|
warn(`[Warp]: ".Connect"::"{remoteName}" does not exist, likely its not registered on the server yet.`)
|
||||||
return { Connected = false, Disconnect = function() return end } :: Connection
|
return {
|
||||||
|
Connected = false,
|
||||||
|
Disconnect = function()
|
||||||
|
return
|
||||||
|
end,
|
||||||
|
} :: Connection
|
||||||
end
|
end
|
||||||
local detail = {
|
local detail = {
|
||||||
i = id,
|
i = id,
|
||||||
c = fn,
|
c = fn,
|
||||||
}
|
}
|
||||||
table.insert(eventListeners, detail)
|
if not eventListeners[id] then
|
||||||
|
eventListeners[id] = {}
|
||||||
|
end
|
||||||
|
table.insert(eventListeners[id], detail)
|
||||||
return {
|
return {
|
||||||
Connected = true,
|
Connected = true,
|
||||||
Disconnect = function(self: Connection)
|
Disconnect = function(self: Connection)
|
||||||
|
|
@ -66,9 +77,12 @@ Client.Connect = function(remoteName: string, fn: (Player, ...any?) -> ...any?):
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.Connected = false
|
self.Connected = false
|
||||||
local idx = table.find(eventListeners, detail)
|
local bucket = eventListeners[detail.i]
|
||||||
if idx then
|
if bucket then
|
||||||
table.remove(eventListeners, idx)
|
local idx = table.find(bucket, detail)
|
||||||
|
if idx then
|
||||||
|
table.remove(bucket, idx)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
} :: Connection
|
} :: Connection
|
||||||
|
|
@ -105,11 +119,7 @@ Client.DisconnectAll = function(remoteName: string)
|
||||||
if not id then
|
if not id then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for idx = #eventListeners, 1, -1 do
|
eventListeners[id] = nil
|
||||||
if eventListeners[idx].i == id then
|
|
||||||
table.remove(eventListeners, idx)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--@remoteName string
|
--@remoteName string
|
||||||
|
|
@ -158,17 +168,16 @@ end
|
||||||
|
|
||||||
if RunService:IsClient() then
|
if RunService:IsClient() then
|
||||||
local function processIncoming(b: buffer, ref: { Instance }?, handleInvokes: boolean)
|
local function processIncoming(b: buffer, ref: { Instance }?, handleInvokes: boolean)
|
||||||
if type(b) ~= "buffer" then
|
if type(b) ~= "buffer" then return end
|
||||||
return
|
local decoded: buffer = handleInvokes and Xor.decodeClient(b) or b
|
||||||
end
|
local contents = Buffer.readEvents(decoded, ref, eventSchemas)
|
||||||
local contents = Buffer.readEvents(b, ref, eventSchemas)
|
|
||||||
for _, content in contents do
|
for _, content in contents do
|
||||||
local remote = content[1]
|
local remote = content[1]
|
||||||
local content = content[2]
|
local args = content[2]
|
||||||
if handleInvokes then
|
if handleInvokes then
|
||||||
if remote == 0 then
|
if remote == 0 then
|
||||||
local id = content[1]
|
local id = args[1]
|
||||||
local results = content[2]
|
local results = args[2]
|
||||||
local pending = pendingInvokes[id]
|
local pending = pendingInvokes[id]
|
||||||
if pending then
|
if pending then
|
||||||
task.spawn(pending :: any, table.unpack(results))
|
task.spawn(pending :: any, table.unpack(results))
|
||||||
|
|
@ -177,35 +186,22 @@ if RunService:IsClient() then
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
if remote == 1 then
|
if remote == 1 then
|
||||||
if #eventListeners == 0 then
|
local remoteName, id, rargs = args[1], args[2], args[3]
|
||||||
continue
|
local connections = eventListeners[remoteName]
|
||||||
end
|
if connections and #connections > 0 then
|
||||||
local remoteName = content[1]
|
Thread(function()
|
||||||
local id = content[2]
|
local results = { connections[1].c(table.unpack(rargs)) }
|
||||||
local args = content[3]
|
table.insert(queueEvent, { 1, { id, results } :: any })
|
||||||
for _, connection in eventListeners do
|
end)
|
||||||
if connection.i == remoteName then
|
|
||||||
Thread(function()
|
|
||||||
local results = { connection.c(table.unpack(args)) }
|
|
||||||
table.insert(queueEvent, {
|
|
||||||
1,
|
|
||||||
{ id, results } :: any,
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #eventListeners == 0 then
|
local connections = eventListeners[remote]
|
||||||
continue
|
if connections then
|
||||||
end
|
for _, connection in connections do
|
||||||
for _, connection in eventListeners do
|
Thread(connection.c, table.unpack(args))
|
||||||
if connection.i ~= remote then
|
|
||||||
continue
|
|
||||||
end
|
end
|
||||||
Thread(connection.c, table.unpack(content))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -220,21 +216,20 @@ if RunService:IsClient() then
|
||||||
|
|
||||||
RunService.PostSimulation:Connect(function(d: number)
|
RunService.PostSimulation:Connect(function(d: number)
|
||||||
deltaT += d
|
deltaT += d
|
||||||
if deltaT < cycle then
|
if deltaT < cycle then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
deltaT = 0
|
deltaT = 0
|
||||||
|
|
||||||
-- reliable
|
--reliable
|
||||||
if #queueEvent > 0 then
|
if #queueEvent > 0 then
|
||||||
Buffer.writeEvents(writer, queueEvent, eventSchemas)
|
Buffer.writeEvents(writer, queueEvent, eventSchemas)
|
||||||
do
|
do
|
||||||
local buf, ref = Buffer.buildWithRefs(writer)
|
local buf, ref = Buffer.buildWithRefs(writer)
|
||||||
|
local encoded = Xor.encodeClient(buf)
|
||||||
Buffer.reset(writer)
|
Buffer.reset(writer)
|
||||||
if not ref or #ref == 0 then
|
if not ref or #ref == 0 then
|
||||||
Event:FireServer(buf)
|
Event:FireServer(encoded)
|
||||||
else
|
else
|
||||||
Event:FireServer(buf, ref)
|
Event:FireServer(encoded, ref)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.clear(queueEvent)
|
table.clear(queueEvent)
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,6 @@ if RunService:IsClient() or RunService:IsRunMode() then
|
||||||
-- wait for the identifiers to be replicated from the server
|
-- wait for the identifiers to be replicated from the server
|
||||||
Replication.wait_for_ready = function()
|
Replication.wait_for_ready = function()
|
||||||
if is_ready then return end
|
if is_ready then return end
|
||||||
|
|
||||||
local thread = coroutine.running()
|
local thread = coroutine.running()
|
||||||
table.insert(ready_yields, thread)
|
table.insert(ready_yields, thread)
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,14 @@
|
||||||
--@EternityDev
|
--@EternityDev
|
||||||
local Server = {}
|
local Server = {}
|
||||||
|
|
||||||
local Players = game:GetService("Players")
|
|
||||||
local RunService = game:GetService("RunService")
|
|
||||||
local Thread = require("./Util/Thread")
|
local Thread = require("./Util/Thread")
|
||||||
local Buffer = require("./Util/Buffer")
|
local Buffer = require("./Util/Buffer")
|
||||||
local Identifier = require("./Util/Identifier")
|
local Identifier = require("./Util/Identifier")
|
||||||
local Replication = require("./Replication")
|
local Replication = require("./Replication")
|
||||||
|
local Xor = require("./Util/Xor")
|
||||||
|
|
||||||
|
local Players = game:GetService("Players")
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
local Event: RemoteEvent = script.Parent:WaitForChild("Event")
|
local Event: RemoteEvent = script.Parent:WaitForChild("Event")
|
||||||
local _repl: RemoteEvent = script.Parent:WaitForChild("_repl")
|
local _repl: RemoteEvent = script.Parent:WaitForChild("_repl")
|
||||||
local UnreliableEvent: UnreliableRemoteEvent = script.Parent:WaitForChild("UnreliableEvent")
|
local UnreliableEvent: UnreliableRemoteEvent = script.Parent:WaitForChild("UnreliableEvent")
|
||||||
|
|
@ -30,7 +32,7 @@ local queueEvent: {
|
||||||
local queueUnreliableEvent: {
|
local queueUnreliableEvent: {
|
||||||
[Player]: { { any } },
|
[Player]: { { any } },
|
||||||
} = {}
|
} = {}
|
||||||
local eventListeners: { Event } = {}
|
local eventListeners: { [number]: { Event } } = {}
|
||||||
local eventSchemas: { [number]: Buffer.SchemaType } = {}
|
local eventSchemas: { [number]: Buffer.SchemaType } = {}
|
||||||
local players_ready: { Player }, player_bytes: { [Player]: number } = {}, {}
|
local players_ready: { Player }, player_bytes: { [Player]: number } = {}, {}
|
||||||
|
|
||||||
|
|
@ -61,7 +63,10 @@ Server.Connect = function(remoteName: string, fn: (Player, ...any?) -> ...any?):
|
||||||
i = Identifier.get_id(remoteName),
|
i = Identifier.get_id(remoteName),
|
||||||
c = fn,
|
c = fn,
|
||||||
}
|
}
|
||||||
table.insert(eventListeners, detail)
|
if not eventListeners[detail.i] then
|
||||||
|
eventListeners[detail.i] = {}
|
||||||
|
end
|
||||||
|
table.insert(eventListeners[detail.i], detail)
|
||||||
return {
|
return {
|
||||||
Connected = true,
|
Connected = true,
|
||||||
Disconnect = function(self: Connection)
|
Disconnect = function(self: Connection)
|
||||||
|
|
@ -69,9 +74,12 @@ Server.Connect = function(remoteName: string, fn: (Player, ...any?) -> ...any?):
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.Connected = false
|
self.Connected = false
|
||||||
local idx = table.find(eventListeners, detail)
|
local bucket = eventListeners[detail.i]
|
||||||
if idx then
|
if bucket then
|
||||||
table.remove(eventListeners, idx)
|
local idx = table.find(bucket, detail)
|
||||||
|
if idx then
|
||||||
|
table.remove(bucket, idx)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
} :: Connection
|
} :: Connection
|
||||||
|
|
@ -108,11 +116,7 @@ Server.DisconnectAll = function(remoteName: string)
|
||||||
if not id then
|
if not id then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for idx = #eventListeners, 1, -1 do
|
eventListeners[id] = nil
|
||||||
if eventListeners[idx].i == id then
|
|
||||||
table.remove(eventListeners, idx)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--@remoteName string
|
--@remoteName string
|
||||||
|
|
@ -149,7 +153,9 @@ end
|
||||||
-- Fire an event to all players except specified ones.
|
-- Fire an event to all players except specified ones.
|
||||||
Server.FireExcept = function(remoteName: string, reliable: boolean, except: { Player }, ...: any?)
|
Server.FireExcept = function(remoteName: string, reliable: boolean, except: { Player }, ...: any?)
|
||||||
for _, player: Player in players_ready do
|
for _, player: Player in players_ready do
|
||||||
if table.find(except, player) then continue end
|
if table.find(except, player) then
|
||||||
|
continue
|
||||||
|
end
|
||||||
Server.Fire(remoteName, reliable, player, ...)
|
Server.Fire(remoteName, reliable, player, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -188,18 +194,21 @@ if RunService:IsServer() then
|
||||||
end
|
end
|
||||||
if not RunService:IsStudio() then
|
if not RunService:IsStudio() then
|
||||||
local bytes: number = (player_bytes[player] or 0) + math.max(buffer.len(b), 800)
|
local bytes: number = (player_bytes[player] or 0) + math.max(buffer.len(b), 800)
|
||||||
if bytes > 8e3 then return end
|
if bytes > 8e3 then
|
||||||
|
return
|
||||||
|
end
|
||||||
player_bytes[player] = bytes
|
player_bytes[player] = bytes
|
||||||
end
|
end
|
||||||
|
|
||||||
local contents = Buffer.readEvents(b, ref, eventSchemas)
|
local decoded = handleInvokes and Xor.decodeServer(player, b) or b
|
||||||
|
local contents = Buffer.readEvents(decoded, ref, eventSchemas)
|
||||||
for _, content in contents do
|
for _, content in contents do
|
||||||
local remote = content[1]
|
local remote = content[1]
|
||||||
local content = content[2]
|
local d = content[2]
|
||||||
if handleInvokes then
|
if handleInvokes then
|
||||||
if remote == 1 then
|
if remote == 1 then
|
||||||
local id = content[1]
|
local id = d[1]
|
||||||
local results = content[2]
|
local results = d[2]
|
||||||
local pending = pendingInvokes[id]
|
local pending = pendingInvokes[id]
|
||||||
if pending then
|
if pending then
|
||||||
task.spawn(pending :: any, table.unpack(results))
|
task.spawn(pending :: any, table.unpack(results))
|
||||||
|
|
@ -208,38 +217,33 @@ if RunService:IsServer() then
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
if remote == 0 then
|
if remote == 0 then
|
||||||
if #eventListeners == 0 then
|
if not next(eventListeners) then
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
local remoteName = content[1]
|
local remoteName = d[1]
|
||||||
local id = content[2]
|
local id = d[2]
|
||||||
local args = content[3]
|
local args = d[3]
|
||||||
for _, connection in eventListeners do
|
local connections = eventListeners[remoteName]
|
||||||
if connection.i == remoteName then
|
if connections and #connections > 0 then
|
||||||
Thread(function()
|
Thread(function()
|
||||||
local results = { connection.c(player, table.unpack(args)) }
|
local results = { connections[1].c(player, table.unpack(args)) }
|
||||||
if not queueEvent[player] then
|
if not queueEvent[player] then
|
||||||
queueEvent[player] = {} :: any
|
queueEvent[player] = {} :: any
|
||||||
end
|
end
|
||||||
table.insert(queueEvent[player], {
|
table.insert(queueEvent[player], {
|
||||||
0,
|
0,
|
||||||
{ id, results } :: any,
|
{ id, results } :: any,
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #eventListeners == 0 then
|
local connections = eventListeners[remote]
|
||||||
continue
|
if connections then
|
||||||
end
|
for _, connection in connections do
|
||||||
for _, connection in eventListeners do
|
Thread(connection.c, player, table.unpack(d))
|
||||||
if connection.i ~= remote then
|
|
||||||
continue
|
|
||||||
end
|
end
|
||||||
Thread(connection.c, player, table.unpack(content))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -267,11 +271,12 @@ if RunService:IsServer() then
|
||||||
Buffer.writeEvents(writer, content, eventSchemas)
|
Buffer.writeEvents(writer, content, eventSchemas)
|
||||||
do
|
do
|
||||||
local buf, ref = Buffer.buildWithRefs(writer)
|
local buf, ref = Buffer.buildWithRefs(writer)
|
||||||
|
local encoded = Xor.encodeServer(player, buf)
|
||||||
Buffer.reset(writer)
|
Buffer.reset(writer)
|
||||||
if not ref or #ref == 0 then
|
if not ref or #ref == 0 then
|
||||||
Event:FireClient(player, buf)
|
Event:FireClient(player, encoded)
|
||||||
else
|
else
|
||||||
Event:FireClient(player, buf, ref)
|
Event:FireClient(player, encoded, ref)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
player_bytes[player] = 0
|
player_bytes[player] = 0
|
||||||
|
|
@ -292,7 +297,7 @@ if RunService:IsServer() then
|
||||||
UnreliableEvent:FireClient(player, buf, ref)
|
UnreliableEvent:FireClient(player, buf, ref)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.clear(player_bytes)
|
player_bytes[player] = 0
|
||||||
table.clear(queueUnreliableEvent[player])
|
table.clear(queueUnreliableEvent[player])
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
@ -323,6 +328,7 @@ if RunService:IsServer() then
|
||||||
table.clear(queueUnreliableEvent[player])
|
table.clear(queueUnreliableEvent[player])
|
||||||
queueUnreliableEvent[player] = nil
|
queueUnreliableEvent[player] = nil
|
||||||
end
|
end
|
||||||
|
Xor.remove(player)
|
||||||
end)
|
end)
|
||||||
for _, player: Player in ipairs(Players:GetPlayers()) do
|
for _, player: Player in ipairs(Players:GetPlayers()) do
|
||||||
onAdded(player)
|
onAdded(player)
|
||||||
|
|
@ -330,9 +336,9 @@ if RunService:IsServer() then
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@class Server
|
@class Server
|
||||||
@schema
|
@schema
|
||||||
define a schema for your data and use a strict packing
|
define a schema for your data and use a strict packing
|
||||||
]]
|
]]
|
||||||
Server.Schema = Buffer.Schema
|
Server.Schema = Buffer.Schema
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue