diff --git a/demo/.config/blink b/demo/.config/blink new file mode 100644 index 0000000..3675cf7 --- /dev/null +++ b/demo/.config/blink @@ -0,0 +1,18 @@ +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 new file mode 100644 index 0000000..29b0f8b --- /dev/null +++ b/demo/net/client.luau @@ -0,0 +1,337 @@ +--!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 + }, + +} \ No newline at end of file diff --git a/demo/net/server.luau b/demo/net/server.luau new file mode 100644 index 0000000..a31208b --- /dev/null +++ b/demo/net/server.luau @@ -0,0 +1,374 @@ +--!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, + }, + +} \ No newline at end of file diff --git a/demo/src/ReplicatedStorage/std/components.luau b/demo/src/ReplicatedStorage/std/components.luau index 695b9ff..70b7425 100644 --- a/demo/src/ReplicatedStorage/std/components.luau +++ b/demo/src/ReplicatedStorage/std/components.luau @@ -7,7 +7,7 @@ local components = { Model = world:component() :: jecs.Entity, Player = world:component(), Target = world:component(), - Transform = world:component(), + Transform = world:component() :: jecs.Entity, Velocity = world:component(), } diff --git a/demo/src/ReplicatedStorage/std/registry.luau b/demo/src/ReplicatedStorage/std/registry.luau new file mode 100644 index 0000000..04b55cc --- /dev/null +++ b/demo/src/ReplicatedStorage/std/registry.luau @@ -0,0 +1,31 @@ +local reserved = 0 + +local function reserve() + reserved += 1 + return reserved +end + +-- If you don't like passing around a world singleton +-- and you need to register component IDs, just register them. +-- I dont use this because I like adding component traits +--[[ + local components = { + Model = registry.reserve(), + Transform = registry.reserve(), + } + + local world = registry.register(jecs.World.new()) + local e = world:entity() + world:set(e, components.Transform, CFrame) +]] +local function register(world) + for _ = 1, reserved do + world:component() + end + return world +end + +return { + reserve = reserve, + register = register, +} diff --git a/demo/src/ServerScriptService/systems/mobsMove.luau b/demo/src/ServerScriptService/systems/mobsMove.luau index f47139a..6cf10f0 100644 --- a/demo/src/ServerScriptService/systems/mobsMove.luau +++ b/demo/src/ServerScriptService/systems/mobsMove.luau @@ -19,7 +19,7 @@ print("client Model", cts.Model) local function mobsMove(dt: number) local players = world:query(Character):with(Player) - for mob, cf, v in world:query(Transform, Velocity):with(Mob) do + for mob, cf, v in world:query(Transform, Velocity):with(Mob):iter() do local p = cf.Position local target diff --git a/demo/src/ServerScriptService/systems/players.luau b/demo/src/ServerScriptService/systems/players.luau index ef0b594..8a68573 100644 --- a/demo/src/ServerScriptService/systems/players.luau +++ b/demo/src/ServerScriptService/systems/players.luau @@ -16,6 +16,10 @@ local conn = {} local function players() for _, player in playersAdded do + std.world:set( + std.world:entity(), + std.world:entity()) + local e = ref(player.UserId):set(Player, player) local characterAdd = player.CharacterAdded conn[e.id()] = characterAdd:Connect(function(rig) diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/main.client.luau b/demo/src/StarterPlayer/StarterPlayerScripts/main.client.luau new file mode 100644 index 0000000..1d7b555 --- /dev/null +++ b/demo/src/StarterPlayer/StarterPlayerScripts/main.client.luau @@ -0,0 +1,6 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local std = require(ReplicatedStorage.std) + +print(script.Parent:WaitForChild("systems"):GetChildren()) +local loop = std.Scheduler(unpack(script.Parent:WaitForChild("systems"):GetChildren())) +game:GetService("RunService").Heartbeat:Connect(loop) diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/systems/move.luau b/demo/src/StarterPlayer/StarterPlayerScripts/systems/move.luau new file mode 100644 index 0000000..a3270b9 --- /dev/null +++ b/demo/src/StarterPlayer/StarterPlayerScripts/systems/move.luau @@ -0,0 +1,17 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local std = require(ReplicatedStorage.std) +local world = std.world + +local cts = std.components + +local Model = cts.Model +local Transform = cts.Transform + +local function move(dt: number) + for _, cf, model in world:query(Transform, Model) do + model.PrimaryPart.CFrame = cf + end +end + +return move diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncMobs.luau b/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncMobs.luau new file mode 100644 index 0000000..0c6e89f --- /dev/null +++ b/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncMobs.luau @@ -0,0 +1,28 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local blink = require(ReplicatedStorage.net) +local std = require(ReplicatedStorage.std) +local ref = std.ref +local world = std.world +local cts = std.components + +local function syncMobs() + for _, id, cf, vel in blink.SpawnMob.Iter() do + local part = Instance.new("Part") + part.Size = Vector3.one * 5 + part.BrickColor = BrickColor.Red() + part.Anchored = true + local model = Instance.new("Model") + model.PrimaryPart = part + part.Parent = model + model.Parent = workspace + + ref("server-"..id) + :set(cts.Transform, cf) + :set(cts.Velocity, vel) + :set(cts.Model, model) + :add(cts.Mob) + end + +end + +return syncMobs diff --git a/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncTransforms.luau b/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncTransforms.luau new file mode 100644 index 0000000..6fa3064 --- /dev/null +++ b/demo/src/StarterPlayer/StarterPlayerScripts/systems/syncTransforms.luau @@ -0,0 +1,16 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local blink = require(ReplicatedStorage.net) +local std = require(ReplicatedStorage.std) +local ref = std.ref +local world = std.world + +local cts = std.components + +local function syncTransforms() + for _, id, cf in blink.UpdateTransform.Iter() do + ref("server-"..id) + :set(cts.Transform, cf) + end +end + +return syncTransforms