From c1c79c2eee3951797e0b6f14f1978530ee6320ef Mon Sep 17 00:00:00 2001 From: Mark Marks Date: Fri, 30 Aug 2024 16:00:33 +0200 Subject: [PATCH] chore: Fix the spawner type for sapphire-jecs, release @ 0.1.1 --- crates/sapphire-jecs/README.md | 2 + crates/sapphire-jecs/lib/init.luau | 5 +- crates/sapphire-jecs/lib/spawner_type.luau | 394 ++++++++++++++++++ crates/sapphire-jecs/wally.toml | 2 +- .../controllers/systems/replication.luau | 4 + .../controllers/systems/update_position.luau | 17 + dev/jecs/client/main.client.luau | 16 - dev/jecs/server/main.server.luau | 16 - dev/jecs/server/services/service.luau | 3 - dev/jecs/server/services/spawn_parts.luau | 29 ++ .../server/services/systems/replication.luau | 7 + .../services/systems/update_position.luau | 17 + 12 files changed, 473 insertions(+), 39 deletions(-) create mode 100644 crates/sapphire-jecs/lib/spawner_type.luau create mode 100644 dev/jecs/client/controllers/systems/update_position.luau delete mode 100644 dev/jecs/server/services/service.luau create mode 100644 dev/jecs/server/services/spawn_parts.luau create mode 100644 dev/jecs/server/services/systems/update_position.luau diff --git a/crates/sapphire-jecs/README.md b/crates/sapphire-jecs/README.md index cd636e1..ee80754 100644 --- a/crates/sapphire-jecs/README.md +++ b/crates/sapphire-jecs/README.md @@ -1,6 +1,8 @@ # sapphire-jecs A lightweight scheduler + niceties (replication, etc.) for [Ukendio/jecs](https://github.com/Ukendio/jecs) for [Mark-Marks/sapphire](https://github.com/Mark-Marks/sapphire) +[And here's a small usage example](/dev/jecs/) + > [!CAUTION] > Replicators set the `OnAdd`, `OnSet` and `OnRemove` hooks for tracked components.\ > This means that any defined of said hooks are overwritten. It is possible to make them coexist, though. For example: diff --git a/crates/sapphire-jecs/lib/init.luau b/crates/sapphire-jecs/lib/init.luau index 14a8b32..c23a93e 100644 --- a/crates/sapphire-jecs/lib/init.luau +++ b/crates/sapphire-jecs/lib/init.luau @@ -23,6 +23,7 @@ local world = require(script.world) local handle = require(script.handle) export type handle = handle.handle local ref = require(script.ref) +local spawner_type = require(script.spawner_type) local SapphireJecs = {} --- @readonly @@ -191,9 +192,7 @@ end --- ``` --- @param ... T... -- Components to use. --- @return spawner -function SapphireJecs.create_spawner(...: T...): spawner - return create_spawner(...) -end +SapphireJecs.create_spawner = (create_spawner :: any) :: spawner_type.create_spawner --- A replicator keeps track of all entities with the passed components and their values - --- whenever a component is changed (add, change, remove) and the replicator listens to it, it's also changed within the contained raw data.\ diff --git a/crates/sapphire-jecs/lib/spawner_type.luau b/crates/sapphire-jecs/lib/spawner_type.luau new file mode 100644 index 0000000..101371b --- /dev/null +++ b/crates/sapphire-jecs/lib/spawner_type.luau @@ -0,0 +1,394 @@ +--!strict +type entity = number & { + __T: T, +} + +type id = entity | number + +local handle = require(script.Parent.handle) +type handle = handle.handle + +export type spawner = { + --- Creates an entity with the given components. + --- @param ... T... + --- @return entity + spawn: (T...) -> entity, + --- Creates an entity with the given components and returns a handle to it. + --- @param ... T... + --- @return handle + spawn_with_handle: (T...) -> handle, +} + +-- Very beautiful type incoming! +-- Sadly this has to be done, components are of different types than their values (`entity` vs `T`) +export type create_spawner = + ((id) -> spawner) + & ((id, id) -> spawner) + & ((id, id, id) -> spawner) + & ((id, id, id, id) -> spawner) + & ((id, id, id, id, id) -> spawner) + & ((id, id, id, id, id, id) -> spawner) + & ((id, id, id, id, id, id, id) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id

, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id + ) -> spawner) + +return "spawner_type" diff --git a/crates/sapphire-jecs/wally.toml b/crates/sapphire-jecs/wally.toml index 89a8ae7..34f059b 100644 --- a/crates/sapphire-jecs/wally.toml +++ b/crates/sapphire-jecs/wally.toml @@ -1,6 +1,6 @@ [package] name = "mark-marks/sapphire-jecs" -version = "0.1.0" +version = "0.1.1" registry = "https://github.com/UpliftGames/wally-index" realm = "shared" license = "MIT" diff --git a/dev/jecs/client/controllers/systems/replication.luau b/dev/jecs/client/controllers/systems/replication.luau index d9198a1..db448b0 100644 --- a/dev/jecs/client/controllers/systems/replication.luau +++ b/dev/jecs/client/controllers/systems/replication.luau @@ -9,6 +9,10 @@ local replication_event = events.data_replication.jecs_world local replication = {} +function replication.start() + events.data_replication.loaded.send() +end + function replication.system() return function(delta_time: number) for _, difference in replication_event.poll() do diff --git a/dev/jecs/client/controllers/systems/update_position.luau b/dev/jecs/client/controllers/systems/update_position.luau new file mode 100644 index 0000000..a4759b1 --- /dev/null +++ b/dev/jecs/client/controllers/systems/update_position.luau @@ -0,0 +1,17 @@ +--!strict +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local components = require(ReplicatedStorage.components) +local jecs = require(ReplicatedStorage.Packages.sapphire_jecs) + +local update_position = {} + +function update_position.system(world: jecs.world) + return function(delta_time: number) + for entity, part, position in world:query(components.part, components.position):iter() do + part.Position = position + end + end +end + +return update_position diff --git a/dev/jecs/client/main.client.luau b/dev/jecs/client/main.client.luau index 8445ecc..7e1573d 100644 --- a/dev/jecs/client/main.client.luau +++ b/dev/jecs/client/main.client.luau @@ -10,20 +10,4 @@ local sapphire_net = require(ReplicatedStorage.Packages.sapphire_net) local controllers = StarterPlayerScripts.controllers local systems = controllers.systems -sapphire.signals.on_extension_registered:Connect(function(extension) - print(`Registered extension {extension.identifier}`) -end) - -sapphire.signals.on_singleton_registered:Connect(function(singleton) - print(`Registered singleton {singleton.identifier}`) -end) - -sapphire.signals.on_singleton_initialized:Connect(function(singleton) - print(`Initialized singleton {singleton.identifier}`) -end) - -sapphire.signals.on_singleton_started:Connect(function(singleton) - print(`Started singleton {singleton.identifier}`) -end) - sapphire:use(sapphire_net):use(sapphire_jecs):register_singletons(controllers):register_singletons(systems):start() diff --git a/dev/jecs/server/main.server.luau b/dev/jecs/server/main.server.luau index 234b9c1..b507c45 100644 --- a/dev/jecs/server/main.server.luau +++ b/dev/jecs/server/main.server.luau @@ -9,20 +9,4 @@ local sapphire_net = require(ReplicatedStorage.Packages.sapphire_net) local services = ServerScriptService.services local systems = services.systems -sapphire.signals.on_extension_registered:Connect(function(extension) - print(`Registered extension {extension.identifier}`) -end) - -sapphire.signals.on_singleton_registered:Connect(function(singleton) - print(`Registered singleton {singleton.identifier}`) -end) - -sapphire.signals.on_singleton_initialized:Connect(function(singleton) - print(`Initialized singleton {singleton.identifier}`) -end) - -sapphire.signals.on_singleton_started:Connect(function(singleton) - print(`Started singleton {singleton.identifier}`) -end) - sapphire:use(sapphire_net):use(sapphire_jecs):register_singletons(services):register_singletons(systems):start() diff --git a/dev/jecs/server/services/service.luau b/dev/jecs/server/services/service.luau deleted file mode 100644 index e5c539d..0000000 --- a/dev/jecs/server/services/service.luau +++ /dev/null @@ -1,3 +0,0 @@ -local service = {} - -return service diff --git a/dev/jecs/server/services/spawn_parts.luau b/dev/jecs/server/services/spawn_parts.luau new file mode 100644 index 0000000..2d2df47 --- /dev/null +++ b/dev/jecs/server/services/spawn_parts.luau @@ -0,0 +1,29 @@ +--!strict +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local jecs = require(ReplicatedStorage.Packages.sapphire_jecs) +local components = require(ReplicatedStorage.components) + +local spawn_parts = {} + +function spawn_parts.start() + local spawner = jecs.create_spawner(components.part, components.position, components.velocity) + + local max = 2147483647 + + for _ = 1, 1_000 do + local rand = Random.new(math.random(max)) + + local part = Instance.new("Part") + part.Anchored = true + + local random_velocity = + Vector3.new(rand:NextNumber(-2.5, 2.5), rand:NextNumber(-2.5, 2.5), rand:NextNumber(-2.5, 2.5)) + local handle = spawner.spawn_with_handle(part, Vector3.zero, Vector3.zero) + handle:set(components.velocity, random_velocity) + + part.Parent = workspace + end +end + +return spawn_parts diff --git a/dev/jecs/server/services/systems/replication.luau b/dev/jecs/server/services/systems/replication.luau index 6b1cd0f..12abd94 100644 --- a/dev/jecs/server/services/systems/replication.luau +++ b/dev/jecs/server/services/systems/replication.luau @@ -9,6 +9,13 @@ local replication_event = events.data_replication.jecs_world local replication = {} +function replication.start() + events.data_replication.loaded.listen(function(_, player) + assert(player, "where player") + replication_event.send_to(player, replicator.get_full_data()) + end) +end + function replication.system() return function(delta_time: number) local difference = replicator.calculate_difference() diff --git a/dev/jecs/server/services/systems/update_position.luau b/dev/jecs/server/services/systems/update_position.luau new file mode 100644 index 0000000..3952d7b --- /dev/null +++ b/dev/jecs/server/services/systems/update_position.luau @@ -0,0 +1,17 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local components = require(ReplicatedStorage.components) +local jecs = require(ReplicatedStorage.Packages.sapphire_jecs) + +local update_position = {} + +function update_position.system(world: jecs.world) + return function(delta_time: number) + for entity, position, velocity in world:query(components.position, components.velocity):iter() do + local new_position = position + (velocity * delta_time) + world:set(entity, components.position, new_position) + end + end +end + +return update_position

+ ) -> spawner) + & (( + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id, + id