mirror of
https://github.com/Ukendio/jecs.git
synced 2025-10-14 09:49:18 +00:00
Update replication demo
Some checks failed
Some checks failed
This commit is contained in:
parent
698854d11b
commit
57e653fa78
2 changed files with 117 additions and 85 deletions
|
@ -12,7 +12,7 @@ local function ecs_ensure_entity(world: jecs.World, id: jecs.Entity)
|
||||||
|
|
||||||
local ser_id = id
|
local ser_id = id
|
||||||
local deser_id = client_ids[ser_id]
|
local deser_id = client_ids[ser_id]
|
||||||
if deser_id then
|
if deser_id then
|
||||||
if deser_id == 0 then
|
if deser_id == 0 then
|
||||||
local new_id = world:entity()
|
local new_id = world:entity()
|
||||||
client_ids[ser_id] = new_id
|
client_ids[ser_id] = new_id
|
||||||
|
@ -40,11 +40,18 @@ end
|
||||||
|
|
||||||
-- local rel_render = `e{jecs.ECS_ID(rel)}v{jecs.ECS_GENERATION(rel)}`
|
-- local rel_render = `e{jecs.ECS_ID(rel)}v{jecs.ECS_GENERATION(rel)}`
|
||||||
-- local tgt_render = `e{jecs.ECS_ID(tgt)}v{jecs.ECS_GENERATION(tgt)}`
|
-- local tgt_render = `e{jecs.ECS_ID(tgt)}v{jecs.ECS_GENERATION(tgt)}`
|
||||||
local function ecs_deser_pairs(world, token)
|
-- local function ecs_deser_pairs_str(world, token)
|
||||||
local tokens = string.split(token, ",")
|
-- local tokens = string.split(token, ",")
|
||||||
local rel = tonumber(tokens[1])
|
-- local rel = tonumber(tokens[1]) :: jecs.Entity
|
||||||
local tgt = tonumber(tokens[2])
|
-- local tgt = tonumber(tokens[2]) :: jecs.Entity
|
||||||
|
|
||||||
|
-- rel = ecs_ensure_entity(world, rel)
|
||||||
|
-- tgt = ecs_ensure_entity(world, tgt)
|
||||||
|
|
||||||
|
-- return jecs.pair(rel, tgt)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
local function ecs_deser_pairs(world, rel, tgt)
|
||||||
rel = ecs_ensure_entity(world, rel)
|
rel = ecs_ensure_entity(world, rel)
|
||||||
tgt = ecs_ensure_entity(world, tgt)
|
tgt = ecs_ensure_entity(world, tgt)
|
||||||
|
|
||||||
|
@ -53,18 +60,24 @@ end
|
||||||
|
|
||||||
local snapshots = collect(remotes.replication.OnClientEvent)
|
local snapshots = collect(remotes.replication.OnClientEvent)
|
||||||
|
|
||||||
return function(world: types.World)
|
return function(world: jecs.World)
|
||||||
for entity in world:each(components.Destroy) do
|
for entity in world:each(components.Destroy) do
|
||||||
client_ids[entity] = nil
|
client_ids[entity] = nil
|
||||||
end
|
end
|
||||||
for snapshot in snapshots do
|
for snapshot in snapshots do
|
||||||
for ser_id, map in snapshot do
|
for ser_id, map in snapshot do
|
||||||
local id = tonumber(ser_id)
|
local id = (tonumber(ser_id) :: any) :: jecs.Entity
|
||||||
if not id then
|
if jecs.IS_PAIR(id) and map.pair then
|
||||||
id = ecs_deser_pairs(world, ser_id)
|
id = ecs_deser_pairs(world, map.relation, map.target)
|
||||||
else
|
elseif id then
|
||||||
id = ecs_ensure_entity(world, id)
|
id = ecs_ensure_entity(world, id)
|
||||||
end
|
end
|
||||||
|
-- if not id then
|
||||||
|
-- id = ecs_deser_pairs_str(world, ser_id)
|
||||||
|
-- else
|
||||||
|
-- id = ecs_ensure_entity(world, id)
|
||||||
|
-- end
|
||||||
|
local members = world:get(id, components.NetworkedMembers)
|
||||||
|
|
||||||
local set = map.set
|
local set = map.set
|
||||||
if set then
|
if set then
|
||||||
|
@ -74,11 +87,23 @@ return function(world: types.World)
|
||||||
world:add(entity, id)
|
world:add(entity, id)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local t = os.clock()
|
local values = map.values :: { any }
|
||||||
local values = map.values
|
|
||||||
for i, entity in set do
|
for i, entity in set do
|
||||||
entity = ecs_ensure_entity(world, entity)
|
entity = ecs_ensure_entity(world, entity)
|
||||||
world:set(entity, id, values[i])
|
local value = values[i]
|
||||||
|
if members then
|
||||||
|
for _, member in members do
|
||||||
|
local data = value[member] :: {jecs.Entity} | jecs.Entity -- targets
|
||||||
|
if typeof(data) == "table" then
|
||||||
|
for pos, tgt in data :: { jecs.Entity } do
|
||||||
|
data[pos] = ecs_ensure_entity(world, tgt)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
value[member] = ecs_ensure_entity(world, data :: any)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
world:set(entity, id, value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,24 +8,16 @@ local jecs = require(ReplicatedStorage.ecs)
|
||||||
local collect = require(ReplicatedStorage.collect)
|
local collect = require(ReplicatedStorage.collect)
|
||||||
local ty = require(ReplicatedStorage.types)
|
local ty = require(ReplicatedStorage.types)
|
||||||
|
|
||||||
return function(world: ty.World)
|
return function(world: jecs.World)
|
||||||
|
|
||||||
--- integration test
|
|
||||||
|
|
||||||
-- for _ = 1, 10 do
|
|
||||||
-- local e = world:entity()
|
|
||||||
-- world:set(e, ct.TestA, true)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
local storages = {} :: { [jecs.Entity]: {[jecs.Entity]: any }}
|
local storages = {} :: { [jecs.Entity]: {[jecs.Entity]: any }}
|
||||||
local networked_components = {}
|
local networked_components = {}
|
||||||
local networked_pairs = {}
|
local networked_pairs = {}
|
||||||
|
|
||||||
for component in world:each(ct.Networked) do
|
for component in world:each(ct.Networked) do
|
||||||
local name = assert(world:get(component, jecs.Name), "Invalid component")
|
local name = world:get(component, jecs.Name)
|
||||||
|
assert(name)
|
||||||
if components[name] == nil then
|
if components[name] == nil then
|
||||||
error("Invalid component:"..name)
|
error("Invalid component:"..name)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
storages[component] = {}
|
storages[component] = {}
|
||||||
|
@ -34,7 +26,8 @@ return function(world: ty.World)
|
||||||
end
|
end
|
||||||
|
|
||||||
for relation in world:each(ct.NetworkedPair) do
|
for relation in world:each(ct.NetworkedPair) do
|
||||||
local name = world:get(relation, jecs.Name) :: string
|
local name = world:get(relation, jecs.Name)
|
||||||
|
assert(name)
|
||||||
if not components[name] then
|
if not components[name] then
|
||||||
error("Invalid component")
|
error("Invalid component")
|
||||||
end
|
end
|
||||||
|
@ -43,7 +36,7 @@ return function(world: ty.World)
|
||||||
|
|
||||||
for _, component in networked_components do
|
for _, component in networked_components do
|
||||||
local name = world:get(component, jecs.Name)
|
local name = world:get(component, jecs.Name)
|
||||||
if not components[name] then
|
if not name or not components[name] then
|
||||||
-- error("Invalid component")
|
-- error("Invalid component")
|
||||||
error(`Networked Component (%id{component}%name{name})`)
|
error(`Networked Component (%id{component}%name{name})`)
|
||||||
end
|
end
|
||||||
|
@ -68,51 +61,51 @@ return function(world: ty.World)
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, relation in networked_pairs do
|
for _, relation in networked_pairs do
|
||||||
world:added(relation, function(entity, id, value)
|
world:added(relation, function(entity: jecs.Entity, id: jecs.Id, value)
|
||||||
local is_tag = jecs.is_tag(world, id)
|
local is_tag = jecs.is_tag(world, id)
|
||||||
local storage = storages[id]
|
local storage = storages[id]
|
||||||
if not storage then
|
if not storage then
|
||||||
storage = {}
|
storage = {}
|
||||||
storages[id] = storage
|
storages[id] = storage
|
||||||
end
|
end
|
||||||
if is_tag then
|
if is_tag then
|
||||||
storage[entity] = true
|
storage[entity] = true
|
||||||
else
|
else
|
||||||
|
storage[entity] = value
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
world:changed(relation, function(entity: jecs.Id, id: jecs.Id, value)
|
||||||
|
local is_tag = jecs.is_tag(world, id)
|
||||||
|
if is_tag then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local storage = storages[id]
|
||||||
|
if not storage then
|
||||||
|
storage = {}
|
||||||
|
storages[id] = storage
|
||||||
|
end
|
||||||
|
|
||||||
storage[entity] = value
|
storage[entity] = value
|
||||||
end
|
end)
|
||||||
end)
|
|
||||||
|
|
||||||
world:changed(relation, function(entity, id, value)
|
world:removed(relation, function(entity, id)
|
||||||
local is_tag = jecs.is_tag(world, id)
|
local storage = storages[id]
|
||||||
if is_tag then
|
if not storage then
|
||||||
return
|
storage = {}
|
||||||
end
|
storages[id] = storage
|
||||||
|
end
|
||||||
|
|
||||||
local storage = storages[id]
|
storage[entity] = "jecs.Remove"
|
||||||
if not storage then
|
end)
|
||||||
storage = {}
|
|
||||||
storages[id] = storage
|
|
||||||
end
|
|
||||||
|
|
||||||
storage[entity] = value
|
|
||||||
end)
|
|
||||||
|
|
||||||
world:removed(relation, function(entity, id)
|
|
||||||
local storage = storages[id]
|
|
||||||
if not storage then
|
|
||||||
storage = {}
|
|
||||||
storages[id] = storage
|
|
||||||
end
|
|
||||||
|
|
||||||
storage[entity] = "jecs.Remove"
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- local requested_snapshots = collect(remotes.request_snapshot.OnServerEvent)
|
-- local requested_snapshots = collect(remotes.request_snapshot.OnServerEvent)
|
||||||
local players_added = collect(Players.PlayerAdded)
|
local players_added = collect(Players.PlayerAdded)
|
||||||
|
|
||||||
return function()
|
return function(_, dt: number)
|
||||||
local snapshot_lazy: ty.Snapshot
|
local snapshot_lazy: ty.snapshot
|
||||||
local set_ids_lazy: { jecs.Entity }
|
local set_ids_lazy: { jecs.Entity }
|
||||||
|
|
||||||
-- In the future maybe it should be requested by the player instead when they
|
-- In the future maybe it should be requested by the player instead when they
|
||||||
|
@ -132,9 +125,7 @@ return function(world: ty.World)
|
||||||
local entities = archetype.entities
|
local entities = archetype.entities
|
||||||
local entities_len = #entities
|
local entities_len = #entities
|
||||||
table.move(entities, 1, entities_len, set_n + 1, set_ids_lazy)
|
table.move(entities, 1, entities_len, set_n + 1, set_ids_lazy)
|
||||||
if is_tag then
|
if not is_tag then
|
||||||
set_values = table.create(entities_len, true)
|
|
||||||
else
|
|
||||||
local column = archetype.columns_map[component]
|
local column = archetype.columns_map[component]
|
||||||
table.move(column, 1, entities_len, set_n + 1, set_values)
|
table.move(column, 1, entities_len, set_n + 1, set_values)
|
||||||
end
|
end
|
||||||
|
@ -144,25 +135,31 @@ return function(world: ty.World)
|
||||||
|
|
||||||
local set = table.move(set_ids_lazy, 1, set_n, 1, {})
|
local set = table.move(set_ids_lazy, 1, set_n, 1, {})
|
||||||
|
|
||||||
local ser_id: string = nil :: any
|
local map = {
|
||||||
|
|
||||||
if jecs.IS_PAIR(component) then
|
|
||||||
ser_id = `{jecs.pair_first(world, component)},{jecs.pair_first(world, component)}`
|
|
||||||
else
|
|
||||||
ser_id = tostring(component)
|
|
||||||
end
|
|
||||||
|
|
||||||
snapshot_lazy[ser_id] = {
|
|
||||||
set = if set_n > 0 then set else nil,
|
set = if set_n > 0 then set else nil,
|
||||||
values = if set_n > 0 then set_values else nil,
|
values = if set_n > 0 then set_values else nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if jecs.IS_PAIR(component) then
|
||||||
|
map.relation = jecs.pair_first(world, component)
|
||||||
|
map.target = jecs.pair_second(world, component)
|
||||||
|
map.pair = true
|
||||||
|
end
|
||||||
|
snapshot_lazy[tostring(component)] = map
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
remotes.replication:FireClient(player, snapshot_lazy)
|
remotes.replication:FireClient(player, snapshot_lazy)
|
||||||
end
|
end
|
||||||
|
|
||||||
local snapshot = {} :: ty.Snapshot
|
-- accumulator += dt
|
||||||
|
|
||||||
|
-- Purposely sending less diffs of the world because doing it at 60hz
|
||||||
|
-- gets expensive. But this requires interpolated elements in the scene.
|
||||||
|
-- if accumulator > 1/60 then
|
||||||
|
-- accumulator = 0
|
||||||
|
|
||||||
|
local snapshot = {} :: ty.snapshot
|
||||||
|
|
||||||
local set_ids = {}
|
local set_ids = {}
|
||||||
local removed_ids = {}
|
local removed_ids = {}
|
||||||
|
@ -193,23 +190,33 @@ return function(world: ty.World)
|
||||||
if dirty then
|
if dirty then
|
||||||
local removed = table.move(removed_ids, 1, removed_n, 1, {}) :: { jecs.Entity }
|
local removed = table.move(removed_ids, 1, removed_n, 1, {}) :: { jecs.Entity }
|
||||||
local set = table.move(set_ids, 1, set_n, 1, {}) :: { jecs.Entity }
|
local set = table.move(set_ids, 1, set_n, 1, {}) :: { jecs.Entity }
|
||||||
local ser_id: string = nil :: any
|
|
||||||
|
|
||||||
if jecs.IS_PAIR(component) then
|
-- local ser_id: string = nil :: any
|
||||||
ser_id = `{jecs.pair_first(world, component)},{jecs.pair_second(world, component)}`
|
|
||||||
else
|
|
||||||
ser_id = tostring(component)
|
|
||||||
end
|
|
||||||
|
|
||||||
snapshot[ser_id] = {
|
-- if jecs.IS_PAIR(component) then
|
||||||
|
-- ser_id = `{jecs.pair_first(world, component)},{jecs.pair_second(world, component)}`
|
||||||
|
-- else
|
||||||
|
-- ser_id = tostring(component)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
local map = {
|
||||||
set = if set_n > 0 then set else nil,
|
set = if set_n > 0 then set else nil,
|
||||||
values = if set_n > 0 then set_values else nil,
|
values = if set_n > 0 then set_values else nil,
|
||||||
removed = if removed_n > 0 then removed else nil
|
removed = if removed_n > 0 then removed else nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if jecs.IS_PAIR(component) then
|
||||||
|
map.relation = jecs.pair_first(world, component)
|
||||||
|
map.target = jecs.pair_second(world, component)
|
||||||
|
map.pair = true
|
||||||
|
end
|
||||||
|
|
||||||
|
snapshot[tostring(component)] = map
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if next(snapshot) ~= nil then
|
if next(snapshot) ~= nil then
|
||||||
remotes.replication:FireAllClients(snapshot)
|
remotes.replication:FireAllClients(snapshot)
|
||||||
|
-- print(snapshot)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue