-- =================================================================== local S if minetest.get_modpath ("intllib") then S = intllib.Getter() else S = function (s) return s end end -- =================================================================== unified_foods.obj_params = {} unified_foods.registered_items = {} unified_foods.drawtype = "sprite" local enable_log_food = false local disable_place_food = ocutil.bool_setting ("disable_place_food" ) or ocutil.bool_setting ("disable_placefood" ) if true then local str = minetest.setting_get ("ufoods_drawtype") if ocutil.str_nonempty (str) then if str == "mobs" then str = "mob" end if str == "sprites" then str = "sprite" end unified_foods.drawtype = str end end -- =================================================================== unified_foods.keep_juicer = { { "group:food_juicer" , "food:juicer" } , } -- =================================================================== unified_foods.keep_vessels = { { "group:bucket_milk" , "bucket:bucket_empty" } , { "group:bucket_milk" , "bucket:bucket_empty" } , { "group:bucket_water" , "bucket:bucket_empty" } , { "group:bucket_water" , "bucket:bucket_empty" } , { "group:cup_milk" , "food:cup" } , { "group:cup_milk" , "food:cup" } , { "group:choco_milk_cup" , "food:cup" } , { "group:choco_milk_cup" , "food:cup" } , { "group:choco_milk_mug" , "food:mug" } , { "group:choco_milk_mug" , "food:mug" } , { "group:food_glass" , "food:glass" } , { "group:food_glass" , "food:glass" } , } -- =================================================================== local mra = minetest.registered_aliases local mri = minetest.registered_items local reg_alias = ocutil.safe_register_alias local reg_craft = minetest.register_craft local reg_item = ocutil.safe_register_item local keep_vessels = unified_foods.keep_vessels local needitem -- =================================================================== local reg_food_panic = function (s) ocutil.panic ("register_food: " .. s) end -- =================================================================== local log_food = function (s) if enable_log_food then ocutil.log ("foodcore: " .. s) end end -- =================================================================== local eat_check = function (dmod) if ocutil.mod_exists (dmod) and (_G [dmod] ~= nil) then return true else return false end end -- =================================================================== unified_foods.item_eat = function (amt, use_rep, poison, heal, msg) if unified_foods.disable_hunger then return default.core_item_eat (amt, use_rep) end return unified_hunger.item_eat (amt, use_rep, poison, heal, msg) end -- =================================================================== minetest.item_eat = function (a, b) return unified_foods.item_eat (a, b) end -- =================================================================== unified_foods.final_item = function (n_int, external_items) if ocutil.thing_exists (n_int) then n_int = mra [n_int] or n_int return n_int, false end for _,value in ipairs (external_items) do value = mra [value] or value if ocutil.thing_exists (value) then minetest.register_alias (n_int, value) return value, false end end return n_int, true end -- =================================================================== --[[ 1. "register_food" is a flexible Unified Foods API routine that de- fines one type of food or utensil. The routine offers some unique and useful features. ---------------------------------------------------------------------- 2. "register_food" makes it possible for a world's food and hunger system to work consistently even if underlying mods are added or re- moved. This routine puts a thin layer on top of existing objects and fills in the cracks. If you specify a food or utensil that already exists in some external mod, this routine creates an alias in the "food:" namespace to that object. Otherwise, this routine creates a suitable node type in the "food:" namespace. ---------------------------------------------------------------------- 3. "register_food" merges similar objects. This is one of Unified Food's key features. Craft-items and nodes that are comparable to the specified object are modified so as to use the same description, image, and food parame- ters. This is done whether or not a new node type is created. So, for example, if there are hamburgers in three different mods that are conceptually the same, the hamburgers end up as more or less iden- tical objects. However, craft-items remain craft-items and nodes re- main nodes. The merge is done non-destructively; i.e., removal of Unified Foods should revert merged objects to their previous state. ---------------------------------------------------------------------- 4. Additional features: 4.1. Image files don't need to be specified except in special cases. "register_food" can find them automatically. Note: Some filename rules apply. 4.2. This routine sets a "food_..." group type automatically. It also creates an alias from a specified base-name to the fully-resolved final object that is used or created. These two features are discussed further at a later point. 4.3. These food characteristics are supported: satiation, replacement upon consumption, healing, and poison. 4.4. Fixed or random messages can be displayed upon consumption. 4.5. This routine can create regular craft-items, placeable craft- items, or placeable nodes as the caller prefers. The "drawtype" set- ting in the object parameters block is used to determine which it is: * A "drawtype" of "none" creates a regular, non-placeable, craft-item. * A "drawtype" of "allfaces", "plantlike", or "torchlike" causes a regular node with the specified drawtype to be created. * A "drawtype" of "sprite" causes a placeable craft-item to be crea- ted. If the craft-item is placed, it turns into a static 2D sprite that al- ways facing the player. This looks better, for many objects, then the other possible drawtypes. The sprite is created in the "ufsprites:" namespace. * A "drawtype" of "mob" creates a placeable craft-item similar to that produced by "sprite". However, if the craft-item is placed, it turns into a 2D mob as opposed to a static sprite. The mob is created in the "ufmobs:" namespace. * Different images can optionally be used for "inventory", "wield", node "tiles", and "sprite" purposes. By "sprite" purposes, we mean either stationary sprites (i.e., objects in the "ufsprites:" name space) or mobile sprites (i.e., objects in the "ufmobs:" namespace). ---------------------------------------------------------------------- 5. Three important rules: 5.1. New craft-items and/or placeable nodes are created only in cases where no existing objects are matched and merged into the "food:" namespace. 5.2. If a "food:" definition uses a "drawtype" setting of "mob" or "sprite", and pre-existing craft-items are merged into the "food:" namespace due to that definition, the pre-existing items will be con- verted to placeable. 5.3. "food:" "drawtype" settings shouldn't otherwise affect pre-exist- ing craft-items or nodes. So, for example, in this sample definition: reg_food ("cherry", { drawtype = "plantlike" , satiate = 2 , external_items = "coderfruit:cherry" , }) the "drawtype" setting of "plantlike" will have no effect if "coder- fruit:cherry" exists. In that event, "food:cherry" will be defined as an alias for "coder- fruit:cherry", and the latter object will be modified to use the Uni- fied Hunger system. However, it won't be redefined as a placeable node. A "drawtype" of "sprite", however, *will* redefine "coderfruit:cherry" as a placeable node. ---------------------------------------------------------------------- 6. A call to "register_food" can be as simple as this: local obj = register_food ("popsicle", { satiate=1 }) The preceding call creates a ready-to-use popsicle. An image file is required. "register_food" will look for the file. It must be stored in the Unified Foods "textures" directory and must have a name similar to: WORD_popsicle.png *or* WORD_popsicle.jpg Several values of WORD are supported. Examples include "farming", "food", "mtfoods", and "ufoods". "obj" is the fully-resolved name of the object that is used or cre- ated. The popsicle produced is added to the group "food_popsicle". The alias "popsicle" is mapped to "obj". "obj" can be used as the output of a crafting recipe. The following string can be used as one of the inputs to such a recipe: "group:food_popsicle" ---------------------------------------------------------------------- 7. "register_food" is called more generally as follows: local obj = register_food ("popsicle", { -- Optional. If this is omitted, it defaults to the base-name -- with the first letter mapped to upper case: -- description = "Popsicle" , -- Optional. These two settings default to true: -- autoalias = true , -- Create an alias autogroup = true , -- Create a group -- Optional. -- stack_max = 99 , -- Set "stack_max" for object -- "drawtype" is usually omitted. It should be "allfaces" if -- the image is square and without transparent parts. If you'd -- like to create a craft-item as opposed to a node, set this -- parameter to "none". -- drawtype = "allfaces" , -- The image to be used often doesn't need to be specified. -- Some rules apply. -- Food parameters. All of these are optional. If "satiate" is -- omitted, the object is treated as an inedible utensil as -- opposed to a food. -- satiate = 6 , -- Satiation effect heal = nil , -- Healing effect poison = nil , -- Poison effect -- Item left over after eating replace = "food:popsicle_stick" , } , { -- Extra groups (optional) vegan=1, snack=1 } , { -- Similar objects in other mods. The mods don't need to be -- installed. This list is optional, but it's recommended if -- similar objects exist. -- If there is one, and only one, item in this list, it may be -- passed to "register_food" as a string instead of a string -- entry in a table. "photon:popsicle" , "docsnacks:popsicle" }) ---------------------------------------------------------------------- 8. The value that "register_food" returns, "obj" in the preceding ex- ample, is the fully-resolved craft-item or node name for the new ob- ject that is created or the old one that is aliased to. This name can be, and often is, used as the output of one or more crafting recipes. ---------------------------------------------------------------------- 9. By default, this routine puts the result object in a group named "food_..." where "..." is the basename specified in the subroutine call. For example, the example in part 6 above will put the result object, regardless of its name, in the following group: food_popsicle=1 If extra groups are specified, as in the example, the object will go into those groups as well. If external object types are specified, as in the example, they'll go into the same groups. To disable the "food_..." group step for a particular object, specify this setting in the associated "register_food" call: autogroup=false ---------------------------------------------------------------------- 10. Object names returned by "register_food" shouldn't be used as in- puts in crafting recipes. Instead, the associated "food_..." groups should be used as inputs. For example: local obj = reg_food ("sushi", { description = "Sushi", satiate = 1, poison = 1 }) minetest.register_craft ({ type = "shapeless" , output = obj , recipe = { "group:food_fish_raw", "group:food_salt" } , }) ---------------------------------------------------------------------- 11. If "register_food" creates a new node, the drawtype used is "plantlike" by default. This can, and should, be changed to "allfaces" if the associated image is square and has no transparent parts. ---------------------------------------------------------------------- 12. By default, "register_food" creates an alias from the input base- name to the fully-resolved name of the craft-item or node that is cre- ated or used. To suppress this step for a given object, specify the following set- ting in the associated "register_food" call: autoalias = false ---------------------------------------------------------------------- 13. Image files must be stored in the Unified Foods "textures" direc- tory. This is required even though it may lead to redundant copies of exter- nal images. There are two reasons for the rule: * It simplifies the code * It improves the robustness of the food system ---------------------------------------------------------------------- 14. Image files may be specified as follows: image = ufoods_popsicle.png Transformations that create images on the fly may be used as well. For an example of a routine which does that, see "register.juice". If this setting is omitted for a particular object, "register_food" will look for the appropriate file. In this case, it must have a name similar to: WORD_BASENAME.png where BASENAME is the object basename specified in the "register_food" call. Several values of WORD are supported. Examples include "farming", "food", "mtfoods", and "ufoods". ---------------------------------------------------------------------- 15. As explained above, the optional 3rd parameter to "register_food" is a table that lists group settings for the target object that the routine is being called to define. A similar list may be specified, either additionally or instead, in the table that is passed to "register_food" as its 2nd parameter. The following syntax is used in this case: local obj = register_food ("popsicle", { ... // The list goes here extra_groups = { ... } , } , ... ---------------------------------------------------------------------- 16. As explained above, the optional 4th parameter to "register_food" is a table that lists external objects which are to be merged, if pos- sible, with the target object that the routine is being called to de- fine. A similar list may be specified, either additionally or instead, in the table that is passed to "register_food" as its 2nd parameter. The following syntax is used in this case: local obj = register_food ("popsicle", { ... // The list goes here external_items = { ... } , } , ... If there is one, and only one, item in the list, "external_items" may be set to that item as a string instead of a string entry in a tab- le. ---------------------------------------------------------------------- 17. By default, "register_food" uses the same image for "inventory", "wield", node "tiles", and "sprite" purposes. This is the image that is specified by "image =" in the parameters block or, if it isn't specified there, the image that the routine lo- cates using the image-file name rules explained in part 13 above. In some cases, the caller may prefer to use different images for dif- ferent purposes. For example, if the specified image shows an object at an angle, nodes will often look better if a horizontal version of the image is used for "tiles". ---------------------------------------------------------------------- To specify a different image for use in node "tiles", add a setting similar to the following to the table that is passed to "register_ food" as its 2nd parameter: tile = "ufoods_taco_horiz.png" or: tiles = "ufoods_taco_horiz.png" ---------------------------------------------------------------------- To specify a different image for use in "inventory" displays, use a setting similar to this one: inv = "ufoods_taco_horiz.png" or: inventory_image = "ufoods_taco_horiz.png" ---------------------------------------------------------------------- To specify a different image for use in "wield" displays, use a set- ting similar to this one: wield = "ufoods_taco_horiz.png" or: wield_image = "ufoods_taco_horiz.png" ---------------------------------------------------------------------- To specify a different image for use in "sprite" displays, use a set- ting similar to this one: sprite = "ufoods_taco_horiz.png" or: sprite_image = "ufoods_taco_horiz.png" ---------------------------------------------------------------------- If all four of the alternate image settings are specified, the "image" setting isn't relevant or checked. --]] -- =================================================================== local img_prefixes = { "bucket" , "coderfruit" , "codermobs" , "dessert" , "farming" , "food" , "misc" , "mobs" , "moono" , "mtfoods" , "ufoods" , } -- =================================================================== local null_use = function (itemstack, player, pointed_thing) return itemstack end -- =================================================================== local make_use = function (obj, ent_name, eat_use) local rec_item = minetest.registered_items [obj] local rec_node = minetest.registered_nodes [obj] local rec_ent = nil if rec_item == nil then reg_food_panic ("make_use: rec_item") end local on_use = rec_item.on_use local obj_eq = "make_use: obj=" .. obj if ent_name ~= nil then log_food (obj_eq .. ": ent_name=" .. ent_name) rec_ent = minetest.registered_entities [ent_name] else log_food (obj_eq .. ": ent_name=nil") end if on_use == nil then on_use = null_use end if eat_use ~= nil then log_food (obj_eq .. ": on_use = eat_use") on_use = eat_use end if rec_ent == nil or rec_node ~= nil then log_food (obj_eq .. ": return on_use") return on_use end log_food (obj_eq .. " : return function") return function (itemstack, player, pointed_thing) local pos = pointed_thing.under if pos ~= nil and not disable_place_food then pos.y = pos.y + 1 local obj = minetest.get_node (pos) if obj.name == "air" then local vs = rec_ent.visual_size if vs ~= nil then local sz = vs.y or 1 if sz >= 0.25 and sz < 1.00 then pos.y = pos.y - ((1 - sz) / 2) elseif sz > 1.00 and sz <= 3.00 then pos.y = pos.y + ((sz - 1) / 2) end end minetest.add_entity (pos, ent_name) itemstack:take_item() return itemstack end end return on_use (itemstack, player, pointed_thing) end end -- =================================================================== unified_foods.register_food = function (n_int, obj_params, extra_groups, external_items) -- =================================================================== local modname = unified_foods.modname local str -- =================================================================== if type (n_int) ~= "string" then reg_food_panic ("n_int isn't a string") end local orig_int= "orig_int=" .. n_int local basename = n_int:gsub ("^food:", "") if ocutil.str_contains (basename, ":") then reg_food_panic ("routine only supports food: objects") end n_int = "food:" .. basename log_food ("n_int=" .. n_int) -- =================================================================== if obj_params == nil then obj_params = {} end -- =================================================================== if type (external_items) == "string" then external_items = { external_items } end if external_items == nil then external_items = {} end str = obj_params.external_items if str ~= nil then if type (str) == "string" then str = { str } end for key, value in pairs (str) do external_items [key] = value end end -- =================================================================== if extra_groups == nil then extra_groups = {} end if obj_params.extra_groups ~= nil then for key, value in pairs (obj_params.extra_groups) do extra_groups [key] = value end end -- =================================================================== local autoalias = obj_params.autoalias local autogroup = obj_params.autogroup local description = obj_params.description local drawtype = obj_params.drawtype local image = obj_params.image local stack_max = obj_params.stack_max local satiate = obj_params.satiate local replace = obj_params.replace local poison = obj_params.poison local heal = obj_params.heal local msg = obj_params.msg local vsize = obj_params.vsize -- =================================================================== if autoalias == nil then autoalias = true end if autogroup == nil then autogroup = true end -- =================================================================== if drawtype == nil then drawtype = unified_foods.drawtype end if drawtype == "mobs" then drawtype = "mob" end if drawtype == "sprites" then drawtype = "sprite" end local sprite_prefix = "ufsprites:" if drawtype == "mob" then sprite_prefix = "ufmobs:" end -- =================================================================== if basename ~= nil then if ocutil.str_true (autogroup) then extra_groups ["food_" .. basename] = 1 end if ocutil.str_empty (description) then description = ocutil.first_to_upper (basename) end end -- =================================================================== if ocutil.str_empty (description) then reg_food_panic (n_int .. ": description not set") end -- =================================================================== local inv_image = obj_params.inv or obj_params.inventory_image if ocutil.str_empty (inv_image) then inv_image = nil else if not ocutil.str_contains (inv_image, "%[") and not ocutil.mod_image_exists (modname, inv_image) then reg_food_panic ("Specified image isn't in " .. "unified_foods/textures: " .. inv_image) end end -- =================================================================== local tiles = obj_params.tile or obj_params.tiles if ocutil.str_empty (tiles) then tiles = nil else if not ocutil.str_contains (tiles, "%[") and not ocutil.mod_image_exists (modname, tiles) then reg_food_panic ("Specified image isn't in " .. "unified_foods/textures: " .. tiles) end end -- =================================================================== local wield_image = obj_params.wield or obj_params.wield_image if ocutil.str_empty (wield_image) then wield_image = nil else if not ocutil.str_contains (wield_image, "%[") and not ocutil.mod_image_exists (modname, wield_image) then reg_food_panic ("Specified image isn't in " .. "unified_foods/textures: " .. wield_image) end end -- =================================================================== local sprite_image = obj_params.sprite or obj_params.sprite_image if ocutil.str_empty (sprite_image) then sprite_image = nil else if not ocutil.str_contains (sprite_image, "%[") and not ocutil.mod_image_exists (modname, sprite_image) then reg_food_panic ("Specified image isn't in " .. "unified_foods/textures: " .. sprite_image) end end -- =================================================================== local need_image = true if inv_image ~= nil and tiles ~= nil and wield_image ~= nil and sprite_image ~= nil then need_image = false end -- =================================================================== if ocutil.str_empty (image) then image = nil elseif need_image then if not ocutil.str_contains (image, "%[") and not ocutil.mod_image_exists (modname, image) then reg_food_panic ("Specified image isn't in " .. "unified_foods/textures: " .. image) end end -- =================================================================== for _, prefix in ipairs (img_prefixes) do if (not need_image) or (image ~= nil) then break end local img_test log_food ("need image for: " .. basename) img_test = prefix .. "_" .. basename .. ".png" if ocutil.mod_image_exists (modname, img_test) then log_food ("image exists: " .. img_test) image = img_test break end img_test = prefix .. "_" .. basename .. ".jpg" if ocutil.mod_image_exists (modname, img_test) then log_food ("image exists: " .. img_test) image = img_test break end end -- =================================================================== if need_image then if image == nil then reg_food_panic ("Didn't find image matching " .. basename .. " in mod " .. modname) end if inv_image == nil then inv_image = image end if tiles == nil then tiles = image end if wield_image == nil then wield_image = image end if sprite_image == nil then sprite_image = image end end -- =================================================================== local is_eat = true if ocutil.str_empty (satiate) then log_food (orig_int .. ": empty satiate") is_eat = false if ocutil.str_nonempty (replace) or ocutil.str_nonempty (poison ) or ocutil.str_nonempty (heal ) or ocutil.str_nonempty (msg ) then reg_food_panic ("Invalid item_eat settings") end else log_food (orig_int .. ": non-empty satiate") -- e.g. orig_int=taco: non-empty satiate if ocutil.str_empty (replace) then replace = nil end if ocutil.str_empty (poison ) then poison = nil end if ocutil.str_empty (heal ) then heal = nil end if ocutil.str_empty (msg ) then msg = nil end end -- =================================================================== if is_eat and type (replace) == "string" and ocutil.str_nonempty (replace) and ocutil.thing_missing (replace) then local drinking_glasses = { "farming:drinking_cup" , "food:glass_empty" , "vessels:drinking_glass" , } local is_glass = false local rep_rep = nil for _, otype in ipairs (drinking_glasses) do if rep_rep == nil and ocutil.thing_exists (otype) then rep_rep = otype end if replace == otype then is_glass = true end end if is_glass then replace = rep_rep end if ocutil.thing_missing (replace) then replace = nil end end -- =================================================================== local needfunc n_int, needfunc = unified_foods.final_item (n_int, external_items) log_food (orig_int .. ": final n_int=" .. n_int) -- =================================================================== local eat_use = nil if is_eat then log_food (orig_int .. ": is_eat") -- e.g.: orig_int=taco: is_eat local ep = {} ep.satiate = satiate ep.replace = replace ep.poison = poison ep.heal = heal ep.msg = msg unified_foods.obj_params [n_int] = ep eat_use = unified_foods.item_eat (satiate, replace, poison, heal, msg) else log_food (orig_int .. ": not is_eat") end -- =================================================================== local sprite_name log_food (orig_int .. ": drawtype=" .. drawtype) -- e.g. orig_int=taco: drawtype=none if drawtype == "mob" or drawtype == "sprite" then sprite_name = sprite_prefix .. basename log_food (orig_int .. ": sprite_name=" .. sprite_name) if needfunc or (minetest.registered_items [n_int] ~= nil and minetest.registered_nodes [n_int] == nil) then unified_foods.register_mob (basename, sprite_image, vsize) unified_foods.register_sprite (basename, sprite_image, vsize) end else log_food (orig_int .. ": delete mobs and sprites") -- e.g. orig_int=taco: delete mobs and sprites local prefixes = { "ufmobs", "ufsprites" } for _, prefix in ipairs (prefixes) do local entity_name = prefix .. ":" .. basename minetest.register_entity (":" .. entity_name, { on_activate = function (self) self.object:remove() end }) end end -- =================================================================== if needfunc then if drawtype == "none" or drawtype == "mob" or drawtype == "sprite" then log_food (orig_int .. ": reg_item: n_int=" .. n_int) -- e.g. orig_int=taco: reg_item: n_int=food:taco reg_item (n_int, { description = description , inventory_image = inv_image , }) else log_food (orig_int .. ": reg_node: n_int=" .. n_int) minetest.register_node (":" .. n_int, { description = description , drawtype = drawtype , tiles = { tiles } , inventory_image = inv_image , wield_image = wield_image , paramtype = "light" , walkable = false , is_ground_content = true , sunlight_propagates = true , groups = { oddly_breakable_by_hand=3, dig_immediate=3, } , selection_box = { type = "fixed" , fixed = { -0.25, -0.25, -0.25, 0.25, 0.25, 0.25 } , } , }) end else log_food (orig_int .. ": " .. basename .. " becomes " .. n_int) end -- =================================================================== local base_items = {} for _, name in ipairs (external_items) do base_items [name] = 1 end base_items [n_int] = 1 -- =================================================================== for obj, _ in pairs (base_items) do local oo = orig_int .. ": obj=" .. obj log_food (oo .. ": overloop 01") unified_foods.registered_items [obj] = 1 obj = mra [obj] or obj unified_foods.registered_items [obj] = 1 obj = mra [obj] or obj unified_foods.registered_items [obj] = 1 log_food (oo .. ": overloop 02: new obj=" .. obj) -- e.g. orig_int=taco: obj=food:taco: -- overloop 02: new obj=food:taco if ocutil.thing_exists (obj) then ocutil.add_item_groups (obj, extra_groups) local oparams = { description = S(description) , inventory_image = inv_image , wield_image = wield_image , } log_food (oo .. ": overloop 03: setting on_use") -- e.g. orig_int=taco: obj=food:taco: -- overloop 03: setting on_use oparams.on_use = make_use (obj, sprite_name, eat_use) if ocutil.str_nonempty (stack_max) then oparams.stack_max = stack_max end local mri_entry = mri [obj] if (mri_entry.drawtype ~= nil) and (mri_entry.drawtype == "torchlike" or mri_entry.drawtype == "plantlike") and mri_entry.tiles ~= nil and type (mri_entry.tiles) == "table" and #mri_entry.tiles == 1 then mri_entry.tiles = { tiles } end log_food (oo .. ": overloop 04: override: " .. obj) -- e.g. orig_int=taco: obj=food:taco: -- overloop 04: override: food:taco minetest.override_item (obj, oparams) else log_food (oo .. ": overloop 05: doesn't exist: " .. obj) end end -- =================================================================== if ocutil.str_true (autoalias) and basename ~= nil then reg_alias (basename, n_int) end return n_int end -- =================================================================== unified_foods.color_drink = function (color) color = color:gsub ("^#", "") return "ufoods_glass_milk.png^[colorize:#" .. color .. ":255^ufoods_glass_empty.png" end -- =================================================================== --[[ 1. "register_juice" is a wrapper for "register_food" which is used to create glasses of different types of juice. This routine offers two important features: * It can optionally generate juice images on the fly * It generates appropriate crafting recipes 2. This routine is called as follows: local obj = register_juice ("potato") *or* local obj = register_juice ("potato", { description = "Potato Juice" , satiate = 3 , color = "#A87D5D" , need_count = 1 , } , { -- Optional "somemod:potato_juice" } The 1st argument is the basename of a "food:" object that is to be juiced. 3a. If there are no other arguments, this routine searches for an im- age file with a name similar to: ufoods_glass_potato_juice.png The actual basename should be substituted for "potato" both here and below. The image file should be a modified copy of either of the following two files: ufoods_glass_empty.png ufoods_glass_milk.png This routine creates an appropriate juice using the image file and de- fault parameters. 3b. If there are two arguments, and the 2nd one is a table, it's structured the same way as the 2nd argument to "register_food", but with the following changes: * "description" defaults to something similar to "Potato Juice" * "image" defaults to the type of string shown in part 3a above * "satiate" defaults to 1 * Two new parameters "color" and "name_count" are supported "color" can be set to a hex color string of the form "#123456". If this is done, and the image file described in part 3a doesn't exist, "register_juice" creates an appropriate juice image on the fly. The juice has the specified color. By default, "register_juice" creates a shapeless crafting recipe for the specified juice. The recipe takes these inputs: "group:food_juicer" "group:food_glass" "group:food_potato" One of each is required. Note: Substitute the appropriate basename for "potato". If "need_count" is set to zero, the crafting recipe is suppressed. If it's set to an integer from 1 to 7, the specified number of copies of the 3rd input are required. Note that the inputs must be placed on separate squares in the craft- ing grid; i.e., a stack won't work. 3c. If there are three arguments, the 2nd is as described in part 3b above and the 3rd is structured the same way as the last argument to "register_food". I.e., the 3rd argument is either a single object name, as a string, or a table that contains a list of object names. 3d. The juice defined is placed in the following group: food_potato_juice=1 "potato_juice" is aliased to the fully-resolved name of the object that is created or used. Substitute the appropriate basename for "potato". --]] -- =================================================================== unified_foods.register_juice = function (lcname, args, external_items) -- ------------------------------------------------------------------- if args == nil then args = {} end if external_items == nil then external_items = {} end if type (args) ~= "table" then ocutil.panic ("register_juice: arg #2 isn't a table") end args = ocutil.clone_table (args) -- ------------------------------------------------------------------- local ucname = ocutil.first_to_upper (lcname) local lcpair = lcname .. "_juice" local item_name = "food:" .. lcpair if args.description == nil then args.description = ucname .. " Juice" end if args.satiate == nil then args.satiate = 1 end args.replace = "food:glass" -- ------------------------------------------------------------------- local groups = {} groups ["food_" .. lcpair] = 1 -- ------------------------------------------------------------------- local image = "ufoods_glass_" .. lcpair .. ".png" if ocutil.mod_image_missing (unified_foods.modname, image) then if args.color ~= nil then image = unified_foods.color_drink (args.color) else image = "ufoods_glass_generic_juice.png" end end args.image = image -- ------------------------------------------------------------------- needitem = unified_foods.register_food (item_name, args, groups, external_items) -- ------------------------------------------------------------------- local obj = "group:food_" .. lcname local need_count = args.need_count if ocutil.str_empty (need_count) then need_count = 1 end if need_count < 0 then need_count = 0 end if need_count > 7 then need_count = 7 end if need_count > 0 then local inputs = { "group:food_juicer", "group:food_glass" } for ii = 1, need_count do table.insert (inputs, obj) end reg_craft ({ type = "shapeless" , output = needitem , recipe = inputs , replacements = unified_foods.keep_juicer , }) end -- ------------------------------------------------------------------- reg_alias (lcpair , needitem) reg_alias (lcname .. "juice" , needitem) return needitem end -- =================================================================== -- End of file.