/
Entity.lua
225 lines (190 loc) · 5.75 KB
/
Entity.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
-- Getting folder that contains our src
local folderOfThisFile = (...):match("(.-)[^%/%.]+$")
local HooECS = require(folderOfThisFile .. 'namespace')
local Entity = HooECS.class("Entity")
function Entity:initialize(parent, name, active)
self.components = {}
self.eventManager = nil
self.active = active or true
self.alive = false
if parent then
self:setParent(parent)
else
parent = nil
end
self.name = name
self.children = {}
end
-- Sets the entities component of this type to the given component.
-- An entity can only have one Component of each type.
function Entity:add(component)
local name = component.class.name
if self.components[name] then
HooECS.debug("Entity: Trying to add Component '" .. name .. "', but it's already existing. Please use Entity:set to overwrite a component in an entity.")
else
self.components[name] = component
if self.eventManager then
self.eventManager:fireEvent(HooECS.ComponentAdded(self, name))
end
end
if component.addedToEntity then component:addedToEntity(self) end
return self
end
function Entity:set(component)
local name = component.class.name
if self.components[name] == nil then
self:add(component)
else
if self.components[name].addedToEntity ~= component.addedToEntity and component.addedToEntity then
component:addedToEntity(self)
end
self.components[name] = component
end
end
function Entity:addMultiple(componentList)
for _, component in pairs(componentList) do
self:add(component)
end
end
function Entity:setMultiple(componentList)
for _, component in pairs(componentList) do
self:set(component)
end
end
-- Removes a component from the entity.
function Entity:remove(name)
if self.components[name] then
if self.components[name].removedFromEntity then
self.components[name]:removedFromEntity(self)
end
self.components[name] = nil
else
HooECS.debug("Entity: Trying to remove unexisting component " .. name .. " from Entity. Please fix this")
end
if self.eventManager then
self.eventManager:fireEvent(HooECS.ComponentRemoved(self, name))
end
return self
end
function Entity:setParent(parent)
if self.parent then self.parent.children[self.id] = nil end
self.parent = parent
self:registerAsChild()
end
function Entity:getParent()
return self.parent
end
function Entity:getChildren()
if next(self.children) then
return self.children
end
end
function Entity:registerAsChild()
if self.id then self.parent.children[self.id] = self end
end
function Entity:get(name)
return self.components[name]
end
function Entity:has(name)
return not not self.components[name]
end
function Entity:getComponents()
return self.components
end
function Entity:getRootEntity()
local entity = self
while entity.getParent do
local parent = entity:getParent()
if parent.engine then
return parent
else
entity = parent
end
end
end
function Entity:getEngine()
return self:getRootEntity().engine
end
function Entity:activate()
if not self.active then
self.active = true
self.eventManager:fireEvent(HooECS.EntityActivated(self))
end
end
function Entity:deactivate()
if self.active then
self.active = false
self.eventManager:fireEvent(HooECS.EntityDeactivated(self))
end
end
function Entity:isActive()
return self.active
end
function Entity:setUpdate(newUpdateFunction)
if type(newUpdateFunction) == "function" then
self.update = newUpdateFunction
local engine = self:getEngine()
if engine then
engine:addUpdateEntity(self)
end
elseif type(newUpdateFunction) == "nil" then
self.update = nil
local engine = self:getEngine()
if engine then
engine:removeUpdateEntity(self)
end
end
end
-- Returns an entity with all components deeply copied.
function Entity:copy(componentList)
function deepCopy(obj, seen)
-- Handle non-tables and previously-seen tables.
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
-- New table; mark it as seen an copy recursively.
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
local k, v = next(obj)
while k do
res[deepCopy(k, s)] = deepCopy(v, s)
k, v = next(obj, k)
end
return res
end
local newEntity = Entity()
newEntity.components = deepCopy(self.components)
if componentList then
if type(componentList) == "table" then
newEntity:setMultiple(componentList)
else
HooECS.debug("Entity:copy() componentList is not a table!")
end
end
return newEntity
end
-- Returns an entity with references to the components.
-- Modifying a component of the origin entity will result in the returned entity being modified too.
function Entity:shallowCopy(componentList)
function shallowCopy(obj)
if type(obj) ~= 'table' then return obj end
local res = setmetatable({}, getmetatable(obj))
local k, v = next(obj)
while k do
res[k] = v
k, v = next(obj, k)
end
return res
end
local newEntity = Entity()
newEntity.components = shallowCopy(self.components)
if componentList then
if type(componentList) == "table" then
newEntity:setMultiple(componentList)
else
HooECS.debug("Entity:shallowCopy() componentList is not a table!")
end
end
return newEntity
end
return Entity