sorcery  itemclass.lua at [93f944b581]

File itemclass.lua artifact bee797c513 part of check-in 93f944b581


-- in theory, minetest groups are supposed to allow us to
-- give consistent, cross-mod classes to items, and easily
-- detect whether items fit into a particular class. unfortunately,
-- they don't really work for this purpose because we often
-- need to attach additional data to items that are outside
-- of our control (and the default mod's authors are amazingly
-- lax in grouping items; for instance, diamonds and mese
-- crystals aren't even part of a 'gem' or 'crystal' group!)
-- this module allows us to consistently classify items, and
-- easily maintain complex hierarchies of subclasses. whether
-- an item belongs to a class can be determined by checking
-- its groups, consulting compat tables, calling a custom
-- predicate function (possibly to check for a _sorcery
-- defprop), or recursing through a list of subclasses.
-- this also means that matters of identity are all controlled
-- from a central location.
sorcery.itemclass = {
	classes = {
		-- gem/crystalline and metal/metallic differentiate
		-- between crafting materials (i.e. gems or ingots
		-- themselves) and items crafted from those materials.
		-- the former includes only crafting materials, the
		-- latter includes both.
		gem = {
			compat = 'gems';
			groups = { 'gem', 'crystal'; };
			predicate = function(name)
				if minetest.get_item_group(name, 'sorcery_gem') ~= 0 
				or minetest.get_item_group(name, 'sorcery_shard') ~= 0 then
					return minetest.registered_items[name]._sorcery.material;
				end
			end;
		};
		crystalline = {
			subclass = {'gem'};
			predicate = function(name)
				local mat = sorcery.matreg.lookup[name]
				if mat and mat.gem then return mat end
			end;
		};
		grindable = {
			compat = 'grindables';
			subclass = {'metallic'};
			predicate = function(name)
				local def = minetest.registered_items[name]._sorcery
				if not def then return nil end
				def = def.material
				if def and def.grindvalue then
					return def end
			end;
		};
		metal = {
			predicate = function(name)
				-- metallookup is a table of 'primary' metal
				-- items, like ingots, fragments, and powders
				return sorcery.data.metallookup[name]
			end;
		};
		metallic = {
			subclass = {'metal'};
			predicate = function(name)
				-- matreg is a registry binding crafted items,
				-- like armors and tools, to the material they
				-- are made out of
				local mat = sorcery.matreg.lookup[name]
				if mat and mat.metal then return mat end
			end;
		};
	};
	get = function(name,class)
		local c = sorcery.itemclass.classes[class]
		local o
		if not c then return false end

		if c.predicate then 
			o = c.predicate(name)
			if o then return o end
		end

		if c.compat then
			o = sorcery.data.compat[c.compat][name]
			if o then return o end
		end

		if c.subclass then
			for _,s in pairs(c.subclass) do
				o = sorcery.itemclass.get(name,s)
				if o then return o end
			end
		end

		if c.groups then
			for _,g in pairs(c.groups) do
				o = minetest.get_item_group(name,g) 
				if o > 0 then return { kind = o } end
			end
			o = nil
		end

		return false
	end;
}