diff options
Diffstat (limited to 'honey/ecs.lua')
| -rw-r--r-- | honey/ecs.lua | 108 | 
1 files changed, 107 insertions, 1 deletions
diff --git a/honey/ecs.lua b/honey/ecs.lua index b4def84..62acce0 100644 --- a/honey/ecs.lua +++ b/honey/ecs.lua @@ -5,28 +5,41 @@ setfenv(1, module)  --===== Components =====-- +-- Components provide a kind-of-type-safe way of storing values, since they are +-- guaranteed to have a specific set of keys and no other values in them. They also serialize +-- nicely for storage. +  Component = {}  function Component.newFactory(name, params, serialize) +	-- create the metatable for this component type  	local metatable = {} -	metatable.__tostring = serialize or Component.serialize +	metatable.__tostring = serialize or Component.serialize -- nice serialization  	metatable.__newindex = function(tbl, index, value)  		if params[index] ~= nil then  			tbl[index] = value  		else +			-- throw an error if we try to set a key that is not in the valid set  			error(string.format("%q is not a valid key for a component of type %q", index, name))  		end  	end + +	-- the factory function for creating components  	return function(tbl)  		local tbl = tbl or {}  		local self = { __type=name } + +		-- ensure that all keys are present  		for k, v in pairs(params) do  			self[k] = v  		end  		setmetatable(self, metatable) + +		-- set the keys from the factory call  		for k, v in pairs(tbl) do  			self[k] = v  		end +  		return self  	end  end @@ -45,4 +58,97 @@ function Component.serialize(self)  	return str  end + +--===== EntityDb =====-- + +EntityDb = {} +EntityDb.__index = EntityDb + + +function EntityDb.new(_) +	local self = { +		entities = {}, +		components = {}, +	} +	setmetatable(self, EntityDb) +	return self +end +setmetatable(EntityDb, {__call=EntityDb.new}) + + +function EntityDb.checkIsValid(self, id) +	if not self.entities[id] then +		error(string.format("invalid entity id: 0x%x", id)) +	end +end + + +local guid = (function() +	local id = 0 +	return function() id=id+1 return id end +end)() +function EntityDb.createEntity(self) +	local id = guid() +	self.entities[id] = true +	return id +end + + +function EntityDb.addComponent(self, id, name, value) +	self:checkIsValid(id) +	if not self.components[name] then +		self.components[name] = { count=0 } +	end + +	local component = self.components[name] +	component[id] = value +	component.count = component.count + 1 +end + + +local function shallowCopy(tbl) +	local copy = {} +	for k, v in pairs(tbl) do copy[k] = v end +	return copy +end + + +function EntityDb.queryComponent(self, name) +	local query = shallowCopy(self.components[name]) +	query.count = nil +	return query +end + + +function EntityDb.queryEntity(self, id) +	self:checkIsValid(id) +	local query = {} +	for name, component in pairs(self.components) do +		query[name] = component[id] +	end +	return query +end + + +function EntityDb.removeComponent(self, id, name) +	self:checkIsValid(id) +	local component = self.components[name] +	if component[id] ~= nil then +		component[id] = nil +		component.count = component.count - 1 +		if component.count == 0 then +			self.components[name] = nil +		end +	end +end + + +function EntityDb.deleteEntity(self, id) +	self:checkIsValid(id) +	for name in pairs(self.components) do +		self:removeComponent(id, name) +	end +	self.entities[id] = nil +end +  return module  | 
