mirror of
https://github.com/Keyslam-Group/Concord.git
synced 2025-09-02 04:13:58 -04:00
Fixed entity lifetime problems
This commit is contained in:
parent
a8bc92a951
commit
38d461f8d6
4 changed files with 110 additions and 129 deletions
95
main.lua
95
main.lua
|
@ -20,77 +20,72 @@ local Entity = Concord.entity
|
||||||
local World = Concord.world
|
local World = Concord.world
|
||||||
local Worlds = Concord.worlds
|
local Worlds = Concord.worlds
|
||||||
|
|
||||||
Concord.loadComponents("test/components")
|
|
||||||
|
|
||||||
|
local test_comp_1 = Component(function(e, a)
|
||||||
|
e.a = a
|
||||||
|
end)
|
||||||
|
|
||||||
local test_comp_2 = Component(function(e, a)
|
local test_comp_2 = Component(function(e, a)
|
||||||
e.a = a
|
e.a = a
|
||||||
end)
|
end)
|
||||||
Components.register("test_comp_2", test_comp_2)
|
|
||||||
|
|
||||||
|
|
||||||
local test_comp_3 = Component()
|
local test_comp_3 = Component()
|
||||||
Components.register("test_comp_3", test_comp_3)
|
|
||||||
|
|
||||||
|
local test_system_1 = System({test_comp_1})
|
||||||
|
|
||||||
local test_system = System({Components.test_comp_1})
|
function test_system_1:init()
|
||||||
Systems.register("test_system", test_system)
|
self.pool.onEntityAdded = function()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function onEntityAdded(pool, e) -- luacheck: ignore
|
print("Added to test_system 1")
|
||||||
print("Added")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function onEntityRemoved(pool, e) -- luacheck: ignore
|
|
||||||
print("Removed")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_system:init()
|
|
||||||
self.pool.onEntityAdded = onEntityAdded
|
|
||||||
self.pool.onEntityRemoved = onEntityRemoved
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_system:update(dt) -- luacheck: ignore
|
|
||||||
--[=[
|
|
||||||
for _, v in ipairs(self.pool) do
|
|
||||||
print(v)
|
|
||||||
end
|
end
|
||||||
]=]
|
self.pool.onEntityRemoved = function() print("Removed from test_system 1") end
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_system:update2(dt) -- luacheck: ignore
|
function test_system_1:test()
|
||||||
--print(#self.pool)
|
print("Running test_system_1 with: " ..#self.pool)
|
||||||
|
|
||||||
|
for _, e in ipairs(self.pool) do
|
||||||
|
local newE = Entity()
|
||||||
|
newE:give(test_comp_1)
|
||||||
|
self:getWorld():addEntity(newE)
|
||||||
|
|
||||||
|
e:give(test_comp_2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local test_system_2 = System({test_comp_2})
|
||||||
|
|
||||||
|
function test_system_2:init()
|
||||||
|
self.pool.onEntityAdded = function(pool, e) print("Added to test_system 2") e:remove(test_comp_1) end
|
||||||
|
self.pool.onEntityRemoved = function() print("Removed from test_system 2") end
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_system_2:test()
|
||||||
|
print("Running test_system_2 with: " ..#self.pool)
|
||||||
|
|
||||||
|
for _, e in ipairs(self.pool) do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local world = World()
|
local world = World()
|
||||||
Worlds.register("testWorld", world)
|
|
||||||
|
|
||||||
local entity = Entity()
|
local entity = Entity()
|
||||||
entity
|
entity:give(test_comp_1, 100, 100)
|
||||||
:give(Components.test_comp_1, 100, 100)
|
|
||||||
:remove(Components.test_comp_1)
|
|
||||||
:give(Components.test_comp_1, 200, 100)
|
|
||||||
:give(Components.test_comp_3, 200, 100)
|
|
||||||
|
|
||||||
Worlds.testWorld:addEntity(entity)
|
world:addEntity(entity)
|
||||||
|
|
||||||
world:addSystem(Systems.test_system, "update")
|
world:addSystem(test_system_1, "test")
|
||||||
world:addSystem(Systems.test_system, "update", "update2")
|
world:addSystem(test_system_2, "test")
|
||||||
|
|
||||||
function love.update(dt)
|
print("Iteration: 1")
|
||||||
world:flush()
|
world:emit("test")
|
||||||
|
|
||||||
world:emit("update", dt)
|
print("Iteration: 2")
|
||||||
end
|
world:emit("test")
|
||||||
|
|
||||||
function love.keypressed(key)
|
print("Iteration: 3")
|
||||||
if key == "q" then
|
world:emit("test")
|
||||||
entity:remove(Components.test_comp_1)
|
|
||||||
end
|
|
||||||
if key == "w" then
|
|
||||||
entity:give(Components.test_comp_1)
|
|
||||||
end
|
|
||||||
if key == "e" then
|
|
||||||
world:removeEntity(entity)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -13,10 +13,6 @@ function Entity.new()
|
||||||
local e = setmetatable({
|
local e = setmetatable({
|
||||||
__world = nil,
|
__world = nil,
|
||||||
|
|
||||||
__addedComponents = {},
|
|
||||||
__removedComponents = {},
|
|
||||||
__operations = {},
|
|
||||||
|
|
||||||
__components = {},
|
__components = {},
|
||||||
|
|
||||||
__isDirty = false,
|
__isDirty = false,
|
||||||
|
@ -29,32 +25,22 @@ function Entity.new()
|
||||||
return e
|
return e
|
||||||
end
|
end
|
||||||
|
|
||||||
local function giveOperation(e, component)
|
|
||||||
local baseComponent = component.__baseComponent
|
|
||||||
|
|
||||||
e[baseComponent] = component
|
|
||||||
e.__components[baseComponent] = component
|
|
||||||
end
|
|
||||||
|
|
||||||
local function removeOperation(e, baseComponent)
|
|
||||||
e[baseComponent] = nil
|
|
||||||
e.__components[baseComponent] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function give(e, baseComponent, ...)
|
local function give(e, baseComponent, ...)
|
||||||
local component = baseComponent:__initialize(...)
|
local component = baseComponent:__initialize(...)
|
||||||
|
|
||||||
e.__addedComponents[#e.__addedComponents + 1] = component
|
e[baseComponent] = component
|
||||||
e.__operations[#e.__operations + 1] = giveOperation
|
e.__components[baseComponent] = component
|
||||||
|
|
||||||
e.__isDirty = true
|
e.__isDirty = true
|
||||||
|
e:__dirty()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove(e, baseComponent)
|
local function remove(e, baseComponent)
|
||||||
e.__removedComponents[#e.__removedComponents + 1] = baseComponent
|
e[baseComponent] = nil
|
||||||
e.__operations[#e.__operations + 1] = removeOperation
|
e.__components[baseComponent] = nil
|
||||||
|
|
||||||
e.__isDirty = true
|
e.__isDirty = true
|
||||||
|
e:__dirty()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Gives an Entity a component with values.
|
--- Gives an Entity a component with values.
|
||||||
|
@ -108,36 +94,22 @@ function Entity:assemble(assemblage, ...)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:__flush()
|
|
||||||
local addi, removei = 1, 1
|
|
||||||
|
|
||||||
for i = 1, #self.__operations do
|
|
||||||
local operation = self.__operations[i]
|
|
||||||
|
|
||||||
if (operation == giveOperation) then
|
|
||||||
operation(self, self.__addedComponents[addi])
|
|
||||||
self.__addedComponents[addi] = nil
|
|
||||||
addi = addi + 1
|
|
||||||
elseif (operation == removeOperation) then
|
|
||||||
operation(self, self.__removedComponents[removei])
|
|
||||||
self.__removedComponents[removei] = nil
|
|
||||||
removei = removei + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
self.__operations[i] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Destroys the Entity.
|
--- Destroys the Entity.
|
||||||
-- @return self
|
-- @return self
|
||||||
function Entity:destroy()
|
function Entity:destroy()
|
||||||
if self.world then
|
if self.__world then
|
||||||
self.world:removeEntity(self)
|
self.__world:removeEntity(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Entity:__dirty()
|
||||||
|
if self.__world then
|
||||||
|
self.__world:__dirtyEntity(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Gets a Component from the Entity.
|
--- Gets a Component from the Entity.
|
||||||
-- @param component The Component to get
|
-- @param component The Component to get
|
||||||
-- @return The Bag from the Component
|
-- @return The Bag from the Component
|
||||||
|
|
|
@ -17,8 +17,9 @@ function World.new()
|
||||||
|
|
||||||
events = {},
|
events = {},
|
||||||
|
|
||||||
__added = {},
|
__added = List(), __backAdded = List(),
|
||||||
__removed = {},
|
__removed = List(), __backRemoved = List(),
|
||||||
|
__dirty = List(), __backDirty = List(),
|
||||||
|
|
||||||
__systemLookup = {},
|
__systemLookup = {},
|
||||||
|
|
||||||
|
@ -36,14 +37,16 @@ function World:addEntity(e)
|
||||||
error("bad argument #1 to 'World:addEntity' (Entity expected, got "..type(e)..")", 2)
|
error("bad argument #1 to 'World:addEntity' (Entity expected, got "..type(e)..")", 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.world then
|
if e.__world then
|
||||||
error("bad argument #1 to 'World:addEntity' (Entity was already added to a world)", 2)
|
error("bad argument #1 to 'World:addEntity' (Entity was already added to a world)", 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.world = self
|
e.__world = self
|
||||||
e.__wasAdded = true
|
e.__wasAdded = true
|
||||||
|
|
||||||
self.entities:add(e)
|
self.__added:add(e)
|
||||||
|
|
||||||
|
--self.entities:add(e)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -58,50 +61,65 @@ function World:removeEntity(e)
|
||||||
|
|
||||||
e.__wasRemoved = true
|
e.__wasRemoved = true
|
||||||
|
|
||||||
|
self.__removed:add(e)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function World:__dirtyEntity(e)
|
||||||
|
if not self.__dirty:has(e) then
|
||||||
|
self.__dirty:add(e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @return self
|
-- @return self
|
||||||
function World:flush()
|
function World:__flush()
|
||||||
|
-- Switch buffers
|
||||||
|
self.__added, self.__backAdded = self.__backAdded, self.__added
|
||||||
|
self.__removed, self.__backRemoved = self.__backRemoved, self.__removed
|
||||||
|
self.__dirty, self.__backDirty = self.__backDirty, self.__dirty
|
||||||
|
|
||||||
local e
|
local e
|
||||||
for i = 1, self.entities.size do
|
|
||||||
e = self.entities:get(i)
|
|
||||||
|
|
||||||
if e.__isDirty then
|
-- Added
|
||||||
e:__flush()
|
for i = 1, self.__backAdded.size do
|
||||||
|
e = self.__backAdded:get(i)
|
||||||
|
|
||||||
if (not e.__wasAdded) then -- The __wasAdded check below will handle this instead
|
self.entities:add(e)
|
||||||
for j = 1, self.systems.size do
|
|
||||||
self.systems:get(j):__evaluate(e)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
e.__isDirty = false
|
for j = 1, self.systems.size do
|
||||||
|
self.systems:get(j):__evaluate(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.__wasAdded then
|
self:onEntityAdded(e)
|
||||||
e.__wasAdded = false
|
end
|
||||||
|
self.__backAdded:clear()
|
||||||
|
|
||||||
for j = 1, self.systems.size do
|
-- Removed
|
||||||
self.systems:get(j):__evaluate(e)
|
for i = 1, self.__backRemoved.size do
|
||||||
end
|
e = self.__backRemoved:get(i)
|
||||||
|
|
||||||
self:onEntityAdded(e)
|
e.__world = nil
|
||||||
|
self.entities:remove(e)
|
||||||
|
|
||||||
|
for j = 1, self.systems.size do
|
||||||
|
self.systems:get(j):__remove(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.__wasRemoved then
|
self:onEntityRemoved(e)
|
||||||
e.world = nil
|
end
|
||||||
self.entities:remove(e)
|
self.__backRemoved:clear()
|
||||||
|
|
||||||
for j = 1, self.systems.size do
|
-- Dirty
|
||||||
self.systems:get(j):__remove(e)
|
for i = 1, self.__backDirty.size do
|
||||||
end
|
e = self.__backDirty:get(i)
|
||||||
|
|
||||||
e.__wasRemoved = false
|
for j = 1, self.systems.size do
|
||||||
|
self.systems:get(j):__evaluate(e)
|
||||||
self:onEntityRemoved(e)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self.__backDirty:clear()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -246,6 +264,8 @@ function World:emit(callbackName, ...)
|
||||||
local listener = listeners[i]
|
local listener = listeners[i]
|
||||||
|
|
||||||
if listener.enabled then
|
if listener.enabled then
|
||||||
|
self:__flush()
|
||||||
|
|
||||||
listener.system[listener.callback](listener.system, ...)
|
listener.system[listener.callback](listener.system, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
local Component = require("src").component
|
|
||||||
|
|
||||||
return Component(function(e, x, y)
|
|
||||||
e.x = x
|
|
||||||
e.y = y
|
|
||||||
end)
|
|
Loading…
Add table
Add a link
Reference in a new issue