sorcery  Diff

Differences From Artifact [e643a56c3c]:

To Artifact [aae72d93b8]:


     1      1   -- by use of the enchanter, it is possible to reveal a random
     2      2   -- recipe and enscribe it on a sheet of paper. these sheets of
     3      3   -- paper can then bound together into books, combining like
     4      4   -- recipes
     5      5   
     6      6   sorcery.cookbook = {}
            7  +local log = sorcery.logger('cookbook')
            8  +
     7      9   local constants = {
     8     10   	-- do not show recipes for items in these groups
     9     11   	exclude_groups = {
    10     12   	};
    11     13   	exclude_names = {
    12     14   		'stairs';
    13     15   		'slab';
................................................................................
    51     53   	return {}
    52     54   end
    53     55   local modofname = function(id)
    54     56   	local sep = string.find(id,':')
    55     57   	if sep == nil then return nil end -- uh oh
    56     58   	return string.sub(id, 1, sep - 1)
    57     59   end
           60  +local item_restrict_eval = function(name, restrict)
           61  +	for _,n in pairs(constants.exclude_names) do
           62  +		if string.find(name,n) ~= nil then
           63  +			return false
           64  +		end
           65  +	end
           66  +	for _,g in pairs(constants.exclude_groups) do
           67  +		if minetest.get_item_group(name, g) > 0 then
           68  +			return false
           69  +		end
           70  +	end
           71  +
           72  +	local props = minetest.registered_items[name]._sorcery
           73  +	local module = modofname(name)
           74  +
           75  +	return not (excluded
           76  +		or sorcery.lib.tbl.has(constants.blacklist_mods,module)
           77  +		or (props and props.recipe and props.recipe.secret)
           78  +		or (restrict and (
           79  +			(restrict.pred and restrict.pred {
           80  +				mod = module, item = name, props = props
           81  +			} ~= true)
           82  +		 or (restrict.mod   and module ~= restrict.mod)
           83  +		 or (restrict.group and (minetest.get_item_group(name, restrict.group) == 0))
           84  +	))) 
           85  +end
           86  +
    58     87   local pick_builtin = function(kind) return function(restrict)
    59     88   	-- ow ow ow ow ow ow ow
    60     89   	local names = {}
    61     90   	for k in pairs(minetest.registered_items) do
    62     91   		local rec = minetest.get_craft_recipe(k)
    63     92   		if rec.items ~= nil and (rec.method == kind or (rec.method == 'shapeless' and kind == 'normal')) then -- is this last bit necessary?
    64         -			local excluded = false
    65         -			for _,n in pairs(constants.exclude_names) do
    66         -				if string.find(k,n) ~= nil then
    67         -					excluded = true break end
    68         -			end
    69         -			if not excluded then for _,g in pairs(constants.exclude_groups) do
    70         -				if minetest.get_item_group(k, g) > 0 then
    71         -					excluded = true break end
    72         -			end end
    73         -			local props = minetest.registered_items[k]._sorcery
    74         -			local module = modofname(k)
    75         -			if not (excluded
    76         -				or sorcery.lib.tbl.has(constants.blacklist_mods,module)
    77         -				or (props and props.recipe and props.recipe.secret)
    78         -				or (restrict and (
    79         -				    (restrict.mod   and module ~= restrict.mod)
    80         -				 or (restrict.group and (minetest.get_item_group(k, restrict.group) == 0))
    81         -			))) then names[#names + 1] = k end
           93  +			if item_restrict_eval(k, restrict) then names[#names + 1] = k end
    82     94   		end
    83     95   	end
    84     96   	return names[math.random(#names)]
    85     97   end end
    86     98   local find_builtin = function(method,kind)
    87     99   	return function(out)
    88    100   		local rec = {}
................................................................................
   219    231   		chance = 4;
   220    232   		slots = {
   221    233   			{0,0};
   222    234   			{0,1};
   223    235   		};
   224    236   		pick = function(restrict)
   225    237   			-- TODO make sure affinity restrictions match
   226         -			return sorcery.register.infusions.db[math.random(#sorcery.register.infusions.db)].output
          238  +			if restrict then
          239  +				local t = {}
          240  +				for _, i in pairs(sorcery.register.infusions.db) do
          241  +					if item_restrict_eval(i.output, restrict) and not (
          242  +						-- conditions which cause failure of restriction test
          243  +						(restrict.ipred and restrict.ipred {
          244  +							mod = module;
          245  +							infusion = i;
          246  +							output = i.output;
          247  +						} ~= true)
          248  +					) then t[#t+1] = i.output end
          249  +				end
          250  +				return select(2, sorcery.lib.tbl.pick(t))
          251  +			else
          252  +				return sorcery.register.infusions.db[math.random(#sorcery.register.infusions.db)].output
          253  +			end
   227    254   		end;
   228    255   		title = function(output)
   229    256   			for _,i in pairs(sorcery.register.infusions.db) do
   230    257   				if i.output == output then
   231    258   					if i._proto and i._proto.name
   232    259   						then return i._proto.name
   233    260   						else break end
................................................................................
   254    281   		name = 'Milling Guide';
   255    282   		node = 'sorcery:mill';
   256    283   		booksuf = 'Manual';
   257    284   		chance = 1;
   258    285   		w = 1, h = 2;
   259    286   		pick = function(restrict)
   260    287   			cache:populate_grindables()
   261         -			local i = cache.grindables[math.random(#cache.grindables)]
   262         -			local pd = sorcery.itemclass.get(i, 'grindable')
   263         -			return pd.powder
          288  +			if restrict then
          289  +				local t = {}
          290  +				for _, i in pairs(cache.grindables) do
          291  +					local pd = sorcery.itemclass.get(i, 'grindable')
          292  +					if item_restrict_eval(pd.powder, restrict) then
          293  +						t[#t+1] = pd.powder
          294  +					end
          295  +				end
          296  +				return select(2, sorcery.lib.tbl.pick(t))
          297  +			else
          298  +				local gd = cache.grindables[math.random(#cache.grindables)]
          299  +				local pd = sorcery.itemclass.get(gd, 'grindable')
          300  +				return pd.powder
          301  +			end
   264    302   		end;
   265    303   		props = props_builtin;
   266    304   		slots = {
   267    305   			{0,1},
   268    306   			{0,0};
   269    307   		};
   270    308   		find = function(out)
................................................................................
   400    438   		end
   401    439   		if kind == nil then -- oh well, we tried
   402    440   			local rks = sorcery.lib.tbl.keys(recipe_kinds)
   403    441   			kind = rks[math.random(#rks)]
   404    442   		end
   405    443   	end
   406    444   
          445  +	if not recipe_kinds[kind] then
          446  +		log.fatalf('attempted to pick recipe of unknown kind "%s"', kind)
          447  +	end
   407    448   	return recipe_kinds[kind].pick(restrict), kind
   408    449   end
   409    450   
   410    451   local render_recipe = function(kind,ingredients,result,notes_right)
   411    452   	local k = recipe_kinds[kind]
   412    453   	local t = ''
   413    454   	local props = k.props(result)
................................................................................
   464    505   	local ing = rec.find(out)
   465    506   	return render_recipe(kind,ing,out,notes_right), rec.w, rec.h
   466    507   end
   467    508   
   468    509   sorcery.cookbook.setrecipe = function(stack,k,r,restrict)
   469    510   	local meta = stack:get_meta()
   470    511   	if not r then r,k = sorcery.cookbook.pickrecipe(k,restrict) end
          512  +	if not r then return false end
   471    513   	local t = recipe_kinds[k]
   472    514   	meta:set_string('recipe_kind', k)
   473    515   	meta:set_string('recipe_name', r)
   474    516   	meta:set_string('description',
   475    517   		(t.title and t.title(r) or desc_builtin(r)) .. ' ' .. t.name)
   476    518   end
   477    519