· 7 years ago · Sep 14, 2018, 03:48 PM
1local utils = require("utils")
2local ECS = {}
3ECS.__index = ECS
4
5
6function ECS.new(class)
7 local self = setmetatable({}, class)
8 self._entityID = 0
9 self._entityData = {}
10 self._classData = {}
11 self._systemData = {}
12 self._systemData.load = {}
13 self._systemData.update = {}
14 self._systemData.draw = {}
15 return self
16end
17
18function ECS:newEntity() -- Create a new blank entity
19 local entity = self._entityID -- Assign the entity an id
20 self._entityID = entity+1 -- Increment the next entity id for this ecs
21 return entity -- Return the entity
22end
23
24function ECS:addSystem(systemPath) -- Add a new system to the ECS
25 local system = require(systemPath) -- Import the system
26 for key, value in pairs(system) do -- Loop through all of the systems
27 self._systemData[key][systemPath] = value -- Add the system to the systemData
28 end
29end
30
31function ECS:removeSystem(systemPath) -- Remove a system from the ecs
32 for key,_ in pairs(self._systemData) do -- Loop through all of the system types
33 self._systemData[key][systemPath] = nil -- Delete (set to nil) the system
34 end
35end
36
37function ECS:set(entity, class, data) -- Set the data for a given entity
38 if not (entity and class) then return nil end -- Check if entity and class are not nil
39 utils.ensure(self._classData, class)[entity] = data -- Set the data for the class table
40 utils.ensure(self._entityData,entity)[class] = data -- Set the data for the entity table
41 return data -- Just return the data so we would know everything went well
42end
43
44function ECS:get(entity, class) -- Get a class of a given entity
45 if not (entity and class) then return nil end -- Check if entity and class are not nil
46
47 local components = self._entityData[entity] -- Get the component table for that entity
48 if not components then return nil end -- Check that the components table exists
49
50 return components[class] -- Return the component with that class
51end
52
53function ECS:removeEntity(entity) -- Remove an entity
54 if not entity then return nil end -- Check if entity isin't nil
55 local components = self._entityData[entity] -- Get the list of components that the entity has
56 for class in pairs(components or {}) do -- Loop threw all of the components that the entity has
57 self._classData[class][entity] = nil -- Delete (set to nil) all of the data for that component and entity
58 end
59 self._entityData[entity] = nil -- Delere (set to nil) the table of components for that entity
60 return components -- return the entities components if you want to use them for something
61end
62
63function ECS:entitiesWithAll(main_class,...) -- Iterate through all of the entities with those components
64 extra_classes = {...}
65 return coroutine.wrap(function ()
66 if not main_class then return nil end
67
68 for entity, component in pairs(self._classData[main_class] or {}) do
69 local yieldComponents = { component }
70 local components = self._entityData[entity]
71
72 for i, class in ipairs(extra_classes) do
73 local component = components[ class ]
74 if not component then goto nextEntity end
75 yieldComponents[i + 1] = component
76 end
77
78 coroutine.yield(entity, unpack(yieldComponents))
79 ::nextEntity::
80 end
81 end)
82end
83
84function ECS:runSystems(systemType,...) -- Run all of the system load functions
85 params = {...} -- Get all of the passed arguments
86 for _,system in pairs(self._systemData[systemType] or {}) do -- Loop through all of the systems
87 for _,subSystem in pairs(system or {}) do -- Loop through all of the sub systems
88 subSystem(self,unpack(params)) -- Run the system
89 end
90 end
91end
92
93
94
95return ECS