diff --git a/addons/observers.luau b/addons/observers.luau index 809d32e..e2e18e7 100644 --- a/addons/observers.luau +++ b/addons/observers.luau @@ -1,26 +1,22 @@ local jecs = require("@jecs") -type Observer = { - callback: (jecs.Entity) -> (), - query: jecs.Query<...any>, -} - -type Monitor = { - callback: (jecs.Entity, jecs.Entity) -> (), - query: jecs.Query -} - export type PatchedWorld = jecs.World & { added: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (), removed: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id) -> ()) -> () -> (), changed: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (), - observer: (PatchedWorld, Observer) -> (), - monitor: (PatchedWorld, Monitor) -> (), + observer: ( + PatchedWorld, + any, + (jecs.Entity) -> () + ) -> (), + monitor: ( + PatchedWorld, + any, + (jecs.Entity, jecs.Id) -> () + ) -> () } -local function observers_new(world, description) - local query = description.query - local callback = description.callback +local function observers_new(world, query, callback) local terms = query.filter_with :: { jecs.Id } if not terms then local ids = query.ids @@ -94,9 +90,7 @@ local function join(world, component) end end -local function monitors_new(world, description) - local query = description.query - local callback = description.callback +local function monitors_new(world, query, callback) local terms = query.filter_with :: { jecs.Id } if not terms then local ids = query.ids @@ -131,7 +125,8 @@ local function monitors_new(world, description) local archetype = r.archetype if jecs.query_match(query, archetype) then - callback(entity, jecs.OnRemove) + local EcsOnRemove = jecs.OnRemove :: jecs.Id + callback(entity, EcsOnRemove) end end @@ -162,7 +157,7 @@ local function observers_add(world: jecs.World): PatchedWorld listeners = {} signals.added[component] = listeners - local function on_add(entity: number, id: number, value: any) + local function on_add(entity, id, value) for _, listener in listeners :: any do listener(entity, id, value) end @@ -170,13 +165,14 @@ local function observers_add(world: jecs.World): PatchedWorld local existing_hook = world:get(component, jecs.OnAdd) if existing_hook then table.insert(listeners, existing_hook) - local idr = world.component_index[component] - if idr then - idr.hooks.on_add = on_add - end end - world:set(component, jecs.OnAdd, on_add) + local idr = world.component_index[component] + if idr then + idr.hooks.on_add = on_add + else + world:set(component, jecs.OnAdd, on_add) + end end table.insert(listeners, fn) return function() @@ -196,7 +192,7 @@ local function observers_add(world: jecs.World): PatchedWorld if not listeners then listeners = {} signals.emplaced[component] = listeners - local function on_change(entity: number, id: number, value: any) + local function on_change(entity, id, value: any) for _, listener in listeners :: any do listener(entity, id, value) end @@ -204,12 +200,13 @@ local function observers_add(world: jecs.World): PatchedWorld local existing_hook = world:get(component, jecs.OnChange) if existing_hook then table.insert(listeners, existing_hook) - local idr = world.component_index[component] - if idr then - idr.hooks.on_change = on_change - end end - world:set(component, jecs.OnChange, on_change) + local idr = world.component_index[component] + if idr then + idr.hooks.on_change = on_change + else + world:set(component, jecs.OnChange, on_change) + end end table.insert(listeners, fn) return function() @@ -229,23 +226,26 @@ local function observers_add(world: jecs.World): PatchedWorld if not listeners then listeners = {} signals.removed[component] = listeners - local function on_remove(entity: number, id: number, value: any) + local function on_remove(entity, id) for _, listener in listeners :: any do - listener(entity, id, value) + listener(entity, id) end end local existing_hook = world:get(component, jecs.OnRemove) if existing_hook then table.insert(listeners, existing_hook) - local idr = world.component_index[component] - if idr then - idr.hooks.on_remove = on_remove - end end - world:set(component, jecs.OnRemove, on_remove) + local idr = world.component_index[component] + if idr then + idr.hooks.on_remove = on_remove + else + world:set(component, jecs.OnRemove, on_remove) + end end + table.insert(listeners, fn) + return function() local n = #listeners local i = table.find(listeners, fn) diff --git a/demo/.config/blink b/demo/.config/blink deleted file mode 100644 index 3675cf7..0000000 --- a/demo/.config/blink +++ /dev/null @@ -1,18 +0,0 @@ -option ClientOutput = "../net/client.luau" -option ServerOutput = "../net/server.luau" - -event UpdateTransform { - From: Server, - Type: Unreliable, - Call: SingleSync, - Poll: true, - Data: (f64, CFrame) -} - -event SpawnMob { - From: Server, - Type: Reliable, - Call: SingleSync, - Poll: true, - Data: (f64, CFrame, u8) -} diff --git a/demo/net/client.luau b/demo/net/client.luau deleted file mode 100644 index 062dcab..0000000 --- a/demo/net/client.luau +++ /dev/null @@ -1,336 +0,0 @@ ---!strict ---!native ---!optimize 2 ---!nolint LocalShadow ---#selene: allow(shadowing) --- File generated by Blink v0.14.1 (https://github.com/1Axen/Blink) --- This file is not meant to be edited - -local ReplicatedStorage = game:GetService("ReplicatedStorage") -local RunService = game:GetService("RunService") - -if not RunService:IsClient() then - error("Client network module can only be required from the client.") -end - -local Reliable: RemoteEvent = ReplicatedStorage:WaitForChild("BLINK_RELIABLE_REMOTE") :: RemoteEvent -local Unreliable: UnreliableRemoteEvent = - ReplicatedStorage:WaitForChild("BLINK_UNRELIABLE_REMOTE") :: UnreliableRemoteEvent - -local Invocations = 0 - -local SendSize = 64 -local SendOffset = 0 -local SendCursor = 0 -local SendBuffer = buffer.create(64) -local SendInstances = {} - -local RecieveCursor = 0 -local RecieveBuffer = buffer.create(64) - -local RecieveInstances = {} -local RecieveInstanceCursor = 0 - -type Entry = { - value: any, - next: Entry?, -} - -type Queue = { - head: Entry?, - tail: Entry?, -} - -type BufferSave = { - Size: number, - Cursor: number, - Buffer: buffer, - Instances: { Instance }, -} - -local function Read(Bytes: number) - local Offset = RecieveCursor - RecieveCursor += Bytes - return Offset -end - -local function Save(): BufferSave - return { - Size = SendSize, - Cursor = SendCursor, - Buffer = SendBuffer, - Instances = SendInstances, - } -end - -local function Load(Save: BufferSave?) - if Save then - SendSize = Save.Size - SendCursor = Save.Cursor - SendOffset = Save.Cursor - SendBuffer = Save.Buffer - SendInstances = Save.Instances - return - end - - SendSize = 64 - SendCursor = 0 - SendOffset = 0 - SendBuffer = buffer.create(64) - SendInstances = {} -end - -local function Invoke() - if Invocations == 255 then - Invocations = 0 - end - - local Invocation = Invocations - Invocations += 1 - return Invocation -end - -local function Allocate(Bytes: number) - local InUse = (SendCursor + Bytes) - if InUse > SendSize then - --> Avoid resizing the buffer for every write - while InUse > SendSize do - SendSize *= 1.5 - end - - local Buffer = buffer.create(SendSize) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - SendBuffer = Buffer - end - - SendOffset = SendCursor - SendCursor += Bytes - - return SendOffset -end - -local function CreateQueue(): Queue - return { - head = nil, - tail = nil, - } -end - -local function Pop(queue: Queue): any - local head = queue.head - if head == nil then - return - end - - queue.head = head.next - return head.value -end - -local function Push(queue: Queue, value: any) - local entry: Entry = { - value = value, - next = nil, - } - - if queue.tail ~= nil then - queue.tail.next = entry - end - - queue.tail = entry - - if queue.head == nil then - queue.head = entry - end -end - -local Types = {} -local Calls = table.create(256) - -local Events: any = { - Reliable = table.create(256), - Unreliable = table.create(256), -} - -local Queue: any = { - Reliable = table.create(256), - Unreliable = table.create(256), -} - -Queue.Unreliable[0] = CreateQueue() -Queue.Reliable[0] = CreateQueue() - -function Types.ReadEVENT_UpdateTransform(): (number, CFrame) - -- Read BLOCK: 32 bytes - local BLOCK_START = Read(32) - local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0) - local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8) - local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12) - local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16) - local Position = Vector3.new(X, Y, Z) - local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20) - local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24) - local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28) - local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ) - return Value1, Value2 -end - -function Types.WriteEVENT_UpdateTransform(Value1: number, Value2: CFrame): () - -- Allocate BLOCK: 33 bytes - local BLOCK_START = Allocate(33) - buffer.writeu8(SendBuffer, BLOCK_START + 0, 0) - buffer.writef64(SendBuffer, BLOCK_START + 1, Value1) - local Vector = Value2.Position - buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X) - buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y) - buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z) - local rX, rY, rZ = Value2:ToOrientation() - buffer.writef32(SendBuffer, BLOCK_START + 21, rX) - buffer.writef32(SendBuffer, BLOCK_START + 25, rY) - buffer.writef32(SendBuffer, BLOCK_START + 29, rZ) -end - -function Types.ReadEVENT_SpawnMob(): (number, CFrame, number) - -- Read BLOCK: 33 bytes - local BLOCK_START = Read(33) - local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0) - local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8) - local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12) - local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16) - local Position = Vector3.new(X, Y, Z) - local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20) - local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24) - local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28) - local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ) - local Value3 = buffer.readu8(RecieveBuffer, BLOCK_START + 32) - return Value1, Value2, Value3 -end - -function Types.WriteEVENT_SpawnMob(Value1: number, Value2: CFrame, Value3: number): () - -- Allocate BLOCK: 34 bytes - local BLOCK_START = Allocate(34) - buffer.writeu8(SendBuffer, BLOCK_START + 0, 0) - buffer.writef64(SendBuffer, BLOCK_START + 1, Value1) - local Vector = Value2.Position - buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X) - buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y) - buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z) - local rX, rY, rZ = Value2:ToOrientation() - buffer.writef32(SendBuffer, BLOCK_START + 21, rX) - buffer.writef32(SendBuffer, BLOCK_START + 25, rY) - buffer.writef32(SendBuffer, BLOCK_START + 29, rZ) - buffer.writeu8(SendBuffer, BLOCK_START + 33, Value3) -end - -local function StepReplication() - if SendCursor <= 0 then - return - end - - local Buffer = buffer.create(SendCursor) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - Reliable:FireServer(Buffer, SendInstances) - - SendSize = 64 - SendCursor = 0 - SendOffset = 0 - SendBuffer = buffer.create(64) - table.clear(SendInstances) -end - -local Elapsed = 0 -RunService.Heartbeat:Connect(function(DeltaTime: number) - Elapsed += DeltaTime - if Elapsed >= (1 / 61) then - Elapsed -= (1 / 61) - StepReplication() - end -end) - -Reliable.OnClientEvent:Connect(function(Buffer: buffer, Instances: { Instance }) - RecieveCursor = 0 - RecieveBuffer = Buffer - RecieveInstances = Instances - RecieveInstanceCursor = 0 - local Size = buffer.len(RecieveBuffer) - while RecieveCursor < Size do - -- Read BLOCK: 1 bytes - local BLOCK_START = Read(1) - local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0) - if Index == 0 then - Push(Queue.Reliable[0], table.pack(Types.ReadEVENT_SpawnMob())) - end - end -end) - -Unreliable.OnClientEvent:Connect(function(Buffer: buffer, Instances: { Instance }) - RecieveCursor = 0 - RecieveBuffer = Buffer - RecieveInstances = Instances - RecieveInstanceCursor = 0 - local Size = buffer.len(RecieveBuffer) - while RecieveCursor < Size do - -- Read BLOCK: 1 bytes - local BLOCK_START = Read(1) - local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0) - if Index == 0 then - Push(Queue.Unreliable[0], table.pack(Types.ReadEVENT_UpdateTransform())) - end - end -end) - -return { - StepReplication = StepReplication, - - UpdateTransform = { - Iter = function(): () -> (number, number, CFrame) - local index = 0 - local queue = Queue.Unreliable[0] - return function(): (number, number, CFrame) - index += 1 - local arguments = Pop(queue) - if arguments ~= nil then - return index, unpack(arguments, 1, arguments.n) - end - return - end - end, - Next = function(): () -> (number, number, CFrame) - local index = 0 - local queue = Queue.Unreliable[0] - return function(): (number, number, CFrame) - index += 1 - local arguments = Pop(queue) - if arguments ~= nil then - return index, unpack(arguments, 1, arguments.n) - end - return - end - end, - }, - SpawnMob = { - Iter = function(): () -> (number, number, CFrame, number) - local index = 0 - local queue = Queue.Reliable[0] - return function(): (number, number, CFrame, number) - index += 1 - local arguments = Pop(queue) - if arguments ~= nil then - return index, unpack(arguments, 1, arguments.n) - end - return - end - end, - Next = function(): () -> (number, number, CFrame, number) - local index = 0 - local queue = Queue.Reliable[0] - return function(): (number, number, CFrame, number) - index += 1 - local arguments = Pop(queue) - if arguments ~= nil then - return index, unpack(arguments, 1, arguments.n) - end - return - end - end, - }, -} diff --git a/demo/net/server.luau b/demo/net/server.luau deleted file mode 100644 index 8a8755c..0000000 --- a/demo/net/server.luau +++ /dev/null @@ -1,372 +0,0 @@ ---!strict ---!native ---!optimize 2 ---!nolint LocalShadow ---#selene: allow(shadowing) --- File generated by Blink v0.14.1 (https://github.com/1Axen/Blink) --- This file is not meant to be edited - -local Players = game:GetService("Players") -local ReplicatedStorage = game:GetService("ReplicatedStorage") -local RunService = game:GetService("RunService") - -if not RunService:IsServer() then - error("Server network module can only be required from the server.") -end - -local Reliable: RemoteEvent = ReplicatedStorage:FindFirstChild("BLINK_RELIABLE_REMOTE") :: RemoteEvent -if not Reliable then - local RemoteEvent = Instance.new("RemoteEvent") - RemoteEvent.Name = "BLINK_RELIABLE_REMOTE" - RemoteEvent.Parent = ReplicatedStorage - Reliable = RemoteEvent -end - -local Unreliable: UnreliableRemoteEvent = - ReplicatedStorage:FindFirstChild("BLINK_UNRELIABLE_REMOTE") :: UnreliableRemoteEvent -if not Unreliable then - local UnreliableRemoteEvent = Instance.new("UnreliableRemoteEvent") - UnreliableRemoteEvent.Name = "BLINK_UNRELIABLE_REMOTE" - UnreliableRemoteEvent.Parent = ReplicatedStorage - Unreliable = UnreliableRemoteEvent -end - -local Invocations = 0 - -local SendSize = 64 -local SendOffset = 0 -local SendCursor = 0 -local SendBuffer = buffer.create(64) -local SendInstances = {} - -local RecieveCursor = 0 -local RecieveBuffer = buffer.create(64) - -local RecieveInstances = {} -local RecieveInstanceCursor = 0 - -type Entry = { - value: any, - next: Entry?, -} - -type Queue = { - head: Entry?, - tail: Entry?, -} - -type BufferSave = { - Size: number, - Cursor: number, - Buffer: buffer, - Instances: { Instance }, -} - -local function Read(Bytes: number) - local Offset = RecieveCursor - RecieveCursor += Bytes - return Offset -end - -local function Save(): BufferSave - return { - Size = SendSize, - Cursor = SendCursor, - Buffer = SendBuffer, - Instances = SendInstances, - } -end - -local function Load(Save: BufferSave?) - if Save then - SendSize = Save.Size - SendCursor = Save.Cursor - SendOffset = Save.Cursor - SendBuffer = Save.Buffer - SendInstances = Save.Instances - return - end - - SendSize = 64 - SendCursor = 0 - SendOffset = 0 - SendBuffer = buffer.create(64) - SendInstances = {} -end - -local function Invoke() - if Invocations == 255 then - Invocations = 0 - end - - local Invocation = Invocations - Invocations += 1 - return Invocation -end - -local function Allocate(Bytes: number) - local InUse = (SendCursor + Bytes) - if InUse > SendSize then - --> Avoid resizing the buffer for every write - while InUse > SendSize do - SendSize *= 1.5 - end - - local Buffer = buffer.create(SendSize) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - SendBuffer = Buffer - end - - SendOffset = SendCursor - SendCursor += Bytes - - return SendOffset -end - -local function CreateQueue(): Queue - return { - head = nil, - tail = nil, - } -end - -local function Pop(queue: Queue): any - local head = queue.head - if head == nil then - return - end - - queue.head = head.next - return head.value -end - -local function Push(queue: Queue, value: any) - local entry: Entry = { - value = value, - next = nil, - } - - if queue.tail ~= nil then - queue.tail.next = entry - end - - queue.tail = entry - - if queue.head == nil then - queue.head = entry - end -end - -local Types = {} -local Calls = table.create(256) - -local Events: any = { - Reliable = table.create(256), - Unreliable = table.create(256), -} - -local Queue: any = { - Reliable = table.create(256), - Unreliable = table.create(256), -} - -function Types.ReadEVENT_UpdateTransform(): (number, CFrame) - -- Read BLOCK: 32 bytes - local BLOCK_START = Read(32) - local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0) - local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8) - local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12) - local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16) - local Position = Vector3.new(X, Y, Z) - local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20) - local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24) - local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28) - local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ) - return Value1, Value2 -end - -function Types.WriteEVENT_UpdateTransform(Value1: number, Value2: CFrame): () - -- Allocate BLOCK: 33 bytes - local BLOCK_START = Allocate(33) - buffer.writeu8(SendBuffer, BLOCK_START + 0, 0) - buffer.writef64(SendBuffer, BLOCK_START + 1, Value1) - local Vector = Value2.Position - buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X) - buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y) - buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z) - local rX, rY, rZ = Value2:ToOrientation() - buffer.writef32(SendBuffer, BLOCK_START + 21, rX) - buffer.writef32(SendBuffer, BLOCK_START + 25, rY) - buffer.writef32(SendBuffer, BLOCK_START + 29, rZ) -end - -function Types.ReadEVENT_SpawnMob(): (number, CFrame, number) - -- Read BLOCK: 33 bytes - local BLOCK_START = Read(33) - local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0) - local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8) - local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12) - local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16) - local Position = Vector3.new(X, Y, Z) - local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20) - local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24) - local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28) - local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ) - local Value3 = buffer.readu8(RecieveBuffer, BLOCK_START + 32) - return Value1, Value2, Value3 -end - -function Types.WriteEVENT_SpawnMob(Value1: number, Value2: CFrame, Value3: number): () - -- Allocate BLOCK: 34 bytes - local BLOCK_START = Allocate(34) - buffer.writeu8(SendBuffer, BLOCK_START + 0, 0) - buffer.writef64(SendBuffer, BLOCK_START + 1, Value1) - local Vector = Value2.Position - buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X) - buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y) - buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z) - local rX, rY, rZ = Value2:ToOrientation() - buffer.writef32(SendBuffer, BLOCK_START + 21, rX) - buffer.writef32(SendBuffer, BLOCK_START + 25, rY) - buffer.writef32(SendBuffer, BLOCK_START + 29, rZ) - buffer.writeu8(SendBuffer, BLOCK_START + 33, Value3) -end - -local PlayersMap: { [Player]: BufferSave } = {} - -Players.PlayerRemoving:Connect(function(Player) - PlayersMap[Player] = nil -end) - -local function StepReplication() - for Player, Send in PlayersMap do - if Send.Cursor <= 0 then - continue - end - - local Buffer = buffer.create(Send.Cursor) - buffer.copy(Buffer, 0, Send.Buffer, 0, Send.Cursor) - Reliable:FireClient(Player, Buffer, Send.Instances) - - Send.Size = 64 - Send.Cursor = 0 - Send.Buffer = buffer.create(64) - table.clear(Send.Instances) - end -end - -RunService.Heartbeat:Connect(StepReplication) - -Reliable.OnServerEvent:Connect(function(Player: Player, Buffer: buffer, Instances: { Instance }) - RecieveCursor = 0 - RecieveBuffer = Buffer - RecieveInstances = Instances - RecieveInstanceCursor = 0 - local Size = buffer.len(RecieveBuffer) - while RecieveCursor < Size do - -- Read BLOCK: 1 bytes - local BLOCK_START = Read(1) - local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0) - end -end) - -Unreliable.OnServerEvent:Connect(function(Player: Player, Buffer: buffer, Instances: { Instance }) - RecieveCursor = 0 - RecieveBuffer = Buffer - RecieveInstances = Instances - RecieveInstanceCursor = 0 - local Size = buffer.len(RecieveBuffer) - while RecieveCursor < Size do - -- Read BLOCK: 1 bytes - local BLOCK_START = Read(1) - local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0) - end -end) - -return { - StepReplication = StepReplication, - - UpdateTransform = { - Fire = function(Player: Player, Value1: number, Value2: CFrame): () - Load() - Types.WriteEVENT_UpdateTransform(Value1, Value2) - local Buffer = buffer.create(SendCursor) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - Unreliable:FireClient(Player, Buffer, SendInstances) - end, - FireAll = function(Value1: number, Value2: CFrame): () - Load() - Types.WriteEVENT_UpdateTransform(Value1, Value2) - local Buffer = buffer.create(SendCursor) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - Unreliable:FireAllClients(Buffer, SendInstances) - end, - FireList = function(List: { Player }, Value1: number, Value2: CFrame): () - Load() - Types.WriteEVENT_UpdateTransform(Value1, Value2) - local Buffer = buffer.create(SendCursor) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - for _, Player in List do - Unreliable:FireClient(Player, Buffer, SendInstances) - end - end, - FireExcept = function(Except: Player, Value1: number, Value2: CFrame): () - Load() - Types.WriteEVENT_UpdateTransform(Value1, Value2) - local Buffer = buffer.create(SendCursor) - buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor) - for _, Player in Players:GetPlayers() do - if Player == Except then - continue - end - Unreliable:FireClient(Player, Buffer, SendInstances) - end - end, - }, - SpawnMob = { - Fire = function(Player: Player, Value1: number, Value2: CFrame, Value3: number): () - Load(PlayersMap[Player]) - Types.WriteEVENT_SpawnMob(Value1, Value2, Value3) - PlayersMap[Player] = Save() - end, - FireAll = function(Value1: number, Value2: CFrame, Value3: number): () - Load() - Types.WriteEVENT_SpawnMob(Value1, Value2, Value3) - local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances - for _, Player in Players:GetPlayers() do - Load(PlayersMap[Player]) - local Position = Allocate(Size) - buffer.copy(SendBuffer, Position, Buffer, 0, Size) - table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances) - PlayersMap[Player] = Save() - end - end, - FireList = function(List: { Player }, Value1: number, Value2: CFrame, Value3: number): () - Load() - Types.WriteEVENT_SpawnMob(Value1, Value2, Value3) - local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances - for _, Player in List do - Load(PlayersMap[Player]) - local Position = Allocate(Size) - buffer.copy(SendBuffer, Position, Buffer, 0, Size) - table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances) - PlayersMap[Player] = Save() - end - end, - FireExcept = function(Except: Player, Value1: number, Value2: CFrame, Value3: number): () - Load() - Types.WriteEVENT_SpawnMob(Value1, Value2, Value3) - local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances - for _, Player in Players:GetPlayers() do - if Player == Except then - continue - end - Load(PlayersMap[Player]) - local Position = Allocate(Size) - buffer.copy(SendBuffer, Position, Buffer, 0, Size) - table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances) - PlayersMap[Player] = Save() - end - end, - }, -} diff --git a/test/addons/observers.luau b/test/addons/observers.luau index b255625..537ce60 100644 --- a/test/addons/observers.luau +++ b/test/addons/observers.luau @@ -4,10 +4,24 @@ local test = testkit.test() local CASE, TEST, FINISH, CHECK = test.CASE, test.TEST, test.FINISH, test.CHECK local observers_add = require("@addons/observers") - TEST("addons/observers", function() local world = observers_add(jecs.world()) + do CASE "Should work even if set after the component has been used" + local A = world:component() + + world:set(world:entity(), A, 1) + local ran = false + world:added(A, function() + ran = true + end) + + local entity = world:entity() + world:set(entity, A, 2) + + CHECK(ran) + end + do CASE "Should not override hook" local A = world:component() @@ -17,12 +31,12 @@ TEST("addons/observers", function() end world:set(A, jecs.OnAdd, counter) - world:set(world:entity(), A, true) - CHECK(count == 1) world:added(A, counter) world:set(world:entity(), A, true) + CHECK(count == 2) + world:set(world:entity(), A, true) - CHECK(count == 3) + CHECK(count == 4) end do CASE "Ensure ordering between signals and observers" @@ -33,10 +47,8 @@ TEST("addons/observers", function() local function counter() count += 1 end - world:observer({ - callback = counter, - query = world:query(A, B), - }) + + world:observer(world:query(A, B), counter) world:added(A, counter) world:added(A, counter) @@ -56,10 +68,8 @@ TEST("addons/observers", function() local function counter() count += 1 end - world:observer({ - query = world:query(A), - callback = counter - }) + + world:observer(world:query(A), counter) local e = world:entity() world:set(e, A, true) @@ -79,10 +89,7 @@ TEST("addons/observers", function() count += 1 end - world:monitor({ - query = world:query(A), - callback = counter - }) + world:monitor(world:query(A), counter) local e = world:entity() world:set(e, A, true)